系统概念

 

参考

存储

大小端

数据在CPU内存中有两种存放方式, 假设数据0x12345678从地址0x1000开始存放

大端

大端是高字节存放到内存低地址

$0x12345678$ 中$0x12$存到低地址, $0x78$存到高地址

graph LR;
    subgraph B[大端]
        B1(0x12)
        B2(0x34)
        B3(0x56)
        B4(0x78)
    end
    subgraph A[地址]
        A1(0x1000)
        A2(0x1008)
        A3(0x1010)
        A4(0x1018)
    end
    B1-->A1
    B2-->A2
    B3-->A3
    B4-->A4

小端

小端是高字节存放到内存高地址

$0x12345678$ 中 $0x12$存到高地址, $0x78$存到低地址

graph LR;
    subgraph S[小端]
        S1(0x78)
        S2(0x56)
        S3(0x34)
        S4(0x12)
    end
    subgraph A[地址]
        A1(0x1000)
        A2(0x1008)
        A3(0x1010)
        A4(0x1018)
    end
    S1-->A1
    S2-->A2
    S3-->A3
    S4-->A4

有效字节

MSB(most significant byte)

最高有效字节

LSB(least significant byte)

最低有效字节

32位int型数$0x12345678$, MSB为$0x12$, LSB为$0x78$

大小

bit 意为位或比特, 是电子计算机中最小数据单位

每一位状态只能是 01

字节

Byte意为字节, 是计算机处理数据基本单位

1字节为8位, 1Byte = 8bit

graph LR;
    subgraph S[Byte]
        A0(bit)
        A1(bit)
        A2(bit)
        A3(bit)
        A4(bit)
        A5(bit)
        A6(bit)
        A7(bit)
    end

格式

ASCII码

一个英文字母占一个字节空间, 如一个ASCII码就是一个字节

UTF-8编码

一个英文字符等于一个字节, 一个中文(含繁体)等于三个字节

中文标点占三个字节, 英文标点占一个字节

Unicode编码

一个英文等于两个字节, 一个中文(含繁体)等于两个字节, 中文标点占两个字节, 英文标点占两个字节

编码

原码

正数

按照绝对值大小转换成二进制数

  • 示例, $32$位系统中, $5$原码为

$00000000$ $00000000$ $00000000$ $00000101$

负数

按照绝对值大小转换成二进制数, 且最高位补$1$

  • 示例, $32$位系统中, $-5$原码为

$10000000$ $00000000$ $00000000$ $00000101$

反码

正数

反码与原码相同

负数

对原码中除符号位之外每位取反

  • 示例, $32$位系统中, $-5$反码为

$1111111$ $11111111$ $11111111$ $11111010$

补码

正数

补码与原码相同

负数

补码为反码最后一位加1

  • 示例, $32$位系统中, $-5$补码为

$1111111$ $11111111$ $11111111$ $11111011$

加法

整数

[$A$]$_补$ $+$ [$B$]$_补$ $=$ [$A+B$]$_补$ $mod$ $2^{n+1}$

小数

[$A$]$_补$ $+$ [$B$]$_补$ $=$ [$A+B$]$_补$ $mod$ $2$

减法

整数

[$A-B$]$_补$ $=$ [$A$]$_补$ $+$ [$-B$]$_补$ $mod$ $2^{n+1}$

小数

[$A-B$]$_补$ $=$ [$A$]$_补$ $+$ [$-B$]$_补$ $mod$ $2$

计算

半加器

将两个一位二进制数相加

  • 输入端口 $A$, $B$

  • 输出端口 进位 $C$ = $A$ & $B$, 和 $S$ = $A$ ^ $B$

输入A 输入B 进位 C 和 S
0 0 0 0
1 0 0 1
0 1 0 1
1 1 1 0

全加器

全加器(full adder)将两个一位二进制数相加, 并根据接收到低位进位信号, 输出和、进位输出

全加器三个输入信号为两个加数A、B和低位进位Cin

全加器通常可以通过级联(cascade)方式, 构成多位(如8位、16位、32位)二进制数加法器基本部分

$A$ $B$ $Cin$ $Cout$ $S$
0 0 0 0 0
1 0 0 0 1
0 1 0 0 1
1 1 0 1 0
0 0 1 0 1
1 0 1 1 0
0 1 1 1 0
1 1 1 1 1

脉动进位加法器

// 全加器代码
int add(int a, int b) {
    int c;
    int s;
    if (a == 0 || b == 0) {
        return 0;
    }
    // 进位标志
    c = a & b;

    // 进位c左移1位
    c <<= 1;
    // 当前和s
    s = a ^ b;
    // 结束标志是输入值一个为0
    return add(s, c);
}

3 + 9 = 12 -> 0011 + 1001 = 1100

寄存器

通用寄存器

名称 作用
ax 累积暂存器
bx 基底暂存器
cx 计数暂存器
dx 资料暂存器
名称 作用
eax 累加器(accumulator), 是很多加法乘法指令缺省寄存器
ebx 基地址(base)寄存器, 在内存寻址时存放基地址
ecx 计数器(counter), 是重复(REP)前缀指令和LOOP指令内定计数器
edx 用来放整数除法产生余数

索引暂存器

名称 作用
si 来源索引暂存器
di 目的索引暂存器
名称 作用
esi 源索引寄存器(source index)
edi 目标索引寄存器(destination index)

用于字符串操作指令, esi指向源串, edi指向目标串

堆叠、基底暂存器

名称 作用
sp 堆叠指标暂存器
bp 基底指标暂存器
名称 作用
esp 堆栈指针
ebp 基址指针(base pointer), 用作高级语言函数调用”框架指针”

esp 专门用作堆栈指针, 被形象地称为栈顶指针, 堆栈顶部是地址小区域, 压入堆栈数据时, 在32位平台上esp每次减少4字节

从零开始写OS内核-BIOS启动到实模式

启动

读取 BIOS

按下电源按钮后, 计算机首先读取一块存储有基本输入输出系統即 BIOS 程序的芯片

开机后 CPU 初始模式是实模式, 地址宽度为 20 位, 即最大地址空间 1MB, 其划分固定, 每一块都被映射到不同设备上

BIOS作用

(1) 开机后 CPU 指令寄存器 IP 被强置为地址 0xFFFF0, 该地址被映射到 BIOS 固件上代码, 是计算机开机后第一条指令地址

(2) CPU 开始执行 BIOS 上代码, 这一部分主要是硬件输入输出设备相关检查, 以及建立一个最初中断向量表

(3) BIOS 代码最后阶段工作, 是检查启动盘上 MBR 分区, 即磁盘上第一个 512B 内容, 又叫引导分区

BIOS 会对这 512B 做一个检查, 其最后2个字节必须是0x55 和 0xaa, 否则就不是合法启动盘

(4) 检查通过后, BIOS 将这 512B 加载到内存 0x7C00 处, 到 0x7E00 为止, 然后指令跳转到 0x7C00 开始执行

内存布局规划

TODO

socket

本地进程通信

  • 消息传递(管道、消息队列、$FIFO$)

  • 同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)

  • 共享内存(匿名和具名, 如$channel$)

  • 远程过程调用($RPC$)

网络中进程通信

  • 如何标识一台主机, 即怎样确定我们将要通信的进程是在那一台主机上运行

  • 如何标识唯一进程?本地通过 pid 标识, 网络中应该怎样标识

解决办法:

  • 网络层ip可以唯一标识网络中主机

  • 传输层协议, 端口可以唯一标识主机中应用程序(进程), 因此利用ip地址, 协议, 端口就可标识网络进程, 网络中进程通信就可利用此标志与其它进程进行交互

流程图

graph TB;
    C(Client)
    C1(socket 创建)
    C2(connect 请求连接Server)
    C3(send 客户端发送数据)
    C4(receive 客户端接收数据)
    C5(close 关闭)

    S(Server)
    S1(socket 创建)
    S2(bind 绑定监听端口)
    S3(listen 设置监听队列)
    S4(accept 循环等待Client连接)
    S5(receive 服务端接收数据)
    S6(send 服务端)
    S7(close 关闭)

    C --> C1 --> C2 --> C3 --> C4 --> C5
    S --> S1 --> S2 --> S3 --> S4 --> S5 --> S6 -->S7

    C2 --> S4
    C3 --> S5
    S6 --> C4
    C5 --> S7
sequenceDiagram
    participant Client
    participant Server
    participant SocketAPI
    participant OS

    Client->>SocketAPI: socket()
    SocketAPI->>OS: 系统调用socket()
    Client->>SocketAPI: connect()
    SocketAPI->>OS: 系统调用connect()

    Server->>SocketAPI: socket()
    SocketAPI->>OS: 系统调用socket()
    Server->>SocketAPI: bind()
    SocketAPI->>OS: 系统调用bind()
    Server->>SocketAPI: listen()
    SocketAPI->>OS: 系统调用listen()
    Server->>SocketAPI: accept()
    SocketAPI->>OS: 系统调用accept()

    Client->>SocketAPI: send()
    SocketAPI->>OS: 系统调用send()
    Server->>SocketAPI: recv()
    SocketAPI->>OS: 系统调用recv()

    Client->>SocketAPI: close()
    SocketAPI->>OS: 系统调用close()
    Server->>SocketAPI: close()
    SocketAPI->>OS: 系统调用close()