0%

=========

关于打印 印刷 冲印。

打印复印、印刷、冲印。
https://zhidao.baidu.com/question/25154682.html
打印不需要模版。 印刷需要一个模版。

打印、印刷用的是CMYK模式。显示器等 设备用RGB模式。
RGB是加色模式,CMYK是减色模式 。RGB模式是一种发光的色彩模式 , CMYK是一种依靠反光的色彩模式 。
RGB的原理是光源发出光到⼈眼(即加⾊原理),在RGB显示屏上是适⽤的(然⽽不是所有的显示屏都是
RGB的)。但凡是涉及到印刷,将图案放置在纸张、布料等物体上,它适⽤的原理就会变成物体反射光到
⼈眼(即减⾊原理)。
https://www.zhihu.com/question/20476536

==========

与 或 非。在数字电路中的表示,门电路。与门,或门,非门。
门电路是数字电路中最基本的逻辑单元。https://zhuanlan.zhihu.com/p/395540201

电路(电子电路):模拟电路 和 数字电路。
https://www.eefocus.com/analog-power/465165
https://zhuanlan.zhihu.com/p/166110092

常见的电子元器件。 工作原理,功能以及作用,具体应用。

电阻,电容,电感器,二极管,三极管,变压器,继电器,开关 等等。
二极管:PN结,单向导电性。 P positive,N negative。 这里是指正 负电荷。N型,因为多了自由电子,对外显负电。P型,多了空穴,对外显正电。
单质硅是不导电的,要让其导电,加入了P,或 N。
N型: Si+P。 多了一个电子,自由移动的载流子, 形成电流。电子流出,负极N极。 电子是多数载流子,空穴 是少数载流子。
P型: Si+B。 少一个电子,空穴,(相当于正电粒子),吸引电子流动,形成电流。电子流入,正极P极。空穴是多数载流子,电子是少数载流子。
要导电,就要电子和空穴复合。
三极管: 发射极,基极,集电极。 发射区,基区,集电区。 电流从基极流向发射极。从集电极流向发射极。
NPN型。 两个PN结。

电子负电荷。 电子移动方向 与 电流方向相反。
正负极 指电流的正负极。
正负电荷 指粒子是正/负电荷。
粒子的正负 是电荷的正负。正电荷 负电荷。

物理上规定电流的方向,是正电荷定向运动的方向(即正电荷定向运动的速度的正方向或负电荷定向运动的速度的反方向)。电流运动方向与电子运动方向相反。
电荷指的是自由电荷,在金属导体中的自由电荷是自由电子,在酸,碱,盐的水溶液中是正离子和负离子。

我们一般所说的电流,指的是正电荷的流向,但实际上正电荷是不会动的,真正会动的是“自由移动的电子”,但电子是带负电的,从“电源的负极”流出,和我们平常所言的“电流从正极流出”正好相反。

物体传导电流的能力叫做导电性,非电解质物体导电的能力是由其原子外层自由电子数以及其晶体结构决定的,比如同样是碳单质,石墨导电,金刚石不导电。
硅单质被称为半导体,是因为硅的导电性是变化的。
https://www.zhihu.com/question/303408616

半导体是指导电能力介于金属和绝缘体之间的固体材料。

正极 负极,根据电势高低。电势高 正极, 电势低 负极。

电池的正极 负极。

电流方向。

电子运动方向。

粒子带电(正负电荷) ,不带电(中性)。
电子 带负电荷。
原子核

物质,分子,原子(原子核,电子)。
原子核:质子(正电荷),中子(不带电)。
质子、中子、电子是构成原子的三种基本粒子。
电荷是粒子的基本性质。带正电荷 带负电荷 不带电。

电池的原理是 原电池, 充电的时候是电解池。

升失氧(氧化反应,被氧化,还原剂),降得还(还原反应,被还原,氧化剂)。

升价 失去电子 氧化反应。

降价 得到电子 还原反应。

正极负极。(电池。电流方向/电势高低,电子方向)
阴极阳极。(电解池,原电池。阳极 氧化反应 吸引负离子, 阴极 还原反应 吸引阳离子。)

氧化还原反应(氧化反应,还原反应):(从最底层电子层面的得失来一步步推导 记忆)
失升氧(失去电子 升价 氧化反应)。充当还原剂,具有还原性,发生氧化反应,得到氧化产物。
得降还(得到电子 降价 还原反应)。充当氧化剂,具有氧化性,发生还原反应,得到还原反应。
利用氧气助记(氧气是氧化剂): 比如,氧气和铁 反应。 氧气和铁 反应。
(h2+o2=h2o。 其中氧气 得到电子,降价,发生还原反应。 是充当氧化剂,具有氧化性。 氧气发生还原反应,得到还原产物 h2o。 氢气 失去电子,升价,发生氧化反应。 是充当还原剂,具有还原性。 氢气发生氧化反应,得到氧化产物h2o。)

百科:https://baike.baidu.com/item/%E6%B0%A7%E5%8C%96%E5%89%82/2520415
在氧化还原反应中,获得电子的物质称作氧化剂 [1] ,与此对应,失去电子的物质称作还原剂。狭义地说,氧化剂又可以指可以使另一物质得到氧的物质,以此类推,氟化剂是可以使物质得到氟的物质,氯化剂、溴化剂等亦然。
(注:这两种定义有不同,前者强调电子的得失,后者则强调氧元素的得失。根据前者定义,一些物质,如二氟化氙是强氧化剂,而根据后者定义,则为氟化剂。本词条主要描述前者。)
含有容易得到电子元素的物质,即氧化性强的物质常用氧化剂。

氧化剂是在氧化还原反应中,获得电子的物质。氧化剂具有氧化性,得到电子化合价降低,发生还原反应,得到还原产物。

=============

邮件

收取邮件一般是客户端主动行为,而不是服务端行为。(其实很多时候都是客户端主动,服务端被动。除非是一直保持连接,才能服务端主动。) 客户端不断去服务端取邮件,这样看过去像服务端主动发过来的,这样看过去也像实时收到。其实后面都是客户端在不断向服务端发送请求的,一直在循环loop。
亦或客户端和服务端一直保持连接,通过类似心跳包一直保持连接,那么这时服务端就可以主动发送邮件给服务端的。 另外,邮件并不是像IM那样实时的,所以也不必维持时刻的连接。一般服务端和客户端 要一直维持连接,那么也是需要类似 客户端那样不断发送心跳包 来维持连接的(一直保持也很耗资源)。 并没有啥都不发送就能一直维持连接的,因为一个连接最多只能维持一段时间,无法一直维持的。 在邮件这里,也是同样的道理。 另外,一般都是客户端主动行为,很少服务端一开始就主动行为的。

代码中发送邮件,那么肯定需要一个邮箱地址,而这个邮箱地址要给服务器鉴权用的。那么就需要某个stmp服务器才能发送(鉴权以及发送其他smtp服务器)。这个服务器可以用三方的如qq 163,也可以用自己写的stmp服务器或linux的mail(不过很大程度上会被拒收) 。
所以代码中并不是只要有收件人的邮箱地址就行的,要有我们收件人的邮箱地址以及该邮箱地址的stmp服务器 才行。 我们客户端是要通过服务端发送邮件,而不是单单客户端就能发送邮件的。

代码中实际上 1.用发送方用自己的stmp服务器发邮件,2.也可以用市场上第三方stmp服务器的。 (直接食用stmp服务器进行发送,不需要发送方的邮件地址和鉴权,直接用stmp服务端发送的)
但基本用的还是第三方,而不是用自己的stmp服务器。
为什么用第三方的stmp服务器。因为如果用自己的stmp服务器发送邮件,可能会被对方的stmp服务器拒绝(虽然stmp服务器之间不需要什么鉴权,不过有的商用的stmp服务器会拒绝一些奇怪domain的stmp服务器发件,因为有垃圾邮件等),因为市场常用的stmp服务器(如QQ 网易等),都会对不信任的domain的stmp服务器拒绝的。所以我们一般用的是市场上第三方stmp服务器进行发送。
如果用第三方的stmp服务器那么可能需要第三方stmp服务器的用户名,密码或者鉴权码。
具体可以见 ~/lxr_Code/gitHub/pythonDemo/email

==========

python函数参数,将类 ,类的实例作为参数传入。 python中的函数的参数可以是任何类型,函数,类, 实例, 一般类型的数据。
https://blog.csdn.net/qq_27403925/article/details/105418916

==========

android 四大组件

android 四大组件 Activity, Service,ContentProvider,Broadcast。
Intent

==========

获取系统设置

在linux/android中,获取系统设置,1.读取文件/配置文件 2.使用api获取。 (很多时候读取文件都能获取。如果获取不到或者api更方便,才会用api。 其实很多软件的设置等也是从配置文件/数据等去处理的)

操作系统中 多线程/多进程。

多进程/多线程 状态以及状态转换: 新建,就绪,运行,阻塞,死亡/终止。
进程的五个状态,其实也可以用在线程上。
就绪和阻塞都是进程线程停止工作,暂停状态,不再运行。
就绪表明进程线程有使用cpu的资格,需要等待调度。也叫可运行状态。可运行状态 表明线程可执行的所有条件都满足了(比如锁等),只要等cpu调度运行就可以。
阻塞表明完全没有使用cpu的资格。

一般说的线程 睡眠,休眠,挂起,等待 等等 都是指进程/线程 从运行状态进入非运行状态,可能是就绪或阻塞(比如时间片用完,挂起,这是指进入就绪状态的)。不过一般都是进入阻塞状态的。 (并没有进入死亡状态的)。
线程终止,是指进入终止/死亡状态。
一般进程线程sleep是进入就阻塞状态。时间到,转为就绪,等待调度。 yield是直接进入就绪状态。
平时编程时,其实说的线程阻塞,等待等,是笼统的说线程停止状态,不严格的区分,没有去细分就绪还是阻塞,也就是说细分的话,两种都有可能,只是将两者都笼统放在一起使用,反正线程不再工作,停止状态。具体代码中就能明显区分了。

多线程的 同步、互斥 操作。
理论:
P/V 操作 (semwait/semsignal 操作)。 操作信号量。

信号量可用于同步 互斥操作。
当信号量值为1(二元信号量) 的时候,可用做互斥。 大于1,可用做同步。
互斥是常用的操作,除了信号量,还有专门的互斥量/互斥锁/锁 用于做互斥。(锁等价于二元信号量)

其实信号量 完全可以用 锁+条件变量+额外的变量 来实现。

一般用于同步:信号量,条件变量(要配合锁)。
一般用于互斥:锁。 二元信号量。
(锁。 二元信号量。互斥操作 也能完成一些同步操作的。)

P/V 完成 同步 或 互斥。

具体实践:
Linux c:
互斥量操作
pthread_mutex_lock pthread_mutex_unlock
pthread_cond_wait pthread_cond_signal (条件变量要配合二元信号量使用)
pthread_cond_wait 阻塞当前线程,并且释放当前线程拥有的锁。
pthread_cond_signal 唤醒在该条件变量的阻塞线程。 将其放入原来锁的竞争队列中去。这时唤醒的那个线程要和其他线程对该锁进行竞争。 只有竞争成功,才能从条件变量阻塞处接着往下运行。 即条件变量唤醒的线程 是处于就绪状态,要等待os的调度的。
pthread_join
信号量操作
sem_wait sem_post

Java:
互斥:synchronized。 lock unlock。 (这些互斥 也可以完成一些同步的操作。)
同步:wait notify。 配合一些变量。 (这些同步 也会有一些互斥的效果。) (类似于C中条件变量的wait signal)
LockSupport.park, LockSupport.unpack (类似一个二元信号量,一般用于同步,因为都是自身线程pack,由其他线程unpack,所以一般是用做同步)
其他:
join。yield。

多线程 同步 互斥过程中可能出现的问题。
死锁,饥饿,

代码Demo。

加锁 进入阻塞状态。

获得锁,进入就绪状态,等待调度。调度得到cpu资格,进入运行状态。

yield 直接进入就绪状态。 等待调度。

wait 释放拥有的锁,并进入阻塞状态。 wait要配合锁来使用的。只能在有拥有某个锁的线程中对某个锁进行wait。

notify 唤醒因条件变量阻塞的线程,进入

sleep 进入阻塞状态,时间到,进入就绪状态,等待调度。并没有释放拥有锁。

join 进入阻塞状态,等其他线程结束。

实践中,五种的状态还是比较笼统,一般还会将阻塞状态细分。
等待阻塞/Waiting,同步阻塞/Blocked,其他阻塞/Timed_Waiting。
等待阻塞: wait操作,释放拥有的锁,并进入阻塞状态。 notify后 或者 时间到后,进入 同步阻塞(要去竞争锁)。
同步阻塞在获的锁后,进入就绪状态。
其他阻塞:比如sleep(进入睡眠状态),join等。没有释放锁,进入阻塞状态。 时间到,进入就绪状态。
比如像Java中的线程状态就比较细致。
JAVA中的状态:
New、Runnable、Blocked、Waiting、Timed_Waiting和Terminated.
其中locked、Waiting、Timed_Waiting 都是阻塞状态,对应着上面的三种阻塞。

wait(1000) //释放锁吗? 如果释放锁,那么锁被其他线程占去之后,一直不还,而线程的时间又到了,怎么办?
会释放锁。 时间到或者notify 之后 进入同步阻塞状态,去争夺锁。

https://www.jianshu.com/p/e2b22c6bcd22
interrupt 中断。并不是完全让线程结束变为terminated,是否变为terminated由程序员决定。程序员在run中判断Thread.interrupted()状态。
某个线程被调用interupt,
如果处于运行状态,只是将设置interrupt的状态,具体是停止还是怎样由 程序员写的代码决定。
如果处于阻塞状态,那么该线程会抛出InterruptedException,同时将状态转为下一个状态。

LockSupport.park() LockSupport.unpark()。 类似于二元信号量。 用做同步。 park 休眠线程/挂起线程->进入阻塞状态。 不释放拥有的锁。

Java 状态转换。

Java 多线程相关API。

参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1304521607217185

Java 代码Demo。
1.线程的创建。

知道理论原理。
知道具体实践。具体实践和理论的互相映照。 api 以及具体使用 场景。
知道具体实践的 底层实现原理。

汇编 推荐两本书:
《X86汇编 从实模式到保护模式》
《汇编语言(第3版) 》王爽著

实模式:
https://blog.csdn.net/zzzzzec/article/details/121311995

笔记:
ROM 程序固化到ROM的。
对于PC的主板而言,BIOS/UEFI 就是固化到ROM里的,是固件。 以前是不可擦写的,现在也是可编程 可擦写的。 即可以刷机新的BIOS或升级BIOS到ROM的。
计算机启动的时候,会先读取BIOS,完成硬件的自检和初始化。然后BIOS将权限交由启动的硬盘或光盘等。运行硬盘中的MBR/GPT。 MBR再去启动OS。 (我们安装的OS是安装到硬盘上,并且设置MBR)
PC中的bootloader是MBR/GPT 中的grub/grub2。
嵌入式中的bootloader(固件) 作用相当于PC中的 BIOS+MBR。也有做硬件自检。

MBR中记录 开机启动程序/开机管理程序。 有grub,grub2,LILO 等。

1. 载入 BIOS 的硬件信息与进行自我测试,并依据设置取得第一个可开机的设备;
2. 读取并执行第一个开机设备内 MBR 的 boot Loader ( 亦即是 grub2, spfdisk 等程序) ;
3. 依据 boot loader 的设置载入 Kernel ,Kernel 会开始侦测硬件与载入驱动程序;
4. 在硬件驱动成功后,Kernel 会主动调用 systemd 程序,并以 default.target 流程开机;
systemd 执行 sysinit.target 初始化系统及 basic.target 准备操作系统;
systemd 启动 multi-user.target 下的本机与服务器服务;
systemd 执行 multi-user.target 下的 /etc/rc.d/rc.local 文件;
systemd 执行 multi-user.target 下的 getty.target 及登陆服务;
systemd 执行 graphical 需要的服务

存储分类:https://blog.csdn.net/vincent3678/article/details/122226578
(内/主存+外/辅存) (pc:内存 + 硬盘)(手机:运存+内存/闪存 (说法乱而已,其实还是 内+外))

CPU可用的内存空间,不仅仅是常规的内存(由内存条提供,RAM,掉电易失),还有BIOS(ROM,不易失),显卡等。

从内存空间去理解计算机和操作系统。因为cpu所有的指令 数据都要放在内存空间中才能处理。 冯诺依曼体系结构中,cpu所有的数据 指令都要从内存空间中取得的。核心就是CPU和内存。
如果要想知道程序如何load到内存,如何被cpu执行, 学习汇编是很好的选择,因为汇编能更好体现这些底层。

一段程序 逻辑上 分为 堆段,代码段,栈段,数据段,BSS段。
虚拟内存, 物理内存。

如何让计算机启动的时候执行我们的代码?
实模式。
我们知道, 8086 可以访问 1MB 内存。其中,0x00000~9FFFF 属于常规内存,由内存条提供;0xF0000~0xFFFFF
由主板上的一个芯片提供,即ROM-BIOS。中间还有一个320KB 的空洞,即0xA0000~0xEFFFF。
传统上,这段地址空间由特定的外围设备来提供,其中就包括显卡。

我们知道,计算机启动的时候,将ROM中的BIOS的代码加载到内存中(0XF0000),然后BIOS进行自检后,会将硬盘的MBR代码加载到内存地址0x7c00,并jmp到该地址,从而运行MBR代码,之后MBR再执行操作系统的代码。
MBR是硬盘上的硬盘的0面0道1扇区。512B。 别小看512B,它足够处理操作系统的boot。它可以选择启动哪个os。将os启动的代码载入内存某个地址,cpu并跳到该内存地址,开始运行os启动代码。
所以,如果我们要启动的执行我们的代码,我们应该将自己的代码编译后放入硬盘的第一个512B,代替MBR。

地址 [地址] 表示取该地址中的值
立即数
8086 寄存器:8个通用寄存器(AX,BX,CX,DX,SI,DI,BP,SP), 6个段寄存器(CS,DS,SS,ES,FS,GS), 程序寄存器(IP),标志寄存器(FLAGS)
以上都是16位的,32位的寄存器在前面加E。
https://zhuanlan.zhihu.com/p/366550341
https://blog.csdn.net/weixin_44519342/article/details/123690618

指令:MOV JMP
(不同体系的CPU中的寄存器,指令等也是不一样的。)
MOV指令无法直接将立即数移动到段寄存器,只能经过通用寄存器来做。
也无法将段寄存器移动到段寄存器,只能通过通用寄存器来做。

每个指令都会对应相应的机器指令。

JMP指令会改变CS, IP https://blog.csdn.net/woxueliuyun/article/details/2033359

div中溢出的问题,https://blog.csdn.net/u010196648/article/details/25067179

第一种类型是用16 位的二进制数除以8 位的二进制数。在这种情况
下,被除数必须在寄存器AX 中,必须事先传送到AX 寄存器里。除数可
以由8 位的通用寄存器或者内存单元提供。指令执行后,商在寄存器AL
中,余数在寄存器AH 中。

第二种类型是用32 位的二进制数除以16 位的二进制数。在这种情况
下,因为16 位的处理器无法直接提供32 位的被除数,故要求被除数的
高16 位在DX 中,低16 位在AX 中 。同时,除数可以由16 位的通用寄存器或者内存单元提供,指令执行
后,商在AX 中,余数在DX 中。

XOR 指令

add 指令需要两个操作数,目的操作数可以是8 位或者16 位的通用
寄存器,或者指向8 位或者16 位实际操作数的内存地址;源操作数可以
是相同数据宽度的8 位或者16 位通用寄存器、指向8 位或者16 位实际操
作数的内存地址,或者立即数,但不允许两个操作数同时为内存单元。
相加后,结果保存在目的操作数中

处理器取指令、执行指令是依赖于段寄存器CS 和指令指针寄存器IP
的,8086 处理器取指令时,把CS 的内容左移4 位,加上IP 的内容,形
成20 位的物理地址,取得指令,然后执行,同时把IP 的内容加上当前指
令的长度,以指向下一条指令的偏移地址。

jmp 指令具有多种格式.
相对近转移。 JMP near inif
绝对地址. JMP 0x5000:0xf0c0

伪指令times 可用于重复它后面的指令若干次

times 20 mov ax,bx

bochs:
https://bochs.sourceforge.io/
https://bochs.sourceforge.io/doc/docbook/user/faq.html
https://blog.csdn.net/weixin_47656385/article/details/120624117
具体实用可参考书第五章。

movsb 和movsw 指令执行时,原始数据串的段地址由DS 指定,偏
移地址由SI 指定,简写为DS:SI;要传送到的目的地址由ES:DI 指定;传
送的字节数(movsb)或者字数(movsw)由CX指定。除此之外,还要
指定是正向传送还是反向传送,正向传送是指传送操作的方向是从内存
区域的低地址端到高地址端;反向传送则正好相反。正向传送时,每传
送一个字节(movsb)或者一个字(movsw),SI 和DI 加1 或者加2;
反向传送时,每传送一个字节(movsb)或者一个字(movsw)时,SI
和DI 减去1 或者减去2。不管是正向传送还是反向传送,也不管每次传送
的是字节还是字,每传送一次,CX 的内容自动减。

cld 指令将DF 标志清零,以指示传送是正
方向的。和cld 功能相反的是std 指令,它将DF标志置位(1)。此时,
传送的方向是从高地址到低地址

需要加上指令前缀rep(repeat),意思是CX 不为零则重复。
rep movsw 的操作码是0xF3 0xA5,它将重复执行movsw 直到CX 的内
容为零。

loop 指令的功能是重复执行一段相同的代码,处理器在执行它的时
候会顺序做两件事:cx减1。 判断cx是否为0,不为0 loop。

加载位置的改变不会对处理器执行指令造成任何困扰,但会给数据访问
带来麻烦。要知道,当前
数据段寄存器DS 的内容是0x0000,因此,number 的偏移地址实际上是
0x012E+0x7C00=0x7D2E。当正在执行的指令仍然用0x012E 来访问数
据,灾难就发生了。

取指令,取数据。逻辑地址,物理地址。(逻辑地址到物理地址要靠基址。)
对于取指令基址在CS,对于取数据基址在DS。
CS:IP
DS:偏移地址

地址,取地址(从该地址中取出数据)

内存 物理地址 = SA *16 + EA。 SA段地址, EA偏移地址/有效地址 Effective address。 Offset Address。

SA和EA 称为逻辑地址。
物理地址。 逻辑地址。 段地址, 偏移地址/有效地址。

在8086 处理器上,如果要用寄存器来提供偏移地址,只能使用BX、
SI、DI、BP,不能使用其他寄存器。
原因很简单,寄存器BX 最初的功能之一就是用来提供数据访问的基
地址,所以又叫基址寄存器(Base Address Register)。之所以不能用
SP、IP、AX、CX、DX,这是一种硬性规定,说不上有什么特别的理
由。而且,在设计8086 处理器时,每个寄存器都有自己的特殊用途,比
如AX是累加器(Accumulator),与它有关的指令还会做指令长度上的
优化(较短);CX 是计数器(Counter);DX 是数据(Data)寄存
器,除了作为通用寄存器使用外,还专门用于和外设之间进行数据传
送;SI 是源索引寄存器( Source Index);DI 是目标索引寄存器
( Destination Index),用于数据传送操作,我们已经在 movsb 和
movsw 指令的用法中领略过了。

inc 是加一指令,操作数可以是8
位或者16 位的寄存器,也可以是字节或者字内存单元。从功能上讲,它
和 add bx, 1
是一样的,但前者的机器码更短,速度更快.
和inc 指令相对的是dec 指令,用于将目标操作数的内容减一,它们
的指令格式相同,不再赘述.

neg 指令带有一个操作数。它的功能很简单,用0 减去指令中指定的操作数。 (就是取相反数)。

很显然,一个8 位的有符号数,要想用16 位的形式来表示,只需将
其最高位,也就是用来辨别符号的那一位(几乎所有的书上都称之为符
号位,实际上这并不严谨),扩展到高8 位即可。
为了方便,处理器专门
设 计 了 两 条 指 令 来 做 这 件 事 : cbw ( Convert Byte to Word ) 和
cwd(Convert Word to Double-word)。
cbw 没有操作数,操作码为98。它的功能是,将寄存器AL 中的有符
号数扩展到整个AX。举个例子,如果AL 中的内容为01001111,那么执
行该指令后,AX 中的内容为0000000001001111;如果AL 中的内容为
10001101,执行该指令后,AX 中的内容为1111111110001101。
cwd 也没有操作数,操作码为99。它的功能是,将寄存器AX 中的有
符 号 数 扩 展 到 DX:AX 。 举 个 例 子 , 如 果 AX 中 的 内 容 为
0100111101111001 , 那 么 执 行 该 指 令 后 , DX 中 的 内 容 为
0000000000000000 , AX 中 的 内 容 不 变 ; 如 果 AX 中 的 内 容 为
1000110110001011 , 那 么 执 行 该 指 令 后 , DX 中 的 内 容 为
1111111111111111,AX 中的内容同样不变。
尽管有符号数的最高位通常称为符号位,但并不意味着它仅仅用来
表示正负号。事实上,通过上面的讲述和实例可以看出,它既是数的一
部分,和其他比特一起共同表示数的大小,同时又用来判断数的正负。

主动权在你自己手上,在写程序的时候,你要做什么,什么目的,
你自己最清楚。如果是无符号数计算,必须使用div 指令;如果你是在做
有符号数计算,就应当使用idiv 指令

bx 也叫基址寄存器。存放某个地址 做为基址,相当于数组0开始的位置。索引SI,bx+si。
SI 的作用相当于索引,因此它被称为索引寄存器(Index Register),或者叫变址寄存器。
另一个常用的变址寄存器是DI。
注意,INTEL8086 处理器只允许以下几种基址寄存器和变址寄存器
的组合:

[bx+si]
[bx+di]
[bp+si]
[bp+di]

这些组合可以用于任何带有内存操作数的指令中。其他任何组合,
比如[bx+ax]、[cx+dx]、[ax+cx]等等,都是非法的

指令jns show 的意思是,如果未设置符号位,则转
移到标号“show”所在的位置处执行。如图6-2 所示,Intel 处理器的标志
寄存器里有符号位SF(Sign Flag),很多算术逻辑运算都会影响到该
位,比如这里的dec 指令。如果计算结果的最高位是比特“0”,处理器把
SF 位置“0”,否则SF 位置“1”。

jns 是条件转移指令,处理器在执行它的时候要参考标志寄存器的SF
位。除了只是在符合条件的时候才转移之外,它和jmp 指令很相似,它
也是相对转移指令,编译后的机器指令操作数也是一个相对偏移量,是
用标号处的汇编地址减去当前指令的汇编地址,再减去当前指令的长度
得到的。

在处理器内进行的很多算术逻辑运算,都会影响到标志寄存器的某
些位。比如我们已经学过的加法指令add、逻辑运算指令xor 等.

奇偶标志位PF
当运算结果出来后,如果最低8 位中,有偶数个为1 的比特,则
PF=1;否则PF=0.

进位标志CF
当处理器进行算术操作时,如果最高位有向前进位或借位的情况发
生,则CF=1;否则CF=0.
CF 标志始终忠实地记录进位或者借位是否发生,但少数指令除外
(如inc 和dec).
加1指令 INC指令功能:目标操作数+1INC指令只有1个操作数,它将指定的操作数的内容加1,再将结果送回到该操作数。INC指令将影响SF,AF,ZF,PF,OF标志位,但是不影响CF标志位。INC指令的操作数的类型可以是通用寄存器或存储单元,但不可以是段寄存器。字或字节操作均可。对于存储单元,需要用BYTE PTR或者WORD PTR说明是字节还是字操作。
为什么不影响CF:链接

OF,该标志的意思是,假定你进行的是有符号数运算,如果运算结果是
正确的,那么OF=0,否则OF=1。比如上面的例子,因为从有符号数的
角度来看,是-1 和2 相加,结果为1,未溢出,故OF=0。简单地说,OF
标志用于指示两个有符号数的运算结果是否错误。

指令对标志位的影响:

“jcc”不是一条指令,而是一个指令族(簇),功能是根据某些条件
进行转移,比如前面讲过的jns,意思是SF≠1(那就是SF=0 了)则转
移.
转移指令必须出现在影响标志的指令之后.
在汇编语言源代码里,条件转移指令的操作数是标号。编译成机器
码后,操作数是一个立即数,是相对于目标指令的偏移量。在16 位处理
器上,偏移量可以是8 位(短转移)或者16 位(相对近转移)

NASM 编译器提供了一个标记“$”,该标记等同于标号,你
可以把它看成是一个隐藏在当前行行首的标号。因此,jmp near $的意思
是,转移到当前指令继续执行。
$是当前行的汇编地址;$$是NASM 编译器提供的另一个标记,代
表当前汇编节(段)的起始汇编地址。

中断:

  • 外部中断 / 硬件中断
    • 可屏蔽中断
    • 不可屏蔽中断
  • 内部中断 / 软件中断 (不可屏蔽)
    • 主动去中断:指令中断
    • 被动去中断:硬件故障(除了硬件中断)、软件中断。

中断信号的来源,或者说,产生中断的设备,称为中断源.

种类型的中断都被统一编号,这称为中断类型号、中断向量或者中断号.

但是,由于不可屏蔽中断的特殊性——几乎所有触发NMI 的事
件对处理器来说都是致命的,甚至是不可纠正的。在这种情况下,努力
去搞清楚发生了什么,通常没有太大的意义,这样的事最好留到事后,
让专业维修人员来做。
也正是这个原因,在实模式下,NMI 被赋予了统一的中断号2,不再
进行细分。一旦发生2号中断,处理器和软件系统通常会放弃继续正常工
作的“念头”,也不会试图纠正已经发生的问题和错误,很可能只是由软件
系统给出一个提示信息。

和代码段、数据段和附加段一样,栈
也被定义成一个内存段,叫栈段(Stack Segment),由段寄存器SS 指
向。
针对栈的操作有两种,分别是将数据推进栈(push)和从栈中弹出
数据(pop)。简单地说,就是压栈和出栈。压栈和出栈只能在一端进
行,所以需要用栈指针寄存器SP (Stack Pointer)来指示下一个数据应
当压入栈内的什么位置,或者数据从哪里出栈。
定义栈需要两个连续的步骤,即初始化段寄存器SS 和栈指针SP 的
内容。源程序第40~42 行用于将栈段的段地址设置为0x0000,栈指针的
内容设置为0x0000

处理器内部,or 指令的目的操作数可以是8 位或者16 位的通用寄
存器,或者包含8/16位实际操作数的内存单元,源操作数可以是与目的
操作数数据宽度相同的通用寄存器、内存单元或者立即数

在16位的处理器上,push 指令的操作数可以是16 位的寄存器或者内存单元

处理器在执行push 指令时,首先将栈指针寄存器SP 的内容减去操
作数的字长(以字节为单位的长度,在16 位处理器上是2),然后,把
要压入栈的数据存放到逻辑地址SS:SP 所指向的内存位置(和其他段的
读写一样,把栈段寄存器SS 的内容左移4 位,加上栈指针寄存器SP 提
供的偏移地址)

pop 指令执行时,处理器将栈段寄存器SS 的内容左移4 位,再加上
栈指针寄存器SP 的内容,形成20 位的物理地址访问内存,取得所需的
数据。然后,将SP 的内容加操作数的字长,以指向下一个栈位置

地址, 取地址 ([],从内存的该地址中取出数据)。

在实模式的汇编中,
汇编编译器中的汇编地址。
逻辑地址的形式是: 段地址:偏移地址。
物理地址=段地址×10H+偏移地址

8086处理器的寻址方式
寄存器寻址
立即寻址
内存寻址:直接寻址,基址寻址,变址寻址,基址变址寻址。(根据偏移地址提供者的不同形式划分)
内存寻址,默认都是DS做段地址,除非显示的表示段超越前缀。

直接寻址。
mov [es:lable], 0x05
目的操作数使用了标号和段超越前缀,但它依然属于直接寻址方式。原因很简单,标号是数值的等价形式,在指令
编译阶段,会被转换成数值;而段超越前缀仅仅用来改变默认的数据段。

mov [bx],dx
基址寻址。bx, bp. 在指令执行时,处理器将数据段寄存器DS 的内容左移4 位,加上基址寄存器BX 中的内容,形成20 位的物理地址。然后,把寄存器DX中的内容传送到该地址处的字单元里。

mov [di],dx
di, si.
变址寻址类似于基址寻址,唯一不同之处在于这种寻址方式使用的是变址寄存器(或称索引寄存器)SI 和DI.和基址寻址一样,当带有这种操作数的指令执行时,除非使用了段超越前缀,处理器会访问由段寄存器DS 指向的数据段,偏移地址由寄存器SI 或者DI 提供。
同样地,变址寻址方式也允许带一个偏移量. mov [si+0x100],al.

使用基址变址的操作数可以使用一个基址寄存器(BX 或者BP),外加一个变址寄存器(SI 或者DI)。它的基本形式是这样的, mov ax,[bx+si].
当处理器执行这条指令时,把数据段寄存器DS 的内容左移4 位,加上基址寄存器BX
的内容,再加上变址寄存器SI 的内容,共同形成20 位的物理地址

超越前缀, 不同汇编编译器,不同的语法。
nasm中 [cs:di], 都放在[]中。
masm中 cs:[di].
注意不同的编译器 会导致一些语法的不同,要区分。https://blog.csdn.net/cainiaohhf/article/details/9916749

标号, 变量名。
实际上都是内存地址。 要取变量的值(变量指示地址中的值)要 [变量],而变量表示的是内存地址的.

操作系统通常肩负着处理器管理、内存分配、程序加载、进程(即
已经位于内存中的程序)调度、外围设备(显卡、硬盘、声卡等)的控
制和管理等任务

处理器的工作模式是将内存分成逻辑上的段,指令的获取和数据的
访问一律按“段地址:偏移地址”的方式进行。相对应地,一个规范的程
序,应当包括代码段、数据段、附加段和栈段。这样一来,段的划分和
段与段之间的界限在程序加载到内存之前就已经准备好了。

NASM 编译器不关心段的用途,可能也根本不知道段的用途,不知
道它是数据段,还是代码段,或是栈段。事实上,这都不重要,段只用
来分隔程序中的不同内容。
不过,话又说回来了,作为程序员,每个段的用途,你自己是清楚
的。所以,为每个段起一个直观好记的名字,那是应该的。如图8-1 所
示,第一个段的名字是“header”,表明它是整个程序的开头部分;第二个
段的名字是“code”,表明这是代码段;第三个段的名字是“data”,表明这
是数据段。
比较重要的是,一旦定义段,那么,后面的内容就都属于该段,除
非又出现了另一个段的定义。另外,如图8-2 所示,有时候,程序并不以
段定义语句开始。在这种情况下,这些内容默认地自成一个段。最为典
型的情况是,整个程序中都没有段定义语句。这时,整个程序自成一个
段。
NASM 对段的数量没有限制。一些大的程序,可能拥有不止一个代
码段和数据段。

逻辑右移 shr, shl。
逻辑右移指令执行时,会将操作数连续地向右移动指定的次数,每移动一次,“挤”出来的比特被移到标志寄存器的CF 位,左边空出来的位置用比特“0”填充

循环右移 ror, rol
循环右移指令执行时,每右移一次,移出的比特既送到标志寄存器的CF 位,也送进左边空出的位

ret retf
https://zhuanlan.zhihu.com/p/372398363

=============

正数,负数。
二进制。原码,反码,补码。
正数: 原码=反码=补码。
负数:原码,是正数的原码 最高位置1 。 反码,除符号位 按位取反。 补码,反码+1。
规定最高位为符号位,表示正负。

https://www.23bei.com/tool/56.html

内存中的二进制,1.实际上是补码,用补码去理解。 2.用 负 = 0-正 理解。
我们说的负数的二进制 实际上都是指 它的补码。 正数的二进制都可以(因为都一样)
1.实际上是补码,用补码去理解:
5
原 反 补
0101 0101 0101
-5
1101 1010 1011

7
0111 0111 0111
-7
1111 1000 1001

2.用 负 = 0-正 理解。
-5
0-5
0000
0101
1011

-7
0-7
0000
0111
1001

得出的实际也是负数的补码。也能表明出最高位1时是负数,所以和我们规定的原反补都是自洽的。 也可以再反推出 反码, 原码。
利用方式2可以快速算出负数的二进制(补码)。比方式1快,方式1要先算出原码 反码,最后算出补码。

  • 如果系统本身是按照有符号系统处理,那么可以确定二进制的正负。 如果本身是无符号,那么就全是正。
  • 如果系统本身同时支持有符号和无符号,那么在处理的时候 要特别指定是有符号 还是无符号,这样才能确定正负。
    一般系统都是同时支持的那种。因此 处理的时候是 需要去指定的。

我们人也算是同时支持有符号和无符号的。因此 处理数字时也是要 指定的(指定有符号 还是无符号)。而我们默认是指定为按照有符号的。另外也有可视化符号表示。
对于十进制,5->+5, -5。
对于二进制,1001->+1001, -1001.
如果没有可视化符号表示,像在计算机中表示的那样,那么前提也是要主动申明是哪种 有符号,还是无符号。
我们人 默认是有符号。 或者处理时 有可视化,是有指定了正负(属于有符号)。
5 /+5
-5
+1001
-1001

一般计算机也是同时支持有符号和无符号的。
对于计算机中的表示,并没有可视化符号去表示,因此要主动去指定是有符号还是符号。
1001 指定有符号,是负数。指定为无符号,是正数。

总结:数

  • 有符号。 (正数 负数 之分,规定最高位为符号位)
  • 无符号。 (全为正数)
  1. 如果本身系统就是有符号,或者 无符号, 那么就按系统指定的去解读。
  2. 如果本身系统同时支持 有符号 ,无符号。那么,就要有表明其是有符号 还是 无符号 的声明或指示。 如果没有明确指示,那么可以有两种不同的解读。对于同一个数,可以有两种解读。按照有符号解读 一种, 无符号的解读 一种
    1. 有可视化的指示。比如可视化的+ -, 这就表明是用有符号的。
    2. 或者有其他的声明。声明是有符号或者无符号,比如 signed int, unsigned int。

人类系统 是同时支持有符号和无符号。 除非有声明 是无符号,否则都是有符号。
而且人类默认是可视化表示,所以显示的是有符号。5或+5, -5。 对于5,没有特别声明是无符号,那么就是有符号,而且是正的,即+5。

可参考印象笔记中《计算机组成原理》。

字节序。
数据 在书写系统 和 内存 存放/表示。 有大端,小端。

  • 书写表示的时候,实际上 大端字节序。 (我们默认左边到右边 位序增大,高位在低地址,所以是大端)。 基本都是大端。
  • 内存 默认也是 左边到右边 位序增大。 数据在内存中,数据的低位在低地址,小端。 数据的高位在高地址,大端。 不同cpu 有不同的字节序。
    • 如果是大端,优点:和书写/表示 系统一致,人感官直觉上 比较自然,缺点:但是cpu处理起来麻烦,处理起来不自然。
    • 如果小端,优点:cpu处理起来自然,逻辑上舒服。 缺点:书写表示时给人感官直觉上 比较麻烦。

================

以下 关于 操作系统启动流程。 文件系统。

文件: 文件大小(文件的实际大小), 文件占的磁盘空间大小。

磁盘: 见《x86汇编语言从实模式到保护模式》4.1.4章节。
磁盘,
从物理角度看, 最小存储单位是 扇区, 512B/4KB 。
0 面0 道1 扇区,或者说是0 头0 柱1 扇区。
从文件系统角度看: 最小存储单位是block,1KB,2KB,4KB。 (inode,superblock等都是存在block里)
inode 128B,256B.

0 lrwxrwxrwx 1 root root 29 12月 6 16:00 resolv.conf -> ../run/resolvconf/resolv.conf
链接的block大小是0,因为只占用inode,并不占用block。

vbox 与宿主 设置共享文件夹。 linux中如果设置挂载点,那么会挂载到那个挂载点。 如果没有设置,那么挂载到 /media/sf_xxx下。
linux中无法直接用当前用户去访问挂载点。 可以在当前用户下 sudo mount –types vboxsf xxx mount_fs/
xxx 是设置共享文件夹时取的名称。 mount_fs是虚拟机中某个目录。
https://www.cnblogs.com/oddcat/articles/9685003.html
https://blog.csdn.net/danshiming/article/details/117997558

grub 可以识别 文件系统。ext2 ext4等。

linux内核启动的时候有一个 根文件系统, 然后才加在文件系统。

linux 中的根文件系统:
Initramfs, 为了映射 路径名到具体文件。从路径名访问到文件。

文件系统。 文件系统格式 ext2 ext4, fat ntfs, hfs。
文件系统:文件的树组织形式。 文件从路径名到物理磁盘文件的映射。

根文件系统: 可以是虚拟文件系统(内存中的),也可以是实际文件系统。 根文件系统,是可以访问/目录的。 不是涉及文件系统格式。 比如Initramfs 是根文件系统, 在加载磁盘文件上的文件系统后,将Initramfs替换后的文件系统,也是根文件系统。
根文件系统的文件系统格式是具体而定的。 而且 根文件系统 的下的目录结构、目录名都有相应的标准规定。

linux内核加载的时候,先启动Initramfs,使得可以通过文件路径名直接在内存中访问必要的文件等,当加载了必要的磁盘驱动等,就可以加载磁盘设备上的文件系统了,就替换掉之前的Initramfs的文件系统。

开机时候的文件系统:
开机的时候, grub启动 stage1 无法识别文件系统 , stage1.5 stage2 可以识别文件系统,然后启动内核,将整个控制权交由内核,grub不再接管。而内核此时无法识别文件系统,因此会有一个虚拟的根文件系统,在加载了必要的磁盘驱动等,就可以加载磁盘设备上的文件系统了,就替换掉之前的Initramfs的文件系统。

开机流程/系统启动流程:
加电启动
-> cpu读取内存空间中地址0处(一般是固化到ROM里的BIOS),执行BIOS里的代码,进行开机硬件检测等。 检测ok,cpu会将启动设备(硬盘) 里的0面0道1扇区的MBR代码载入到内存的0x7c00处,并且将执行地址跳转到0x7c00执行。这时,基本BIOS结束,将操作交由MBR。
-> 执行MBR中的bootloader,Linux下的MBR中的bootloader一般为grub。grub stage1, (stage1.5,)stage2。 stage1 下是无法识别文件系统的,在1.5 2 才可以识别文件系统。 做了一些处理后,载入 /boot下的内核文件(因为可以识别文件系统,因此可以找到/boot下的内核映像文件)
->加载内核(内核文件/boot/vmlinuxxxxx),启动内核。这时bootloader基本结束,操作交由内核了,即交给os了。内核加载时,为了能处理init服务,路径形式,那么需要加载文件系统(grub已经不在了,而此时内核又没有文件系统,无法访问路径形式的文件),所以 此时内核会先加载的虚拟的根文件系统(/boot/initramfs,这个在grub阶段加载进内存了。然后这个文件会被解压缩并且在内存当中仿真成一个根目录。相应的目录下的文件因为在内存中有相应的加载,因此可以通过路径来访问相应的文件,相当于是一个文件系统。这个文件解压缩后和我们正常目录下的文件时一样的,这个只是在内核启动时加载虚拟文件系统时用到,解压,将里面的文件加载到内存中,从而执行.这个文件实际上就是那些必要文件的压缩),这样就能找到必须的服务和模块,在加载了必要的磁盘驱动等,就可以加载磁盘设备上的文件系统了,就替换掉之前的Initramfs的文件系统,真正的文件系统就加载完成了。 这时基本内核加载差不多了。
->启动第一个进程,进城号为1 的 init 进程,后续必要进程启动,处理相应的配置文件等(如rc.local等)
-> 系统的用户登陆界面。

(grub2 stage1.5后 和 加载完的os 都能识别磁盘上的文件系统)

UEFI读取GPT表,然后在相应的分区中读取.efi文件(bootloader),控制权就交由分区中的bootloader了,bootloader再加载操作系统内核。
BIOS的是要先读取硬盘的MBR,根据MBR中的bootloader,要么加载相应分区中的内核文件,要么交由各自分区开头的bootloader处理。
菜单一:MBR( grub2) –> kernel file –> booting
菜单二:MBR( grub2) –> boot sector( Windows loader) –> Windows kernel –>
booting
菜单三:MBR( grub2) –> boot sector( grub2) –> kernel file –> booting
而最终 boot loader 的功能就是“载入 kernel 文件”啦!

内核/OS 启动流程, 也是重要的一环。

https://www.crybit.com/linux-boot-process/
https://zhuanlan.zhihu.com/p/392858237
https://blog.csdn.net/billbonaparte1/article/details/82629176
https://blog.csdn.net/zinnc/article/details/105026631

磁盘物理结构。
磁盘的MBR,分区结构。
文件系统格式。 文件的逻辑结构 对应 到磁盘物理结构。 文件通过 路径名形式 映射到磁盘物理结构。
开机流程。BIOS/UEFI, MBR/GPT,bootloader。等等。

开机流程简化版:
1.电源键启动,2.cpu读取内存地址0处代码(BIOS),BIOS功能 硬件自检等以及启动顺序设置(u盘 硬盘 光驱 网络等),3.从启动的硬盘/u盘 0面0道1扇区 读取mbr或gpt (分区表),执行mbr里面的bootloader。 4.在bootloader中选择进入的操作统分区启动系统。 4.操作系统的启动。

总结:
BIOS, UEFI : 固化到ROM的固件。 硬件启动时 加载到内存空间地址0处,并运行的第一个程序。
MBR,GPT: 是用于分区的分区表。 只是MBR中有446bytes用于存储bootloader(如grub)(MBR中的bootloader也可能是只是部分的bootloader)。 GPT并没有存储bootloader,bootloader是在各自分区中的.efi文件。
每个分区的文件系统。NFTS,ext4,fat32,exfat等等。

每个硬盘 都有一个(0个或1个) 分区表 MBR/GPT。 分区表是以硬盘为基础建立的,而不是以每个分区。
用U盘启动盘软件对其写入引导后把启动文件考进去就变成启动盘。 U盘此时也有建立了MBR或GPT的。
U盘启动方式,其中 安装的引导程序,算是bootloader吧。通过启动项选择U盘启动。启动时进入U盘,再通过U盘的引导程序(算是bootloader)进入其他系统。

Windows

Android

Macos

  • 菜单栏/状态栏软件
    • Hidden Bar
    • iStat Menus
    • Paste
    • MenuBarX
  • 软件
    • Mos
    • Jitouch
    • 键指如飞: (显示当前app的快捷键)
    • 自动切换输入法
    • iShot

Chrome插件

  • videospeed
  • OneTab
  • Google 翻译
  • Tampermonkey
    • 网盘助手

Here's something encrypted, password is required to continue reading.
阅读全文 »

Here's something encrypted, password is required to continue reading.
阅读全文 »

之前就了解过正向代理和反向代理, 这两天突然又搞不清楚了。看来还是没有真的了解正向代理和反向代理。

代理

代理,中介,委托。字面意思就是帮别人做事。原理是多了中间方。本来双方直接联系,现在不直接联系,变成了代理/中介和某一方联系。
好了,中文的意思就是上面的简单解释了。 在计算机中,很多地方都会用到代理,比如:

  • 在设计模式中有 代理模式/委托模式。
  • 服务器中的代理服务器。有 正向代理,反向代理。
  • 网络攻击中的中间人攻击,实际上也能算代理。

今天要说的就是 正向代理和反向代理。

正向代理。用过科学上网的都知道,那个服务器就是一个正向代理服务器。
反向代理。用过nginx的应该比较熟悉,nginx一大特色就是支持反向代理。

我为什么之前了解了,现在又糊涂了。主要也是因为名词的不理解。正向 反向 其实 和方向没有关系,和数据流动没关系。正是这样的翻译,让人比较迷惑和误会。 正向代理 反向代理 都是代理。 都是代理的一种表现方式。它们主要是看给谁做代理。这个正和反是从客户端的角度来区分。从客户端角度来看,正向代理,就是给客户端做代理。 反向代理,就是給服务器做代理(即对客户端来说反过来给服务器做代理)。

正向代理 反向代理 都是代理。 都是代理的一种表现方式。区分它们的关键是,看它给谁做代理。这个正和反是从客户端的角度来区分。从客户端角度来看,正向代理,就是给客户端做代理。 反向代理,就是給服务器做代理(即对客户端来说,是反过来给服务器做代理)。

  • 在没有代理情况下,客户端和服务端是直接通讯的。
  • 正向代理。 客户端请了代理/中介,由中介和服务端通讯。中介代表了客户端。可以看成客户端和中介是一伙的,服务端是另一伙。
  • 反向代理。 服务端请了代理/中介, 由中介和客户端通讯。中介代表了服务端。可以看成服务端和中介是一伙的,客户端是另一伙。
![找不到图片时显示的文字](imgs/20220414_1.jpeg)

正向代理的运用:

  • vpn的使用。
  • 中间人攻击。
  • 设计模式中 代理模式/中介模式/委托模式。

反向代理的运用:

  • nginx的负载均衡。负载均衡的原理就是反向代理。
  • 内网传统。ngrok。原理也是反向代理。

正向代理的用途:

  • 对服务端隐藏客户端。 服务端只知道中介。
  • 突破访问限制。 如VPN。

方向代理用途:

  • 对客户端隐藏服务端。 客户端只知道中介。
  • 负载均衡。

看到一篇很通俗的解释,链接

正向代理和反向代理的区别
虽然正向代理服务器和反向代理服务器所处的位置都是客户端和真实服务器之间,所做的事情也都是把客户端的请求转发给服务器,再把服务器的响应转发给客户端,但是二者之间还是有一定的差异的。
1、正向代理其实是客户端的代理,帮助客户端访问其无法访问的服务器资源。反向代理则是服务器的代理,帮助服务器做负载均衡,安全防护等。
2、正向代理一般是客户端架设的,比如在自己的机器上安装一个代理软件。而反向代理一般是服务器架设的,比如在自己的机器集群中部署一个反向代理服务器。
3、正向代理中,服务器不知道真正的客户端到底是谁,以为访问自己的就是真实的客户端。而在反向代理中,客户端不知道真正的服务器是谁,以为自己访问的就是真实的服务器。
4、正向代理和反向代理的作用和目的不同。正向代理主要是用来解决访问限制问题。而反向代理则是提供负载均衡、安全防护等作用。二者均能提高访问速度。

1

用电脑的都知道enter键是回车键,实际上应该叫回车换行键才准确,因为作用不仅仅是回车,还有换行的作用。今天说一说回车、换行的那些事。

这一切要从古早的电传打字机说起。当我们在电传打字机上打完一行字时,那么就要进行两个操作,回车和换行。
回车让打字机的打印头回到起始位置。 换行让打印头往下移动一行。观看视频

回车 CR。Carriage return。 Carriage是打字机的滑杠。但是它也有马车的意思,所以翻译成回车。
换行 LR。Line feed。字面意思 喂了一行,含义就是换行。
回车 CR,ASCII值是0x0D,13, 转义字符是\r。 (return)
换行 LF,ASCII值是0x0A,10, 转义字符是\n。 (new line)

2

到了计算机时代,沿袭了打字机的概念。
回车 光标回到行首 不换行。 换行 光标移动到下一行 不回到行首。
那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以,用一个字符来完成两个操作。于是,就出现了分歧。
unix 中,用\n 完成 回车和换行 的功能(虽然\n还叫回车,但完成了回车和换行)。 \r还是仅仅的回车,无换行。
macos 中,用\r 完成 回车和换行 的功能。 不过现在macos也转向了unix方式了。
windows中,维持传统,\r\n 才是回车和换行。 \r仅仅是回车,\n仅仅是换行。
(另外,注意, 在网络协议中还是用\r\n表示回车换行,比如http协议中头和数据之间的换行就是\r\n)

一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号,即多余的\r就用^M表示出来。(之所以显示为^M是因为Linux下一般用^表示Ctrl键,而Ctrl+M表示回车,可以在命令行里试试)

另一个后果 就是编程上的兼容性问题。
比如C语言对于文件中回车换行的处理。C标准库为了统一文件的回车换行,可以使用文本模式。
打开文件的方式分为两种:二进制模式和文本模式。
对于二进制模式,写入\r \n 原样写入, 读出\r \n 也是原样读出。
对于文本模式, 分系统。 对于windows,写入\n,会转成\r\n, 读出\r\n会转成 \n. 对于linux/macos, 写入\n,还是转成\n, 读出\n会转成\n(linux/unix/mac 下文本模式和二进制模式都一样的,都等同于二进制模式)。虽然在系统层面不一样,但是在c的层面统一了。 文本模式其实就是 在中间 加了一层,做了兼容处理。 (很多时候计算机问题,都能往上加一层后,解决问题。比如网络的七层模型等)
所以对于文本模式,实现回车 换行,统一使用\n。 对于二进制模式,还是要分系统分析,要做跨平台的处理。 对于C标准库中的标准输入 标准输出 标准错误 默认是文本模式的,因此printf(“\n”)在各个系统都是回车换行。

3

虽然我们日常只说 回车 或者 换行 或者 enter,但是实际都是指 回车和换行,即回到行首,并到下一行。

4

参考:
https://www.ruanyifeng.com/blog/2006/04/post_213.html
https://zhuanlan.zhihu.com/p/479064200

5 附录

在c中如何控制回车,换行,以及光标的移动。
参考:https://blog.csdn.net/yuhai738639/article/details/79221835
以下标准输入输出 其实都是在文本模式下。

  • 仅仅回车,未换行:
    #include <stdio.h>
    #include <unistd.h> 
    int main(){
    	for(int i = 0; i < 100; i++){
    		printf("process %4d \r", i); //回车 未换行。
    		fflush(stdout);//强制刷新缓存,输出显示
    		// usleep(200);
    		sleep(1);
    
    	}
    	return 0;
    }
  • 仅仅换行,不回车
    无。
  • 回车换行:(虽然\n还是叫回车,但是完成了回车和换行操作)
    \n
更多的参考可以 查看 笔记 C语言。

教程

菜鸟教程

语法

  • 正则:匹配(核心,基础(其他的功能都是在匹配基础上的)), 提取。

  • 一般我们要处理的 输入 都是字符串形式的。

  • 正则表达式也是以字符串形式,也叫模式串,规则串。
    (输入串中只要有部分 匹配 模式串的,那么就属于匹配,true,如果连部分都没匹配,就是不匹配,false)

    • 原生的正则表达式: 字符串形式 ‘/pattern/flags’.
      模式串包裹在//中。
      pattern的元字符: 普通字符,非打印字符(用转义表示),特殊字符,限定符,定位符。 语法

元字符的完整列表以及它们在正则表达式上下文中的行为:语法2

flag,是标志/修饰符,正则表达式的标记用于指定额外的匹配策略。有g i m s。 语法3

注意事项

  • 正则在不同环境下有不同的方言。 要注意区别。

    • 有的正则表达式是 放在//里面的,如”/^(abc)(bcd)/g” g是修饰符/标记符 表示全局匹配。 放在//里的也是原生的正则表达式的语法。
    • 有的直接开始 “^(abc)(bcd)”,修饰符在其他地方设置。
  • 输入的字符串形式有单行,多行(含\n)。

  • 正则表达式的单行模式 和 多行模式, /pattern/g, /pattern/gm。
    多行模式 只是影响到 ^ $ 定位符的作用。如果没有^ $ 那么单行模式和多行模式没什么区别。

    • 对于正则表达式为单行模式,将输入的字符串(不管单行还是多行) 都以整体去处理。 ^ $ 定位整体的开头和结尾。
    • 对于正则表达式为多行模式的,多行模式下会改变^和$的含义【^和$是匹配整个字符串的开头和结尾】,使它在任意一行的行首和行尾进行匹配,即每行每行处理。 如果没有^$那么会以所有行整体处理,不是以行为单位的一行一行处理。
    • 注意,正则中的. 无法匹配\r \n。如果要做多行/跨行匹配,见下面讨论。多行/跨行匹配和 单行模式 多行模式没有关系,不同的概念。
        <script>
      function myFunction(){
      	var str="runoobgoogle\ntaobao\nrunoobweibo";
          var n1=str.match(/^runoob/g);   // 匹配一个 
          var n2=str.match(/^runoob/gm);  // 多行匹配
      	document.getElementById("demo1").innerHTML=n1; //runoob
      	document.getElementById("demo2").innerHTML=n2; //runoob,runoob
      }
      </script>
  <script>
function myFunction(){
	var str="runoobgoogle\ntaobao\nrunoobweibo";
    var n1=str.match(/runoob/g);   
    var n2=str.match(/runoob/gm); 
	document.getElementById("demo1").innerHTML=n1; //runoob,runoob
	document.getElementById("demo2").innerHTML=n2; //runoob,runoob
}
</script>
  • 跨行/多行匹配问题。
    和正则表达式的单行模式 多行模式 没有必然关系。 参考
    .不能匹配换行,\r和\n。(不匹配回车和换行)
    解决跨行匹配问题:主要就是要解决\n或\r的匹配。

    • 使用s修饰符。 /pattern/s。
    • 把 . 改为 (?:.|\n)
      参考
      function myFunction(){
      	var str='123\n\rabcbcd';
          var n1=str.match(/123.*/g);  
      	alert(n1); // ==> 123
      }
      
      function myFunction(){
      	var str='123\nabcbcd';
          var n1=str.match(/123.*/gs);  
      	alert(n1); //==> 123\nabcbcd
      }
      正则/123.+/g 不能匹配 “123\nabc”。
      正则/123.+/gs 可以匹配 “123\nabc”。
  • 正则贪婪模式与非贪婪模式。链接

    当 ? 字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
    可以看到,在“整个表达式匹配成功”的前提下,非贪婪模式才真正的影响着子表达式的匹配行为,如果整个表达式匹配失败,非贪婪模式无法影响子表达式的匹配行为。

^ 表示开始。 $ 表示结束。 /^(abc)(bcd)$/ 表示 以abc开始 bcd结束。 /^(abc)|(bcd)$/ 表示以abc开始 或者 bcd结束, abcagugh, asugbcd, bcdsaa 不行, safabc 不行。 /^(abc)$|^(bcd)$/ 匹配 abc 或bcd。

  • ()也用于捕获分组。例外,如果()中前面有如下会变成非捕获分组,变成先行 后行断言: ?:、?=、?<=、?!、?<!等。 ?:仅仅是非捕获。后面四种不仅非捕获,而且零宽(即不消耗字符),而且还有特定作用。

  • 反向引用。 链接

  • 反向引用。 向后处理视为正向,引用到前面的规则,所以叫反向引用。
    (?:[1-9])([a-z]+)\1
    123456runoobrunoob623runoob456 =>6runoobrunoob

    ([1-9])([a-z]+)\1
    123456runoob623runoob456 => 6runoob6
    123456runoob123runoob456 => 无

  • 先行断言,后行断言。
    ?=、?<=、?!、?<! 的使用区别。链接
    (?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion)
    (?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)
    (?<=pattern) 零宽正向后行断言(zero-width positive lookbehind assertion)
    (?<!pattern) 零宽负向后行断言(zero-width negative lookbehind assertion)
    我感觉这里不叫正向 负向,叫正 和 负更好, 正先行断言,负先行断言。正后行断言,负后行断言。记忆方法:这里正 负向是表示肯定 否定, 先行 后行是表示 位置在pattern的前 后。
    还有其他的叫法, 正预测先行断言, 负预测先行断言。 正回顾后发断言, 负回顾后发断言。
    正向肯定断言, 正向否定断言, 负向肯定断言, 负向否定断言。(从查找的方向看,这种叫法其实也合理)(最后的叫法最合理。)

正则表达式在编程语言中运用

链接

在 Java 中,\\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。

所以,在其他的语言中(如 Perl),一个反斜杠 \ 就足以具有转义的作用,而在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。也可以简单的理解在 Java 的正则表达式中,两个 \\ 代表其他语言中的一个 \,这也就是为什么表示一位数字的正则表达式是 \\d,而表示一个普通的反斜杠是 \\

java 中的正则字符串(java字符串形式的正则表达式)是包裹在原生的正则表达式字符串上的(即实际上加了一个中间层做处理)。 所以要将java字符串形式的正则表达式 转为 原生的正则表达式字符串, 要\\d。 java自己先对自己的字符串做处理的,而不是直接处理正则,其他的语法是直接处理正则,因此只要\d.

![找不到图片时显示的文字](imgs/20220413_1.jpeg)

Java中正则表达式。

  • String类的方法中直接使用正则表达式模式串。
    String 的str.replace(regstr, repstr) , str.find(regstr), str.match(regstr)
  • 专门的正则类。 Pattern类 (将模式串编译成pattern类)。 match类(由pattern类match方法得到match类实例)。

python中的正则表达式。 https://www.jianshu.com/p/5295c5988b7f

  • 字符串类中的方法不支持正则规则。
  • 专门的正则模块 re 模块。 1. 模块中的函数,re.match,re.search等。 2.专门正则相关的类。Pattern类 (re.compile(patstr) 将模式串编译成pattern类), match类(由pattern类match方法得到match类实例)。
    匹配 查看一个字符串是否符合正则表达式的语法,一般返回true或者false
    获取 正则表达式来提取字符串中符合要求的文本
    替换 查找字符串中符合正则表达式的文本,并用相应的字符串替换
    分割 使用正则表达式对字符串进行分割。

正则表达式引擎

https://blog.csdn.net/weixin_55267022/article/details/118082886

https://www.cnblogs.com/Bubgit/p/10240790.html

正则表达式/模式串。
根据正则表达式 构造 NFA, DFA。 (正则表达式引擎)
遍历字符串/待匹配字符串。 一个一个遍历, 跟随NFA DFA进行比较,
0.针对整个字符串而言,如果遍历到某个字符时不在NFA/ DFA的状态中,那么不匹配。 或者 如果遍历结束时不在终结状态,不匹配。 只有遍历结束时 在 NFA/DFA的 终结状态 才是匹配。
1.针对部分匹配而言,如果待匹配字符串部分 走到了终结状态,那么说明部分字符串符合正则表达式。(这个可用于提取)。如果整个过程都没走到终结状态,那么就是连部分都不匹配的。

手动流程: 1. 正则表达式,如果可以直观转DFA,可以直接转DFA。 如果不能,先转NFA(转NFA比较直观),再将NFA转DFA(手动)。 2.根据DFA处理待匹配字符串(手动) 。
正则表达式模式串->NFA->DFA—>匹配。

完整的正则表达式程序(两部分:表达式引擎+匹配),流程(代码形式):
根据 正则表达式字符串 生成 状态机(实际上是图结构)(有NFA,DFA) (节点是状态,线是输入的值)。 这个生成状态机部分的程序称为正则表达式引擎,用于生成状态机。(重点,难点)
然后利用状态机 去遍历待匹配字符串,看是否匹配。
https://blog.csdn.net/weixin_39969611/article/details/114613950
https://baijiahao.baidu.com/s?id=1736259056451963107&wfr=spider&for=pc

https://blog.csdn.net/weixin_43655282/article/details/108963761

https://blog.csdn.net/qq_40294512/article/details/89004777 好! move操作的为所有出现的输入值。

正则表达式 可以 直观的 转为 NFA。 NFA状态转换图和转换表 都是 直观的看出正则表达式的 含义。
但是对于程序而言,这个不好处理,因为对输入是不确定的。 对计算机而言更合适处理的的是DFA,因此将NFA转成DFA。 转换DFA时,可能会出现多个结束状态。
NFA 转 DFA, 要引入闭包的概念和操作。
对任何非确定的有穷自动机N ,存在定义同一语言的确定的有穷自动机D。对任何确定的有穷自动机D ,存在定义同一语言的非确定的有穷自动机N

NFA/DFA 都有状态转换图,状态转换表。 起始状态 终结状态。

NFA 有 带有和不带有“ε-边”的NFA。 两者等价。 一般用带有”ε-边”的NFA。 一般 带有”ε-边” 可以变为只有一个终结状态,而不带有”ε-边”可能会有多个终结状态。
NFA的不确定性:多值映射(输入一个值有多个状态转换),带空转移。

NFA/DFA 可以用在正则表达式。 也可以用在编译原理 的词法分析阶段(将源程序/字符串形式 生成token表)。

背景

新拉了一条移动的宽带,300M。因为某些**原因,要用到ipv6。 因为那个vps,只提供ipv6的地址。所以,要折腾宽带的ipv6.

手上的设备:

  • 广东深圳移动 300M 免费一年。
  • 光猫型号:吉比特 GM232。
  • 路由器: 大麦DW33D。Mercury8012(不支持ipv6)。移动的RAX3000Q
  • 宽带用户名和密码。 用户名是手机号,密码可以在移动app上重置。
  • 光猫后台管理。两种方式 user, admin。 user的在猫的背面。 admin的CMCCAdmin和aDm8H%MdA。
  • 光猫设备认证码。 这个用来重置光猫以及注册光猫设备。 可以在安装的时候让装维师傅告知下。一般用不上。

登录光猫网页管理界面,将一些重要的信息先截图备份,避免在后续操作中不知道怎么改回来(注意vlanid别搞错了)。移动给的光猫默认有4个连接。

移动猫一般有三种连接。 分别是宽带,网络电视,网络电话。 这三种都绑定了猫的一个LAN口。 所以有的lan口直连电脑不行,因为dhcp获取不到而且不是给上网用的,是特殊用途。

移动光猫的网口有1个千兆lan口,3个百兆lan口。被绑定了三个口。绑定了那么该端口的dhcp就不能使用了。
internet 就是我们平时用来上网的连接。OTTV 用于IPTV业务的连接。VOIP 用于语音业务的连接。
移动光猫lan1是绑定了pppoe拨号。 lan2 lan4是绑定了网路电视和网络语音。 lan3空,可以直连电脑。
所以,能直连电脑的网口只有lan1 和lan3. 其他口连接的话,不会分配ip的。

找不到图片时显示




开搞

现在移动 电信 宽带都是有ipv6地址的,提供的猫也支持公网ipv6.
4G 5G也是有公网ipv6地址的。 手机 电脑等都支持ipv6的。但是家用路由器不一定。
如何检测当前网络是否支持ipv6?

注意: 手机 电脑上能获取ipv6地址 不代表就能上ipv6网络。 可以使用上述方法进行检测。

关于手机 电脑上有两个ipv6地址,解释
inet6 2409:8955:321c:41aa:c6f:5822:7f30:8e60 prefixlen 64 autoconf secured
inet6 2409:8955:321c:41aa:e527:782d:3c19:9124 prefixlen 64 autoconf temporary
关于ipv6的内网 还是外网地址:
fe80开头的是内网IPV6地址,其他开头的是公网IPV6地址,
电信为240e::/20 移动为2409:8000::/20 联通为2408:8000::/20
讨论

ipv6 地址:
fe08开头 本地地址。 类似 192.168
2001:db8 是经过NAT。 可以接收外来请求(但是要你先主动发起请求才行)。
2409 公网ipv6

开搞过程中出现的问题:

  • 光猫拨号,查看状态信息,发现光猫有ipv6地址。也可开启了dpcpv6。 有线直连电脑,电脑有ipv6,而且能稳定顺畅访问ipv6网络。这个光猫没有wifi功能。所以用wifi要配合一个路由器使用。但是设备无线连接路由器或有线连接路由器,可能会无法获取ipv6地址。

DW33D

  • 光猫拨号,DW33D wan口连接, DW33D没有分配到ipv6地址。手机 电脑连接路由器也获取不到ipv6.该问题是因为DW33D官方固件中不支持ipv6. 刷入新的固件能获取ipv6.
  • 新固件 获取的ipv6,无法连上ipv6网络。
  • 但是,后来这个路由器手贱升级了变成砖了。刷机救砖是另一个悲剧的过程。总之失败告终。不过理论上应该和移动RAX3000Q一样,都能完成ipv6的获取。

tp路由器

  • 使用tp的路由器(Mercury8012),不支持ipv6.
  • 曲线救国。将tp桥接到光猫,这样手机 电脑连接的路由器时 由光猫进行dhcp 分配ipv6. 但是问题是,这个ipv6地址时而能上时而不能上ipv6网络,不稳定,应该是和路由器有关系。

移动RAX3000Q

  • 移动RAX3000Q路由器。支持ipv6,也支持nat6。 支持wifi6. 移动送的免费用一年,一年后要还的。
  • RAX3000Q很好,下面的多个实验都支持了。

如何让自己家里的设备连接时也能有ipv6?

  • 如果家里的路由器不支持ipv6。 方法:路由器桥接到猫。让路由器lan连接到猫的lan,关闭路由器DHCP,修改路由器br-lan不要和猫同一网段。连接到路由器的设备的ipv4 v6地址由猫DHCP来分配。 地址让支持ipv6的猫去分配ipv6,这样设备也能得到IPV6地址。
  • 如果家里的路由器支持ipv6。 方法;1.同上。让路由器桥接猫。 2.自己本身支持ipv6分配,开启nat6.(不过似乎是内网ipv6,那么可能还是无法访问ipv6网络)。3.开启猫的桥接模式,将网络功能桥接到某个网口。 拨号 dhcp等全由路由器来做,猫只做猫/调制解调的功能。 这个要求路由器本身支持ipv6。
    最好的方式是3。
    光猫改桥接:https://zhuanlan.zhihu.com/p/343762196 。1.进入光猫配置页面。更改Internet的连接模式,改成brigde模式,选择ipv4/ipv6, 绑定在某个lan口。(如果无法修改,可以删除后再新建一个连接) 2.路由器进行拨号。

我们来说说这三种获取ipv6地址的方法。

  1. 路由器桥接到猫。 光猫拨号上网,支持ipv6,开始dhcp6,RA设置O M 模式。 路由器lan/wan连接到光猫(一般用lan),设置成桥接模式,关闭路由器的dhcp。 这样电脑、手机设备连接路由器时,会获取到猫分配的ipv6地址,而且是公网的ipv6地址。缺点和问题:获取的ipv6可能不稳定,手机端可能获取不到ipv6地址。 经测试,mercury8012做的桥接获取的ipv6不稳定,而且手机端获取不到ipv6. RAX3000Q 电脑端没问题,但是手机端无法获取ipv6.
  2. 路由器本身支持ipv6,并且支持nat6。(前提是路由器支持ipv6,并且能够获取到猫分配的公网ipv6)。 光猫拨号上网,设置RA O M模式。 路由器wan口连接光猫,设置成自动获取ip模式(也即路由模式)(这样能从猫那里获取ipv4和公网ipv6的)(这里的dhcp模式,是说以DHCP客户端去获取IP地址。 还有DHCP服务器端,是进行分配ip地址的。), 开启NAT6。手机 电脑等设备连接路由器,那么获取到的ipv6地址是NAT6内网的ipv6地址,并不是公网的ipv6。可以访问ipv6网络(前提要你先主动发请求出去)。
    • 理论上 路由器本身支持ipv6的dhcp,那么手机等设备也可以获取公网的ipv6,压根不需要nat6. 但是 经测试后,直接使用路由器的dhcp6并不能获取到ipv6地址。这个可能是和猫 路由器设置有关的。而NAT6比较简单,使用开启nat6,获取内网的ipv6地址,可以访问ipv6网络。
  3. 光猫做桥接,路由器进行拨号并自动分配ipv6。光猫设置网络为桥接模式。路由器wan口连接光猫。 路由器使用pppoe拨号上网。并不需要其他什么而外设置,一般都是自动分配ipv4 ipv6。(这个要求路由器能支持ipv6)。 电脑 手机等设备连接路由器后获取到的是公网的ipv6地址的。

我的选择:
实验了这么几种方式,都能获取ipv6地址。但是我的需求,很简单,只想要能访问ipv6地址,因此我采用的是第二种方式。第一种路由器桥接光猫,光猫的性能堪忧。 第三种 暴露公网ipv6可能会带来不友好的攻击。

其实在技术上,ipv6和ipv4是类似的。 但是历史原因,造成了两种网络的割裂,纯ipv4网络和纯ipv6网络无法联通(基础设备,协议的不支持)。 现在随着基础设备支持ipv6,纯ipv4网络和i纯pv6网络以后也会慢慢互相连通的,对用户来说会感知透明。

电脑直连可以获取到ipv6,说明ipv6没问题。 光猫上没有显示分配的ipv6 有点奇怪的。 算了,不影响不管它。
路由器直连为什么没有分配到ipv6? 难道因路由器连接的是lan1,电脑直连lan3? 和这个没关系。 电脑直连lan1照样有ipv6. 所以问题出在路由器身上。

光猫上为什么不显示ipv6的分配情况。
为什么路由器上没有分配ipv6,而直连的电脑可以? 那应该就是路由器的问题, 怎么解决?

直连光猫有ipv6,路由器wan lan都有ipv6, 但是手机连接路由器 ipv6 是内网的ipv6.
可能原因:dhcp,将路由器的dhcp关闭 让猫去dhcp。
应该是路由器的问题,可以像RAX3000Q那样NAT6。

问题:
在让路由器做交换机之后,可以获取到ipv6,但是有时候能上ipv6,有时候不能。 这就很奇怪了。可能是路由器的问题。也有可能猫的问题。
现在不知道如果让路由器拨号 会不会有问题?

如果路由器拨号 不会有问题,那说明你是猫的问题了。
设置ipv6的RA,开启 O M模式。 LAN测DNS获取方式 HGWProxy (和DNS关系不大)。 不过这个设置之后,会导致有时候ipv6连不上

问题:
光猫会分配ipv6, 有线直连,有ipv6地址,可以连ipv6网络,比较稳定。

  • 将大麦升级后,分配了ipv6但是无法联ipv6网络。 可能是猫的设置问题。
  • 将路由器桥接光猫后,分配了ipv6,有时可以连ipv6网络,有时不可以。 这个可能是路由器的问题。也有可能猫的设置问题。 可以用大麦路由器去测试测试。

将新账号 放在以前旧的移动光猫上,无法注册成功。 可能是账号和设备绑定的。

大麦DW33D 硬件是支持ipv6的。

  • 原先的固件不支持,所以导致连接的设备没有分配ipv6.
  • 更新了固件。 支持了。 但是分配的是内网的ipv6,还是无法访问ipv6网络的。(待解决,很奇怪,计算是内网,只是外部无法访问到内部,但也应该能访问到ipv6网络)
  • 使用路由器桥接猫。 这个能行,但是受限于猫的性能。
  • 使用猫的桥接模式(不是猫桥接到路由器)。其实就是不用光猫拨号,用路由器拨号。猫这里只做猫的功能,然后将网络功能桥接到某个网口,该网口连接路由器wan口,路由器进行拨号。

python 包,模块。

  • 包 即目录(可以含有__init__.py,有则是regularpackage,没有则是namespacepackage)。 包名即目录名。 调用包里的模块。 包名.xx中的xx是目录下的 模块/.py文件。
  • 模块 即.py文件。模块名即文件名(不带.py)。 调用模块里的东西 模块名.xx xx可以是.py文件中的类 函数 变量等。

import 导入模块或导入模块中的某个东东。两种写法。

  • import xxx 导入模块。 (xxx查找路径 系统目录以及当前目录 或 xxx指定的 如 AA.BB.bb)。 只能导入整个模块, 要想导入模块中的某个用from。
  • from XXX import YYY 导入模块或导入模块中的东东。 从XXX模块中导入YYY(具体的类 函数 变量)。 或 从XXX包中导入模块YYY。 (XXX查找路径 系统目录以及当前目录或XXX指定的如../../ABC,不能直接指定,要sys.append)

import 绝对导入 和 相对导入(使用.和..和…等。相对导入只能用在from形式,即有.或..只能用在from。直接import .XXX是不行)(在顶级包下无法使用相对导入,即无法使用from ./../…等相对导入的形式。或者说相对导入无法..到顶级包。 顶级包 就是python命令运行时那个py文件所在的目录为顶级目录)。(绝对路径,相对路径)
(绝对是python命令执行时所在的目录为根目录,即以顶级包所在目录为根目录的。 相对是当前py文件的所在目录。)
一般相对导入(. ..)只用在有包的情况下。

pyhton2之前 默认/隐式 为相对导入, python3为绝对导入。

  • python3绝对导入2种: from import, import。 相对导入(.或..) from import。
  • python2绝对导入2种: from import,import(eg:import AA.BB.aa)。 相对导入 from import, import(只是import xxx默认为相对的 <=> from . import xxx) .
    (涉及. .. 只能用from形式)

非常简单暴力的方法,将搜索路径 加入到sys中, sys.append。

绝对导入时的模块寻找路径:
python模块的搜索目录有下面四个部分组成
1:python命令执行时的所在目录。
2:环境变量PYTHONPATH中列出的目录
通过设置该系统环境变量,可以指定python的额外搜索目录
3:python标准库目录
python的标准库
4:python的.pth文件扩展额外的搜索目录
该文件提供了一种扩展搜索目录的方式。在该文件中每一行表示一个扩展目录
python程序在启动时按照上面的顺序依次依次合并起来称为python的库文件查找路径集合。所以当python在查找某一个模块时,首先查找home目录然后PYTHONPATH目录,然后标准库,然后.pth文件中提供的目录。
python的模块搜索路径列表存放在sys.path变量总,可以通过输出该变量来查看当前模块搜索列表。也可以通过改改变该变量的值来动态修改python的搜索路径。

相对导入时的模块寻找路径,就是相对导入的路径去寻找。 (相对导入 是相对当前.py文件所在目录)

(相对导入时如果要找上顶级包上一层的模块,可以上层路径加到sys路径中,作为绝对导入形式导入。)

python import 引用导致的循环导入。

  • import过程 实际上是栈的形式。 A 中import B , 在import处,暂停A的执行,去执行导入的文件B,导入文件B执行完之后,返回到A中的import点,A从import点处继续往下执行。

解决import错误。

  • ValueError: attempted relative import beyond top-level package # 试图在顶级包(top-level package)之外进行相对导入
  • ImportError: attempted relative import with no known parent package. 在顶级包中无法用相对导入。
  • ModuleNotFoundError: No module named ‘moduleY’ 找不到moduel。 解决方法,看绝对 还是 相对,然后去看看寻找路径中有没有该module。

如果你想在顶级包下使用顶级包上层的模块,那么可以将上层模块加入到sys路径中。然后以绝对导入方式直接import。