0%

现象

QQ图片20220512202816

现象如图所示,会一直打印A。

在执行时,追踪IDT表,发现表中每一项第四位的值发生了变化。

QQ图片20220512203227

在IDT表初始化后,其所有描述表的第四位的值均为ignore_int首第四位值,即0x114。

在修改的程序后,每次eax都会多执行一条+2的指令。

操作系统的引导

完成 bootsect.s 的屏幕输出功能

关键代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

! 文件:bootsect.s
entry _start
_start:
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#25
mov bx,#0x0007
mov bp,#msg1
mov ax,#0x07c0
mov es,ax
mov ax,#0x1301
int 0x10
inf_loop:
jmp inf_loop
msg1:
.byte 13,10
.ascii "LKJos is running..."
.byte 13,10,13,10
.org 510
boot_flag:
.word 0xAA55

我们修改的字符为19个,再加上前后一共3个回车加换行,所以总共25个字符。

将 .org 508 修改为 .org 510,是因为这里不需要 root_dev: .word ROOT_DEV,为了保证 boot_flag 一定在最后两个字节,所以要修改 .org。

执行下面两个命令编译和链接 bootsect.s

1
2
$ as86 -0 -a -o bootsect.o bootsect.s
$ ld86 -0 -s -o bootsect bootsect.o

需要留意的文件是 bootsect 的文件大小是 544 字节,而引导程序必须要正好占用一个磁盘扇区,即 512 个字节。 造成多了 32 个字节的原因是 ld86 产生的是 Minix 可执行文件格式, 这样的可执行文件处理文本段、数据段等部分以外,还包括一个 Minix 可执行文件头部。

去掉32字节的头部文件。

1
dd bs=1 if=bootsect of=Image skip=32

接下来进行拷贝,并且run

1
2
3
4
5
6
# 当前的工作路径为 /common/linux-0.11/boot/
# 将刚刚生成的 Image 复制到 linux-0.11 目录下
$ cp ./Image ../Image
# 执行run 脚本
$ ../../run

注:由于我执行run的时候有些许问题,所以我对于目录结构进行了修改。

效果如下图

image-20220508200758526

bootsect.s 读入 setup.s

首先编写一个 setup.s,该 setup.s 可以就直接拷贝前面的 bootsect.s,然后将其中的显示的信息改为:“Now we are in SETUP”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
entry _start
_start:
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#25
mov bx,#0x0007
mov bp,#msg2
mov ax,cs ! 这里的cs其实就是这段代码的段地址
mov es,ax
mov ax,#0x1301
int 0x10
inf_loop:
jmp inf_loop
msg2:
.byte 13,10
.ascii "Now we are in SETUP"
.byte 13,10,13,10
.org 510
boot_flag:
.word 0xAA55

接下来需要编写 bootsect.s 中载入 setup.s 的关键代码,注意去掉无限循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
SETUPLEN=2              ! 读入的扇区数
SETUPSEG=0x07e0 ! setup代码的段地址
entry _start
_start:
mov ah,#0x03 ! 设置功能号
xor bh,bh ! 将bh置0
int 0x10 ! 返回行号和列号,供显示串用
mov cx,#25 !要显示的字符串长度
mov bx,#0x0007 ! bh=0,bl=07(正常的黑底白字)
mov bp,#msg1 ! es:bp 要显示的字符串物理地址
mov ax,#0x07c0 ! 将es段寄存器置为#0x07c0
mov es,ax
mov ax,#0x1301 ! ah=13(设置功能号),al=01(目标字符串仅仅包含字符,属性在BL中包含,光标停在字符串结尾处)
int 0x10 ! 显示字符串

! 将setup模块从磁盘的第二个扇区开始读到0x7e00
load_setup:
mov dx,#0x0000 ! 磁头=0;驱动器号=0
mov cx,#0x0002 ! 磁道=0;扇区=2
mov bx,#0x0200 ! 偏移地址
mov ax,#0x0200+SETUPLEN ! 设置功能号;需要读出的扇区数量
int 0x13 ! 读磁盘扇区到内存
jnc ok_load_setup ! CF=0(读入成功)跳转到ok_load_setup
mov dx,#0x0000 ! 如果读入失败,使用功能号ah=0x00————磁盘系统复位
mov ax,#0x0000
int 0x13
jmp load_setup ! 尝试重新读入

ok_load_setup:
jmpi 0,SETUPSEG ! 段间跳转指令,跳转到setup模块处(0x07e0:0000)

! 字符串信息
msg1:
.byte 13,10 ! 换行+回车
.ascii "LKJos is running..."
.byte 13,10,13,10 ! 换行+回车

! 将
.org 510

! 启动盘具有有效引导扇区的标志。仅供BIOS中的程序加载引导扇区时识别使用。它必须位于引导扇区的最后两个字节中
boot_flag:
.word 0xAA55

效果如下图

image-20220508210219587

需要修改build.c,并且删除同目录下的 hdc-0.11.img.lock 即可。

setup.s 获取基本硬件参数

setup.s 将获得硬件参数放在内存的 0x90000 处。原版 setup.s 中已经完成了光标位置、内存大小、显存大小、显卡参数、第一和第二硬盘参数的保存。

ah=#0x03 调用 0x10 中断可以读出光标的位置,用 ah=#0x88 调用 0x15 中断可以读出内存的大小。 有些硬件参数的获取要稍微复杂一些,如磁盘参数表。在 PC 机中 BIOS 设定的中断向量表中 int 0x41 的中断向量位置( 4*0x41 = 0x0000:0x0104 )存放的并不是中断程序的地址,而是第一个硬盘的基本参数表。 第二个硬盘的基本参数表入口地址存于 int 0x46 中断向量位置处。每个硬盘参数表有 16 个字节大小。

在PC机中BIOS设定的中断向量表中int 0x41的中断向量位置存放的并不是中断程序的地址,而是第一个硬盘的基本参数表。对于100%兼容的BIOS来说,这里存放着硬盘参数表阵列的首地址0xF000:0E401,第二个硬盘的基本参数表入口地址存于int 0x46中断向量位置处.每个硬盘参数表有16个字节大小.

这段话是重点,磁盘参数就存放在以0x0000:0x0104为首地址的单元中只存了4个字节,里面存放的是磁盘参数表的偏移地址和段地址,也就是上文所说这里存放着硬盘参数表阵列的首地址0xF000:0E401。

以十六进制方式显示比较简单。这是因为十六进制与二进制有很好的对应关系(每 4 位二进制数和 1 位十六进制数存在一一对应关系),显示时只需将原二进制数每 4 位划成一组,按组求对应的 ASCII 码送显示器即可。ASCII 码与十六进制数字的对应关系为:0x30 ~ 0x39 对应数字 0 ~ 9,0x41 ~ 0x46 对应数字 a ~ f。从数字 9 到 a,其 ASCII 码间隔了 7h,这一点在转换时要特别注意。为使一个十六进制数能按高位到低位依次显示,实际编程中,需对 bx 中的数每次循环左移一组(4 位二进制),然后屏蔽掉当前高 12 位,对当前余下的 4 位(即 1 位十六进制数)求其 ASCII 码,要判断它是 0 ~ 9 还是 a ~ f,是前者则加 0x30 得对应的 ASCII 码,后者则要加 0x37 才行,最后送显示器输出。以上步骤重复 4 次,就可以完成 bx 中数以 4 位十六进制的形式显示出来。

如下图:

image-20220508215057266

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
! 文件setup.s
INITSEG = 0x9000

entry _start
_start:
! 在显示字符串之前必须先获取当前光标的位置,这样就可以把字符串显示到当前光标处了
mov ah,#0x03
xor bh,bh
int 0x10

! 利用10号中断的13号功能打印字符串"Now we are in SETUP."
mov cx,#26
mov bx,#0x0007
mov bp,#msg1
mov ax,cs
mov es,ax
mov ax,#0x1301
int 0x10

! 下面开始读取一些硬件参数

! 读入光标位置信息,保存到0x90000处
mov ax,#INITSEG
mov ds,ax
mov ah,#0x03
xor bh,bh
int 0x10
mov [0],ds

! 读入内存大小位置信息,保存到0x90002处
mov ah,#0x88
int 0x15
mov [2],ax

! 从0x41处拷贝16个字节(磁盘参数表)到0x90004处
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0004
mov cx,#0x10
rep ! 重复16次
movsb


! 先打印光标位置
! 打印字符串之前要先读取光标位置,将字符串打印到当前光标处
mov ah,#0x03
xor bh,bh
int 0x10

! 打印字符串 "Cursor POS:"
mov cx,#11
mov bx,#0x0007
mov ax,cs
mov es,ax
mov bp,#msg2
mov ax,#0x1301
int 0x10

! 调用打印函数,打印光标位置
mov ax,#0x9000
mov ds,ax
mov dx,0x0
call print_hex
call print_nl

! 打印内存大小
! 打印字符串"Memory SIZE:"
mov ah,#0x03
xor bh,bh
int 0x10 ! 读取光标位置

mov cx,#12
mov bx,#0x0007
mov ax,cs
mov es,ax
mov bp,#msg3
mov ax,#0x1301
int 0x10


! 调用打印函数,打印内存大小信息
mov ax,#0x9000
mov ds,ax
mov dx,0x2
call print_hex


! 打印字符串"KB"
mov ah,#0x03
xor bh,bh
int 0x10 ! 读取光标位置

mov cx,#2
mov bx,#0x0007
mov ax,cs
mov es,ax
mov bp,#msg4
mov ax,#0x1301
int 0x10
call print_nl

!打印柱面数
! 打印字符串"Cyls"
mov ah,#0x03
xor bh,bh
int 0x10 ! 读取光标位置

mov cx,#5
mov bx,#0x0007
mov ax,cs
mov es,ax
mov bp,#msg5
mov ax,#0x1301
int 0x10


! 调用打印函数打印磁盘柱面数
mov ax,#0x9000
mov ds,ax
mov dx,0x4
call print_hex
call print_nl

! 打印磁头数
! 打印字符串"Heads:"
mov ah,#0x03
xor bh,bh
int 0x10 ! 读取光标位置

mov cx,#6
mov bx,#0x0007
mov ax,cs
mov es,ax
mov bp,#msg6
mov ax,#0x1301
int 0x10


! 调用打印函数打印磁盘磁头数
mov ax,#0x9000
mov ds,ax
mov dx,0x6
call print_hex
call print_nl


! 打印每磁道扇区数
! 打印字符串"sectors"
mov ah,#0x03
xor bh,bh
int 0x10 ! 读取光标位置

mov cx,#8
mov bx,#0x0007
mov ax,cs
mov es,ax
mov bp,#msg7
mov ax,#0x1301
int 0x10

! 调用打印函数打印扇区数
mov ax,#0x9000
mov ds,ax
mov dx,0x12
call print_hex
call print_nl

Inf_loop:
jmp Inf_loop ! 无限循环


! print_hex函数:将一个数字转换为ascii码字符,并打印到屏幕上
! 参数值:dx
! 返回值:无
print_hex:
mov cx,#4 ! 要打印4个十六进制数字,故循环4次
print_digit:
rol dx,#4 ! 循环以使低4比特用上 !! 取dx的高4比特移到低4比特处
mov ax,#0xe0f ! ah = 请求的功能值,al = 半字节(4个比特)掩码
and al,dl ! 取dl的低4比特值
add al,#0x30 ! 给al数字加上十六进制0x30
cmp al,#0x3a
jl outp ! 如果是一个不大于十的数字
add al,#0x07 ! 如果是a~f,要多加7
outp:
int 0x10
loop print_digit ! 用loop重复4次
ret

! 打印回车换行
print_nl:
mov ax,#0xe0d
int 0x10
mov al,#0xa
int 0x10
ret

msg1:
.byte 13,10
.ascii "Now we are in SETUP."
.byte 13,10,13,10

msg2:
.ascii "Cursor POS:"

msg3:
.ascii "Memory SIZE:"

msg4:
.ascii "KB"

msg5:
.ascii "Cyls:"

msg6:
.ascii "Heads:"

msg7:
.ascii "Sectors:"


.org 510
boot_flag:
.word 0xAA55

问题解答

1
当PC的电源打开后,80x86结构的CPU将自动进入实模式,并从地址0xFFFF0开始自动执行程序代码,这个地址通常是ROM—BIOS中的地址。PC机的BIOS将执行某些系统的检测,并在物理地址0处开始初始化中断向量。此后将启动设备的第一个扇区512字节读入内存绝对地址0x7C00处。因为当时system模块的长度不会超过0x80000字节大小512KB,所以bootsect程序把system模块读入物理地址0x10000开始位置处时并不会覆盖在0x90000处开始的bootsect和setup模块,多此一举的是system模块移到内存中相对靠后的位置,以便加载系统主模块。解决方案是在保证操作系统启动引导成功的前提下尽量扩大ROM—BIOS的内存寻址范围。

知识点记录

数据寄存器

AH&AL=AX(accumulator):累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数,另外,所有的I/O指令都使用这一寄存器与外界设备传送数据。

BH&BL=BX(base):基址寄存器,常用于地址索引

CH&CL=CX(count):计数寄存器,常用于计数;常用于保存计算值,如在移位指令,循环(loop)和串处理指令中用作隐含的计数器.

DH&DL=DX(data):数据寄存器,常用于数据传递。

他们的特点是,这4个16位的寄存器可以分为高8位: AH, BH, CH, DH.以及低八位:AL,BL,CL,DL。这2组8位寄存器可以分别寻址,并单独使用。

中断知识

int 0x10

image-20220509162715086

注意,这里ah要先有值,代表内部子程序的编号

功能号ah=0x03,作用是读取光标的位置

输入:

1
bh = 页号

返回:

1
ch = 扫描开始线;cl = 扫描结束线;dh = 行号;dl = 列号

功能号ah=0x13,作用是显示字符串

输入:

1
al = 放置光标的方式及规定属性,下文 al=1,表示目标字符串仅仅包含字符,属性在BL中包含,光标停在字符串结尾处;es:bp = 字符串起始位置;cx = 显示的字符串字符数;bh = 页号;bl = 字符属性,下文 bl = 07H,表示正常的黑底白字;dh = 行号;dl = 列号

功能号ah=0x0e,作用是显示字符

输入:

1
al = 字符

int 0x13

在DOS等实模式操作系统下,调用INT 13h会跳转到计算机的ROM-BIOS代码中进行低级磁盘服务,对程序进行基于物理扇区的磁盘读写操作。

功能号ah=0x02,作用是读磁盘扇区到内存
输入:

寄存器 含义
ah 读磁盘扇区到内存
al 需要读出的扇区数量
ch 磁道
cl 扇区
dh 磁头
dl 驱动器
es:bx 数据缓冲区的地址

返回

1
ah = 出错码(00H表示无错,01H表示非法命令,02H表示地址目标未发现…);CF为进位标志位,如果没有出错CF=0

功能号ah=0x00,作用是磁盘系统复位

1
2
输入:dl = 驱动器
返回:如果操作成功———— C F = 0 CF=0CF=0,a h = 00 H ah=00Hah=00H

int 0x15

功能号ah=0x88,作用是获取系统所含扩展内存大小

1
2
输入:ah = 0x88
返回:ax = 从0x100000(1M)处开始的拓展内存大小(KB)。若出错则CF置位,ax = 出错码。

int 0x41

在PC机中BIOS设定的中断向量表中int 0x41的中断向量位置 (4 ∗ 0 x 41 = 0 x 0000 : 0 x 0104 4*0x41 = 0x0000:0x01044∗0x41=0x0000:0x0104)存放的并不是中断程序的地址,而是第一个硬盘的基本参数表。对于100%兼容的BIOS来说,这里存放着硬盘参数表阵列的首地址0xF000:0E401,第二个硬盘的基本参数表入口地址存于int 0x46中断向量位置处.每个硬盘参数表有16个字节大小.

其他

lds

格式: LDS reg16,mem32

其意义是同时给一个段寄存器和一个16位通用寄存器同时赋值

举例:

地址 100H 101H 102H 103H
内容 00H 41H 02H 03H
1
2
3
4
5
LDS AX,[100H]
! 结果:AX=4100H DS=0302H
可以理解为
mov AX,[100H]
mov DS,[100H+2]

调试分析 Linux 0.00 多任务切换

执行 153 行 iret 时栈的变化

执行前栈的内容

image-20220504154137710

执行后栈的内容

image-20220504154156025

在执行前后进行了栈的切换,从任务0的内核栈切换到了任务的用户栈。

模式切换

当进入和退出 system_interrupt 时,都发生了模式切换,请总结模式切换时,特权级是如何改变的?栈切换吗?如何进行切换的?

在进入中断时,通过查询IDT表,获得索引,之后进行特权级检查,要求CPL<=调用门DPL;RPL<=调用门DPL。DPL<=CPL。特权级检查通过,则特权级改变。栈也进行切换。处理器从当前任务的TSS段获得该中断使用的堆栈的段选择符与栈指针,然后把被中断的栈选择符与栈指针压入新栈。EFLAGES、CS、EIP的值也被压栈。

当退出时,使用iret指令。把保存的寄存器内容恢复到EFLAGES中,完成特权级复原,即切换为3。同时栈也切换回原来的栈。

任务切换过程

当时钟中断发生,进入到 timer_interrupt 程序,请详细记录从任务 0 切换到任务 1 的过程。

image-20220504170543986

以本图为例分析。说明第一次切换时的状况,第一次切换,即时钟中断发生时,大概率会在227行,此时任务号为0,当跳入时钟中断后,从125行开始进行转换,首先将1写入寄存器eax,然后判断,因为此时任务号为0,所以不执行127行,执行128行,则将任务号改为1,然后在129行跳转到任务1的代码段。

任务0时的寄存器如下:

img

任务1时的寄存器如下:

image-20220504205616009

任务切回过程

又过了 10ms ,从任务1切换回到任务 0 ,整个流程是怎样的? TSS 是如何变化的?各个寄存器的值是如何变化的?

image-20220504170543986

如图,承接上题叙述,从代码段228执行,在232循环,大概率在循环时进行时间中断发生,在126行比较时,由于此时任务号为1,所以跳转到131行,将任务号设为0,在132行处,跳转到任务0,由于任务0执行到129行,所以从130执行,再跳转到133行,弹栈后通过iret返回,由于上次为在226行触发中断,所以回到226行。

寄存器变化如下:

QQ图片20220504212642

变至

img

下图为任务0的TSS

image-20220504214234727

下图为任务1的TSS

image-20220504214319515

详细总结任务切换的过程

image-20220504170543986

还是对照这张图片,从头来讲。

第一次切换,即时钟中断发生时,大概率会在227行,此时任务号为0,当跳入时钟中断后,从125行开始进行转换,首先将1写入寄存器eax,然后判断,因为此时任务号为0,所以不执行127行,执行128行,则将任务号改为1,然后在129行跳转到任务1的代码段。

从代码段228执行,在232循环,大概率在循环时进行时间中断发生,在126行比较时,由于此时任务号为1,所以跳转到131行,将任务号设为0,在132行处,跳转到任务0,由于任务0执行到129行,所以从130执行,再跳转到133行,弹栈后通过iret返回,由于上次为在226行触发中断,所以回到226行。

然后大概率在此行,再次遇到时间中断,从125行开始进行转换,首先将1写入寄存器eax,然后判断,因为此时任务号为0,所以不执行127行,执行128行,则将任务号改为1,然后在129行跳转到任务1。由于任务1上次执行至

132行,所以从133行开始,到iret返回至232行。

又大概率在232行遇到时钟中断,执行到126行比较后跳转到131行,将任务号变为0,回到任务0的代码段。

至此为一个流程。

调试分析Linux0.00引导程序

简述head.s的工作原理

​ 主要包括初始设置与任务执行切换。

​ 初始设置包括:

1.设置GDT表。

2.设置系统定时芯片。

3.设置IDT表。

4.切换到任务0。

任务执行切换则为:

​ head.s程序中把定时器芯片8253的通道0设置成每经过10ms就向中断控制芯片8259A发送一个时钟中断请求信号。PC机的ROM BIOS开机时已经在8259A把时钟中断请求信号设置成中断向量8,在中断8的处理过程中执行任务切换操作。任务切换的实现方法是查看current变量中当前运行任务号,若当前为0,就利用任务1的TSS选择符作为操作数执行远跳转指令,从而切换到任务1中执行,否则反之。

​ 每个任务在执行时,会先把一个字符的ASCLL码放入寄存器AL中,然后调用系统中断调用int 0x80,而该系统调用处理过程则会调用一个简单的字符写屏子程序,把寄存器AL中的字符显示在屏幕上,同时把字符显示的屏幕下一个位置记录下来,作为下一次显示字符的屏幕位置。在显示过一个字符后,任务代码会使用循环语句延迟一段时间,然后跳转到任务代码开始出继续循环执行,从而不断显示。

记录head.s的内存分布情况

首先从GDT表看起,GDTR为0x998(3f),则跳转到0x998去。寄存器SS的内容为0010。

由于第一项为空,则从第二项看,第二项为FF 07 00 00 00 9A C0 00。将其填写到段描述中,发现其S为1,TYPE为A,为代码段,G为1,段限长为0 07 FF ,基地址为0。则实际段长度为8MB。

第三项为FF 07 00 00 00 93 C0 00。将其填写到段描述中,发现其S为1,TYPE为3,为栈段,G为1,段限长为0 07 FF ,基地址为0,B/D为1。

第四项为02 00 00 80 0B 92 C0 00,将其填写到段描述符中,发现其S为1,TYPE为2,为数据段,G为1,段限长为0 00 02,基地址为0XB8000。则实际段长度为8KB。

第五、第六、七项S为0。

再查询任务0 LDT表

同理分析,则代码段与数据段基地址均为0,段限长为0x03ff,实际长度为4MB。

再查询任务1 LDT表

同理分析,则代码段与数据段基地址均为0,段限长为0x03ff,实际长度为4MB。

再运行到任务0处,此时SS寄存器为0x17,栈段基地址为0,段限长为0x03ff。

运行到任务1同理,此时SS寄存器为0x17,栈段基地址为0,段限长为0x03ff。

初始化的代码段起始地址为0,段长为8MB,则终止地址为0X800000。数据段起始地址为0XB8000,段长为8kb,终止地址为0XBA000。

任务0的代码段起始地址为0,段长为4MB,则终止地址为0X400000。数据段起始地址为0,段长为4MB,则终止地址为0X400000。

任务1的代码段起始地址为0,段长为4MB,则终止地址为0X400000。数据段起始地址为0,段长为4MB,则终止地址为0X400000。

栈段编号 名称 起始地址 终止地址
1 init_stack 0x9d8 0xbd8
2 Km_stk0 0xc60 0xe60
3 Km_stk1 0xe00 0x10e0
4 User _stk1 0x1108 0x1308

简述head.s 57-62行

将新调度任务(任务0)的上下文,加载进处理器中,并将从加载的EIP指向的指令出开始执行。具体操作为

57:将任务0当前局部空间数据段选择符入栈,

58:将堆栈指针入栈,

59:将标志寄存器值入栈,

60:将当前局部空间代码段选择符入栈,

61:将代码指针入栈,

62:通过执行中断返回指令,切换到特权级3的任务0执行。·

简述iret执行后,PC如何找到下一条指令。

image-20220427150129063

在iret执行前,eip的值为000000ac,esp为00000bc4,cs的值为0008,栈顶的值为000010e0,然后执行iret。

image-20220427150336651

栈内五条内容均被弹出,其中000010e0被写入eip,同时0000000f被写入cs,则获得了下一条指令的地址。

记录iret执行前后,栈的变化

执行前

image-20220427151617085

执行后

image-20220427151627637

看上述两张图,图一为执行时,ss为0010,esp为00000bc4,当iret执行后,会弹出五条内容。分别为之前保存的寄存器eip的值,寄存器cs的值,标志寄存器eflags的值,寄存器esp的值,寄存器ss的值。

系统调用int 0x80时,栈的变化情况

调用int 0x80前,栈为task0或task1的用户栈

image-20220427151837544

调用int 0x80后,为此任务的系统栈。

image-20220427152127334

由于执行前任务特权级为3,而执行后任务特权级为0,所以进行了栈切换。压入了中断前的ss、栈指针、标志寄存器、cs和下一条指令的eip。ss寄存器的值也发生了相应变化。

用两个模型来预测,再用三组数据比较分析。

同时为了避免大环境的干扰,应对未试点的省份也进行预测。同时证明模型的合理性。

机制设计及实验研究

整体思路:

上海实施试点是2014年,所以我们采取14-19年作为政策采取后的数据,采用08-13作为政策采取前的数据。

通过08-13年的数据,采用合成控制法与..模型两种方式,预测分析政策未被实施的情况下上海地区的碳排放量,

模型中需要注意:

由于碳排放量所受的影响因素是多方面的,基于控制变量的原则,我们采用合成控制法预测上海地区的碳排放量时,所选择的其他地区应是未被试点的地区,同时我们假设,国家各地区整体的经济发展趋势大致拟合经济发展曲线,可消除一部分经济等其他因素对于实验数据的干扰。对于..模型,我们同样假设经济发展拟合经济发展曲线。通过这两种方式,我们可扩大我们所研究的试点政策对于碳排放量的影响。

为了验证我们预测模型的正确性,我们进行了稳健性检验,平行趋势检验,异质性分析。

稳健性检验:对于未试点的地区,同样用该模型进行预测,对预测数据与实际数据比较,发现拟合度较高,验证模型基本正确。

平行趋势检验:对于上海地区与选择的其他地区,在试点政策颁布前,有关碳排放政策大致相同。同时碳排放曲线大致相同。

异质性检验:

最后,对于模拟产生的两组数据,与实际数据,我们通过..分析法,对于三组数据进行分析,得出…

教室管理信息系统

在之前的基础上进行改进,优化了数据结构和存储设计,改进了索引结构,满足第四范式。

数据库部分

创建数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
create database CMIS
on primary
(
name='f1',
filename='F:\sqlserver\sqlwj\cmis\f1.mdf',
size=3mb,
maxsize=unlimited,
filegrowth=3%
),
(
name='f2',
filename='F:\sqlserver\sqlwj\cmis\f2.ndf',
size=10mb,
maxsize=500mb,
filegrowth=6mb
)
log on
(
name='f3',
filename='F:\sqlserver\sqlwj\cmis\f3.ldf',
size=1mb,
maxsize=unlimited,
filegrowth=2%
)

创建学生信息表

1
2
3
4
5
6
7
8
create table 学生信息
(
学号 char(10) not null,
姓名 varchar(15) not null,
性别 varchar(5) not null,
院系号 varchar(5) not null,
密码 varchar(15) not null
)

创建教师信息表

1
2
3
4
5
6
7
8
9
--创建教师信息表
create table 教师信息
(
教师编号 char(10) not null,
教师姓名 varchar(15) not null,
性别 varchar(5) not null,
院系号 varchar(5) not null,
职称 varchar(15) not null,
)

创建院系信息表

1
2
3
4
5
6
--创建院系信息表
create table 院系信息
(
院系号 varchar(5) not null,
院系名称 varchar(15) not null
)

创建教室信息表

1
2
3
4
5
6
--创建教室信息表
create table 教室信息
(
教室编号 varchar(5) not null,
教学楼编号 varchar(5) not null,
)

创建教学楼信息表

1
2
3
4
5
6
--创建教学楼信息表
create table 教学楼信息
(
教学楼名称 varchar(10) not null,
教学楼编号 varchar(5) not null
)

创建课程信息表

1
2
3
4
5
6
7
--创建课程信息表
create table 课程信息
(
课程名称 varchar(30) not null,
课程编号 varchar(7) not null,
教师编号 char(10) not null,
)

创建教室使用信息表

1
2
3
4
5
6
7
8
--创建教室使用信息表
create table 教室使用信息
(
教室编号 varchar(5) not null,
时间 varchar(10) not null,
状态 varchar(10) not null,
课程编号 varchar(7) not null
)

创建课程时间表

1
2
3
4
5
6
7
--创建课程时间表
create table 课程时间
(
课程编号 varchar(7) not null,
上课时间 varchar(10) not null,
上课教室 varchar(5) not null
)

约束

设置主键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--将教师信息表中教师编号设置为主键约束,身份证号设为唯一约束
alter table 教师信息
add constraint PK_教师编号 primary key (教师编号)
--将学生信息表中学号设置为主键约束,身份证号设为唯一约束
alter table 学生信息
add constraint PK_学号 primary key (学号)
--将教室信息中教室编号设置为主键
alter table 教室信息
add constraint PK_教室编号 primary key(教室编号)
--将教学楼信息中教学楼编号设置为主键
alter table 教学楼信息
add constraint PK_教学楼编号 primary key(教学楼编号)
--将院系信息中院系号号设置为主键
alter table 院系信息
add constraint PK_院系号 primary key(院系号)
--将课程信息中课程编号设置为主键
alter table 课程信息
add constraint PK_课程编号 primary key(课程编号)

设置外键约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
--将教师信息中的院系号与院系信息中的院系号添加外键
alter table 教师信息
add constraint FK_教师院系号 foreign key(院系号)references 院系信息(院系号)

--将教学楼信息中的教学楼编号与教室信息中的教学楼编号添加外键
alter table 教室信息
add constraint FK_教学楼编号 foreign key(教学楼编号)references 教学楼信息(教学楼编号)

--将学生信息中的院系号与院系信息中的院系号添加外键
alter table 学生信息
add constraint FK_学生院系号 foreign key(院系号)references 院系信息(院系号)


--将教室使用信息表中教室编号与教室信息表中的教室编号添加外键
alter table 教室使用信息
add constraint FK_教室编号教室使用信息 foreign key (教室编号)references 教室信息(教室编号)

--将教室使用信息表中课程编号与课程信息表中的课程编号添加外键
alter table 教室使用信息
add constraint FK_课程编号教室使用信息 foreign key (课程编号)references 课程信息(课程编号)

--对课程信息表中教师编号添加外键约束
alter table 课程信息
add constraint FK_教师编号课程信息 foreign key(教师编号)references 教师信息(教师编号)

--对课程时间表中上课教室添加外键约束
alter table 课程时间
add constraint FK_上课教室课程时间 foreign key(上课教室)references 教室信息(教室编号)

--对课程时间表中课程编号添加外键约束
alter table 课程时间
add constraint FK_课程编号课程时间 foreign key(课程编号)references 课程信息(课程编号)

设置检查约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
--对教师信息中的性别添加约束
  alter table 教师信息
  add constraint CK_性别教师 check (性别='男' or 性别='女')

--对学生信息中的性别添加约束
  alter table 学生信息
  add constraint CK_性别学生 check (性别='男' or 性别='女')

--对教室使用信息的时间进行约束
alter table 教室使用信息
add constraint CK_时间 check (时间='周一一二' or 时间='周一三四' or 时间='周一五六' or 时间='周一七八' or
时间='周二一二' or 时间='周二三四' or 时间='周二五六' or 时间='周二七八' or
时间='周三一二' or 时间='周三三四' or 时间='周三五六' or 时间='周三七八' or
时间='周四一二' or 时间='周四三四' or 时间='周四五六' or 时间='周四七八' or
时间='周五一二' or 时间='周五三四' or 时间='周五五六' or 时间='周五七八' or
时间='周六一二' or 时间='周六三四' or 时间='周六五六' or 时间='周六七八' or
时间='周日一二' or 时间='周日三四' or 时间='周日五六' or 时间='周日七八'
)

--对课程时间中上课时间约束
alter table 课程时间
add constraint CK_课程时间 check (上课时间='周一一二' or 上课时间='周一三四' or 上课时间='周一五六' or 上课时间='周一七八' or
上课时间='周二一二' or 上课时间='周二三四' or 上课时间='周二五六' or 上课时间='周二七八' or
上课时间='周三一二' or 上课时间='周三三四' or 上课时间='周三五六' or 上课时间='周三七八' or
上课时间='周四一二' or 上课时间='周四三四' or 上课时间='周四五六' or 上课时间='周四七八' or
上课时间='周五一二' or 上课时间='周五三四' or 上课时间='周五五六' or 上课时间='周五七八' or
上课时间='周六一二' or 上课时间='周六三四' or 上课时间='周六五六' or 上课时间='周六七八' or
上课时间='周日一二' or 上课时间='周日三四' or 上课时间='周日五六' or 上课时间='周日七八'
)

插入信息

插入教学楼基本信息

1
2
3
4
5
6
7
8
insert into 教学楼信息
values('正心','ZX')

insert into 教学楼信息
values('诚意','CY')

insert into 教学楼信息
values('格物','GW')

插入教室基本信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
insert into 教室信息
values('ZX101','ZX')

insert into 教室信息
values('ZX102','ZX')

insert into 教室信息
values('ZX103','ZX')

insert into 教室信息
values('ZX104','ZX')


insert into 教室信息
values('ZX201','ZX')

insert into 教室信息
values('ZX202','ZX')

insert into 教室信息
values('ZX203','ZX')

insert into 教室信息
values('ZX204','ZX')

insert into 教室信息
values('ZX301','ZX')

insert into 教室信息
values('ZX302','ZX')

insert into 教室信息
values('ZX303','ZX')

insert into 教室信息
values('ZX304','ZX')


insert into 教室信息
values('ZX401','ZX')

insert into 教室信息
values('ZX402','ZX')

insert into 教室信息
values('ZX403','ZX')

insert into 教室信息
values('ZX404','ZX')

insert into 教室信息
values('ZX501','ZX')

insert into 教室信息
values('ZX502','ZX')

insert into 教室信息
values('ZX503','ZX')

insert into 教室信息
values('ZX504','ZX')


insert into 教室信息
values('ZX601','ZX')

insert into 教室信息
values('ZX602','ZX')

insert into 教室信息
values('ZX603','ZX')

insert into 教室信息
values('ZX604','ZX')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
insert into 教室信息
values('CY101','CY')

insert into 教室信息
values('CY102','CY')

insert into 教室信息
values('CY103','CY')

insert into 教室信息
values('CY104','CY')


insert into 教室信息
values('CY201','CY')

insert into 教室信息
values('CY202','CY')

insert into 教室信息
values('CY203','CY')

insert into 教室信息
values('CY204','CY')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
insert into 教室信息
values('GW101','GW')

insert into 教室信息
values('GW102','GW')

insert into 教室信息
values('GW103','GW')

insert into 教室信息
values('GW104','GW')


insert into 教室信息
values('GW201','GW')

insert into 教室信息
values('GW202','GW')

insert into 教室信息
values('GW203','GW')

insert into 教室信息
values('GW204','GW')

插入院系信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
insert into 院系信息
values('001','计算机')

insert into 院系信息
values('002','航天')

insert into 院系信息
values('003','机电工程')

insert into 院系信息
values('004','材料科学')

insert into 院系信息
values('005','数学')

insert into 院系信息
values('006','经济与管理')

插入教师信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
insert into 教师信息
values('0000000001','姜老师','男','006','教授')

insert into 教师信息
values('0000000002','邹老师','男','001','教授')

insert into 教师信息
values('0000000003','陈老师','女','001','教授')

insert into 教师信息
values('0000000004','金老师','男','006','教授')

insert into 教师信息
values('0000000005','左老师','男','001','教授')

insert into 教师信息
values('0000000006','刘老师','男','001','教授')

插入课程信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
insert into 课程信息
values('国际结算','EM32907','0000000001')

insert into 课程信息
values('数据库系统','CS33503','0000000002')

insert into 课程信息
values('编译系统','CS33502','0000000003')

insert into 课程信息
values('国际企业管理','EM32408','0000000004')

insert into 课程信息
values('模式识别与深度学习','CS33262','0000000005')

insert into 课程信息
values('操作系统设计与实现','CS32202','0000000006')

插入课程时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
insert into 教室使用信息
values('ZX301','周一三四','有课','CS32202')
insert into 教室使用信息
values('ZX301','周三三四','有课','CS32202')
insert into 课程时间
values('CS32202','周一三四','ZX301')
insert into 课程时间
values('CS32202','周三三四','ZX301')

insert into 教室使用信息
values('ZX201','周一七八','有课','CS33262')
insert into 教室使用信息
values('ZX201','周三五六','有课','CS33262')
insert into 课程时间
values('CS33262','周一七八','ZX201')
insert into 课程时间
values('CS33262','周三五六','ZX201')

insert into 教室使用信息
values('ZX202','周二三四','有课','CS33502')
insert into 教室使用信息
values('ZX202','周四一二','有课','CS33502')
insert into 课程时间
values('CS33502','周二三四','ZX202')
insert into 课程时间
values('CS33502','周四一二','ZX202')

insert into 教室使用信息
values('ZX102','周一五六','有课','CS33503')
insert into 教室使用信息
values('ZX102','周四五六','有课','CS33503')
insert into 课程时间
values('CS33503','周一五六','ZX102')
insert into 课程时间
values('CS33503','周四五六','ZX102')

insert into 教室使用信息
values('ZX402','周五一二','有课','EM32408')
insert into 教室使用信息
values('ZX402','周五三四','有课','EM32408')
insert into 课程时间
values('EM32408','周五一二','ZX402')
insert into 课程时间
values('EM32408','周五三四','ZX402')

insert into 教室使用信息
values('ZX601','周四三四','有课','EM32907')

insert into 课程时间
values('EM32907','周四三四','ZX601')

编写存储

插入课程信息存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
create procedure information_entry
@coursename varchar(15),--输入参数,课程名称
@coursenumber varchar(7),--输入参数,课程编号
@coursetime varchar(10),--输入参数,课程时间
@teachername varchar(15),--输入参数,教师名称
@teachernumber char(10),--输入参数,教师编号
@buildingnumber varchar(5),--输入参数,教学楼编号
@roomnumber varchar(5)--输入参数教室编号
AS
insert into 课程信息
values(@coursename,@coursenumber,@teachernumber)
insert into 课程时间
values(@coursenumber,@coursetime,@roomnumber)
insert into 教室使用信息
values(@roomnumber,@coursetime,'有课',@coursenumber)
go

查询指定教室使用情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
create procedure classroom_query
@room varchar(5),
@time varchar(10),
@state varchar(10)='空闲' output
AS

select @state=状态
from 教室使用信息
where 教室编号=@room and 时间=@time
if @state IS NULL
set @state='空闲'
else if @state='有课'
begin
select @state=课程编号
from 教室使用信息
where 教室编号=@room and 时间=@time

end
go

少一个查询指定课程

借用存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
declare @state varchar(10)
go
create procedure borrow
@building varchar(5),
@room varchar(5),
@time varchar(10),
@reason varchar(10),
@state varchar(10) output
AS
declare @state1 varchar(10)
select @state1=状态
from 教室使用信息
where 教室编号=@room and 时间=@time
if @state1 IS NULL
begin
set @state1='空闲'

print '此时教室空闲,可以借用'
insert into 教室使用信息
values(@room,@time,@reason,'其他')
end
else
print '此教室被占用,正在'+@state1
set @state=@state1
print @state
go

一个例子

1
2
3
4
select *from 教室使用信息
declare @state varchar(10)
exec borrow '001','1102','周一三四','其他',@state output
print @state

判断密码是否正确

1
2
3
4
5
6
7
8
9
10
11
12
13
create procedure password_query
@user char(10),
@password varchar(15),
@state varchar(10)='false' output
AS
declare @password1 varchar(15)
select @password1=密码 from 学生信息
where 学号=@user
if @password1 IS NOT NULL and @password1=@password
set @state='true'
else
set @state='false'
go

删除课程

1
2
3
4
5
6
7
create procedure delete_course
@number varchar(7)
AS
delete from 课程信息 where 课程编号=@number
delete from 教室使用信息 where 课程编号=@number
delete from 课程时间 where 课程编号=@number

删除教师

1
2
3
4
5
6
7
8
9
10
create procedure delete_teacher
@number char(10)
AS
delete from 课程时间 where 课程编号 in(
select 课程编号 from 课程信息 where 教师编号=@number)
delete from 教室使用信息 where 课程编号 in(
select 课程编号 from 课程信息 where 教师编号=@number)
delete from 课程信息 where 教师编号=@number
delete from 教师信息 where 教师编号=@number

创建存储往学生信息插入大量数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
--创建循环插入10000条记录的存储过程
CREATE PROCEDURE CREATE_student
AS
declare @cnt INT=0;
while @cnt<10000
begin
declare @name varchar(15)
set @name=(SELECT LEFT(LOWER(NEWID()),8))
declare @password varchar(15)
set @password=(SELECT LEFT(LOWER(NEWID()),9))
declare @sex INT
set @sex=(SELECT 1 + RAND() * 2)
declare @sno char(10)
set @sno=replace(str(@cnt,10),' ','0')
declare @y INT
set @y=(SELECT 1 + RAND() * 6)
INSERT INTO 学生信息
VALUES
(
@sno,
@name
,CASE @sex --随机选取3个枚举值
when 1 then '男'
when 2 then '女'
END
,CASE @y --随机选取6个枚举值
when 1 then '001'
when 2 then '002'
when 3 then '003'
when 4 then '004'
when 5 then '005'
when 6 then '006'
END
,@password


);
set @cnt=@cnt+1;
end;

创建视图

创建视图,查询计算机学院邹老师所有课程名称

1
2
3
4
5
6
7
8
9
--创建视图,查询计算机学院邹老师所有课程名称
go
create VIEW view_邹
as
select 课程名称
from 课程信息
where 教师编号='0000000002'
go

DBMS

一.绪论

基于文件系统的数据管理方法

特点

1
2
数据存储于文件中
数据由应用程序经过文件系统进行管理

缺点

1
2
3
4
5
6
7
每当文件格式发生变化,就要修改应用程序
文件中存在冗余数据
文件修改可能造成数据不一致
文件修改可能破坏数据正确性
没有索引,只能扫描文件,数据访问效率低
只能对整个文件进行访问控制,数据安全性差
没有并发控制,多个应用程序同时读写文件可能产生冲突

基于数据库管理系统的数据管理方法

特点

1
2
数据存储在数据库中
数据由应用程序经过数据库管理系统进行管理

基于二者的对比

(1)FS:每当文件格式发生变化,就要修改应用程序

​ DBMS:只要数据模式不发生重大变化,应用程序基本无需修改

(2)FS:文件中存在冗余数

​ DBMS:冗余数据较少

(3)FS:文件修改可能造成数据不一致

​ DBMS:在数据库规范情况下基本不会造成

(4)FS:文件修改可能会破坏数据正确性

​ DBMS:会对数据更新进行完整行进检查

(5)FS:没有索引,访问效率低

​ DBMS:提供索引

(6)FS:只能对整个文件进行访问控制,数据安全性差

​ DBMS:可规定用户对于数据库哪一部分进行操作

(7)FS:文4没有并发控制

​ DBMS:提供并发控制机制

数据库功能

image-20220419155148171

数据库:有组织的、共享的、持久存储的数据集合。

数据库系统

由数据库、数据库管理系统、应用程序和数据库用户在一起构成的系统。

数据库的三层模式结构

数据库模式通常分三个层次定义,从低到高分别是:

内模式/存储模式

概念模式

外模式/视图

内模式/存储模式

描述数据库的物理存储结构和存取方式

数据库只有一个内模式

定义内模式时通常使用物理数据模型提供的概念

image-20220419161358869

概念模式

为全体数据库用户描述整个数据库的结构和约束

数据库只有一个概念模式

定义概念模式时使用实现数据模型提供的概念

image-20220419161406993

外模式/视图

从不同类别用户的视角描述数据库结构

可以有多个外模式

定义外模式时也可以使用实现数据模型提供的概念

模式映射

在三层模式结构中,不同层次模式之间的映射用于完成应用程序与数据库之间的数据转换和请求转换。

image-20220419161701579

分类

外模式-概念模式映射

概念模式-内模式映射

数据独立性

逻辑数据独立性

物理数据独立性

image-20220419161856014

数据库语言分类

数据定义语言

数据操作语言

事务

由数据库上的一系列操作完成的复杂任务,这些操作要么全执行,要么全不执行

性质

1
2
3
4
原子性
一致性
隔离性
持久性

并发控制

为了充分利用,允许多个事务并发执行。

多个事务并发可能会破坏数据一致性。

二.关系数据库

关系数据模型

三要素:关系数据结构、关系操作、关系完整性约束。

关系数据结构

关系中属性的个数即为关系的

只有符合客观实际的关系才是正确的关系。

:关系的某些属性集合具有区分不同元组的作用。

超键:可以唯一标识每个元组的属性。

候选键:任意真子集都不是超键的超键。即极小的超键。

主键:每个关系都有至少一个候选键,人为指定其中一个作为主键。

外键:设F为关系R的属性子集。若F与关系S的主键K相对,则称F为R的外键。

关系操作

查询语言的类型:关系代数、关系演算、结构化查询语言SQL。

关系完整性约束

完整性约束的类型:实体完整性、参照完整性、用户定义完整性。

实体完整性约束规则

1
主键值唯一且非空。

参照完整性约束

1
对于外键的约束,外键值为空或不为空则必须在S存在。

用户定义完整性约束

1
根据需求定义。

关系代数

image-20220429102419874

选择操作

image-20220429102724224

投影操作

image-20220429102802024

并操作

image-20220429102936467

差操作

image-20220429103101865

笛卡尔积操作

image-20220429103204733

笛卡尔积作用仅仅是将R和S无条件连接起来。

重命名操作

image-20220429103735239

派生关系代数操作

image-20220429103929302

交操作

image-20220429103955343

$\theta$连接

image-20220429104206279

image-20220429104313090

等值连接:连接条件仅涉及相等比较的连接称作等值连接。

自然连接

image-20220429104433735

自然连接与$\theta$连接的区别

自然连接 $\theta$连接
连接条件 隐含给出 明确给出
结果属性 去掉重复的同名属性 保留重名的同名属性

左外连接

image-20220429152859130

右外连接

image-20220429152930580

全外连接

image-20220429153001556

image-20220429153136222

扩展关系代数操作

image-20220429153530381

分组操作

image-20220429153851312

image-20220429154021150

eg:image-20220429154350259

赋值操作

image-20220429154424910

关系演算

image-20220429154749803

eg:image-20220429154903454

image-20220429155326624

eg:image-20220429155635735

三、结构化查询语言

SQL数据定义

声明用户定义完整性约束

1
2
3
4
规定属性值非空
规定属性值不重复
定义属性缺省值
规定属性值必须满足表达式给出的条件

定义视图

从用户视角所看到的数据

数据更新

修改:update 关系名 set

数据完整性检查

1
2
3
4
目的:数据修改可能导致数据库违反完整性约束,需要对数据完整性进行检查
功能:实体完整性检查
参照完整性检查
用户定义完整性检查

数据查询

选择查询条件

image-20220430151413245

image-20220430151423792

image-20220430151432387

image-20220430151614464

image-20220430152007869

image-20220430152148390

注意:空值判断,应用 is null,不可以用 =或者!=

集合操作

image-20220430152507160

查询结果排序

image-20220430152758643

限制查询结果数量

image-20220430153226417

聚集查询

image-20220430153259151

:聚集函数不能出现在where子句中

分组查询

image-20220430154427314

image-20220430154532489

注意事项

image-20220430154629326

连接查询

内连接

image-20220430154937567

image-20220430155011604

自然连接

image-20220430155059752

自连接

image-20220430155231450

外连接

image-20220430155522668

嵌套查询

image-20220430155907373

image-20220430162018068

使用exists关键字进行查询的时候,首先,我们先查询的不是子查询的内容,而是查我们的主查询的表,然后,根据表的每一条记录,依次去判断where后面的条件是否成立。

in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。

嵌套查询的写法

image-20220430162413322

派生

image-20220430162522047

四、概念数据库设计

数据库设计的过程

image-20220503171629777

实体-联系模型

实体-联系模型:简称ER模型,用于将现实世界抽象为实体及实体间的联系。

ER模型概念:

image-20220503194731246

与实体相关的概念

实体:数据库中表示的现实世界中的具体对象或事物。

属性:用于刻画实体的特性。

属性的类型

1
2
3
4
简单属性
复合属性
多值属性
派生属性

image-20220503195624675

实体型的ER图表示

image-20220503200250388

弱实体型:没有键属性的实体型。

标识实体型、属主实体型:由于弱实体型没有键属性,需要依赖于其他实体型进行区分。

标识联系型:弱实体型与其标识实体型通过标识联系型关联。

部分键:用于区分和同一标识实体相关联的弱实体的属性集合。

image-20220503201117189

与联系相关的概念

联系:一个联系表示多个实体之间有意义的关联关系。

联系型:同一类联系共同具有的类型。

联系型的度:参与到一个联系型中的实体型的个数。

联系集:数据库中当前存储的联系型的实例的集合。

image-20220503202245562

image-20220503202303200

联系型的约束

image-20220503202559606

存在依赖约束/参与度约束:刻画实体型参与到联系型中的最小基数。

联系型的属性

image-20220503204803972

多元联系:3个以上实体参与的联系

增强ER模型

image-20220503205006243

子类/超类

image-20220503205634485

不相交子类:若超类的每个实体属于最多一个子类,则子类是不相交的。

重叠子类:若超类的每个实体可以属于多个子类,则子类是重叠的。

全部特化:超类的每个实体必须属于至少一个子类。

部分特化;超类的某些实体可以不属于任何子类。

五、逻辑数据库设计

ER模型转换为关系数据库模式

实体型的转换

image-20220503211916414

复合属性的转换

image-20220503211959174

多值属性的转换

image-20220503212559635

弱实体型的转换

image-20220503213011437

M:N二元联系型的转换

image-20220503213209789

N:1二元联系型的转换

image-20220505150449415

1:1二元联系型的转换

与N:1相同

二元自联系型的转换

image-20220505150832315

标识联系型的转换

image-20220505151309647

设计不合理的关系可能产生的异常问题

1
2
数据更新问题
数据冗余问题

知识要点图

image-20220505152648076

函数依赖

定义

image-20220505153034089

image-20220505153146687

类型

image-20220505153456821

image-20220505154107287

函数依赖的公理系统

逻辑蕴含

image-20220505154619657

image-20220505154814471

image-20220505155016364

image-20220505155029011

image-20220505155051886

image-20220505155443317

等价函数依赖集

相关概念

image-20220505161038489

最小覆盖

image-20220505161611936

关系模式的范式

第一范式

若关系模式R的每个属性都是不可分的,则称R为第一范式关系模式。

存在问题

1
2
3
4
数据插入异常
数据删除异常
数据修改繁琐
数据冗余

原因

1
非主属性部分函数依赖于候选键

第二范式

image-20220505162809352

存在问题

1
2
3
4
数据插入异常
数据删除异常
数据修改繁琐
数据冗余

原因

1
非主属性传递函数依赖于候选键

第三范式

image-20220505163512256

存在问题

1
2
3
4
数据插入异常
数据删除异常
数据修改繁琐
数据冗余

原因

1
主属性部分依赖于候选键

BCNF

image-20220505164427068

消除主属性间的传递依赖。

关系模式分解

image-20220505221923466

分解准则1:无损连接性

image-20220505223653143

分解准则2:函数依赖保持性

image-20220505224121199

image-20220505224450639

无损连接性判定

image-20220505224650480

函数依赖保持性判定

image-20220505225103477

关系模式分解方法

image-20220505225520028

image-20220505225621412

image-20220505230144599

六、物理数据库设计

物理数据库设计概述

1
在逻辑数据库设计的基础上,为数据库中的关系选择合适的存储结构和存取方法,并进行数据库调优,使数据库上的事务能够高效执行。

image-20220517092422735

工作负载分析

工作负载是一组混合在一起的查询和更新。

选择度:满足条件的结果元组在全部候选元组中所占的比例。

索引设计

索引设计的基本过程

image-20220517093148475

索引设计的准则

1.是否建索引

image-20220517093239212

2.索引键的确定

image-20220517093413507

3.复合索引的设计

image-20220517093654977

B+树支持的查询

全值匹配:和所有索引属性进行匹配

匹配最左前缀:和前面几个索引属性进行匹配

匹配属性前缀:只匹配前缀属性的前缀部分

范围匹配:在给定范围内对前缀进行匹配

精确匹配某一属性并范围匹配另一属性

B+树还支持索引属性排序

B+树的限制

必须从B+树的最左属性开始匹配

条件中不能包含表达式

不能跳过B+树的属性

如果索引中有关某个属性的范围查询,则其右边所有属性都无法使用索引查找

覆盖索引

如果一个索引包含一个查询需要用到的所有属性,则称该索引为覆盖索引

image-20220517094732264

单个复合索引 vs 多个单属性索引

方案一:建立一个符合索引

方案二:建立多个单属性索引

多个单属性索引的缺点

1
2
3
没有在单个复合索引上做查询效率高
索引合并涉及排序,要消耗大量计算和存储资源
在查询优化时,索引合并的代价并不被计入,被低估了查询代价

4.是否使用聚簇索引

image-20220517105950271

  • 聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
  • 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因

不同存取路径区别

image-20220517110305889

image-20220517110324506

5.用哈希表还是B+树

image-20220517110351806

哈希表的限制

1
2
3
4
不支持部分索引属性匹配
只支持等值比较查询,不支持范围查询
无法用于排序
存在冲突

6.权衡索引代价维护

image-20220517110455031

7.不唯准则

image-20220517110521088

索引调优

MYSQL索引设计技巧1:前缀索引

image-20220517110623727

索引选择性:image-20220517110657824

MYSQL索引设计技巧2:聚簇索引

image-20220517110758667

MYSQL索引设计技巧3:伪哈希索引

image-20220517110906396

image-20220517110921919

内模式设计

关系是否采用聚簇索引?

若使用聚簇索引,应按哪些属性聚簇索引?

同聚簇索引设计准则。

查询改写

恒真/假的选择条件

含表达式的选择条件

image-20220517111330363

无用的去重操作

无用的分组操作:分组操作昂贵

无用的投影操作

无用的连接操作

临时关系:占用额外存储空间,且其上没有索引

嵌套查询;查询器优化嵌套查询能力弱

类型转换

概念模式调优

image-20220517111617834

image-20220517111626325

image-20220517111717761

image-20220517111725636

数据类型选择

1
2
3
1.尽量使用可以正确存储的最小数据类型
2.选择简单的数据类型
3.最好将属性声明为not null

标识符的选择

image-20220517111924723

1
2
3
整型:最好的选择,占用空间少,速度快
ENUM和SET:糟糕的选择,比较时转换为字符串,速度慢,MYSQL内部用整型来存储这两个类型的值,占用空间少
字符串型:糟糕的选择,空间大,速度慢

七、存储管理

按CPU访问存储介质的方式,可将存储器分为三类。

1
2
3
主存储器
二级存储器
三级存储器

主存

1
2
包括:寄存器、高速缓存、内存
主存特点:按字节寻址、可使用load/store指令直接访问

二级存储器

1
2
包括:磁盘/机械硬盘、闪存/固态硬盘
特点:按块寻址、联机使用 CPU无法直接访问,需用read、write将数据先复制到主存

三级存储器

1
2
包括:磁带、光盘、网络存储
脱机使用、按块存储、需先将数据复制到二级存储

存储层次间的数据传输

image-20220517140913250

数据局部性:同一单元的数据经常被同时访问到

虚拟内存不是存储层级中的一层。

按存储介质的易失性/持久性,可分为

1
2
易失性存储器:计算机重启后,易失性存储器的数据会丢失
菲易失性存储器

image-20220517141520177

持久性内存又称非易失性内存:按字节寻址、非易失

磁盘

image-20220517150119891

image-20220517150149305

image-20220517150221095

数据库的文件存储

将一个数据库存储为一个或多个文件;每个文件包含多个页。

数据库文件的页可以存储元组、元数据、索引、日志记录等。

1
大多数DBMS在一个页中只存储一种类型对象。

每个页拥有唯一编号,称作页号。

DBMS的存储管理器负责管理数据库文件

1
2
记录页中元组的读/写
记录页中的空闲空间

文件存储的分类

1
2
面向行的存储
面向列的存储

各种表示

image-20220517150756822

字符串image-20220517150806178

元组image-20220517150906343

元组头image-20220517150929367

元组数据image-20220517150952603

变长元组的布局image-20220517151016064

页布局image-20220517151037574

页头image-20220517151052727

页数据image-20220517151136047

面向元组的组织方法

分槽页是最常见的面向元组的数据组织方法

1
2
槽数据
元组序列

image-20220517151256195

image-20220517151329418

槽的元数据存储在页头中

1
2
槽的数量:用于确定下一个空闲槽的编号
最后一个槽的起始位置的偏移量:用于确定新元组的插入位置

记录号

image-20220517151514495

溢出页image-20220517151912914

页碎片化

1
随着元组删除或版本过期,其中会产生碎片:浪费磁盘空间、增加磁盘I/O

日志结构页布局

1
文件中只存储数据更新操作的日志记录,而不存储元组
1
2
3
4
新的日志记录只能写到文件末尾
插入操作的日志记录包含整个插入的元组
删除操作的日志记录包含被删除的元组的主键
修改操作的日志记录包含被修改的元组的主键,被修改的属性及修改后的属性值

读元组image-20220517153113658

日志记录索引image-20220517153153633

日志记录合并image-20220517153318250

文件组织

法一:堆文件组织

法二:顺序/有序文件组织

法三:哈希文件组织

堆文件组织

image-20220517154020888

基于链表的页组织方式

image-20220517154058030

基于页目录的堆文件页组织方式

image-20220517154149229

顺序/有序文件组织

image-20220517155245093

哈希文件组织

image-20220517155305809

缓冲区管理

image-20220517155330366

缓冲池的页称作页框

页表image-20220517155451024

DBMS用两个变量记录缓冲池中每个页框的状态

image-20220517155552825

image-20220517155602529

缓冲区功能

1
请求页;修改页;释放页

请求页

1.image-20220517155820278

2.image-20220517155834306

3.image-20220517155852966

实际在情况3下,DBMS会终止提出该请求的事务,为了避免资源浪费

页替换策略

image-20220517160334148

image-20220517160404076

image-20220517160413288

image-20220517160425855

image-20220517160437840

缓冲池与虚拟内存的相同点

image-20220517160507768

缓冲池与虚拟内存的不同点

1.image-20220517160644326

2.image-20220517160704040

面向行的存储image-20220517160738464

面向列的存储image-20220517160804399

缺点:面向列的存储适合于联机分析处理,不适合于联机事务处理。元组重构代价高,元组删除和修改代价高;解压代价

八、索引结构

索引

有序索引:通过按索引键有序排列索引项来实现索引

哈希索引:通过按索引键哈希值分桶来实现索引

有序索引image-20220517164143525

哈希索引image-20220517164528124

有序索引

根据数据文件中的元组是否按索引键值排序,分为聚簇索引与非聚簇索引。

聚簇索引

文件中的元组按索引键排序的,则索引为聚簇索引。

1
2
聚簇索引的索引键通常为关系主键;
一个关系通常只有一个聚簇索引

非聚簇索引

文件中的元组不按索引键排序的,则索引为非聚簇索引。

1
一个关系上可以有多个非聚簇索引

索引组织表

索引组织表=聚簇索引文件+数据文件

1
在索引组织表中,聚簇索引的索引项中存储元组本身,而不是地址

根据关系中每个元组在索引中是否都有一个对应索引项,可将有序索引分为两类:稠密索引、稀疏索引

稠密索引image-20220517165842013

稀疏索引image-20220517165923898

根据索引键是否为关系的主键,可将有序索引分为两类:主索引,二级索引

主索引

1
索引键为主键;一个关系只有一个

二级索引

1
2
索引键不是主键:
通常为非聚簇索引,一个关系可以有多个

其他索引及创建方法

创建主索引:image-20220517170535689

创建二级索引:image-20220517170606370

image-20220517170620535

唯一索引:索引键值不能重复image-20220517170648750

image-20220517170708910

外键索引image-20220517170727013

image-20220517170735536

image-20220517170745828

索引结构

有序索引结构

1
2
3
4
平衡树
跳表:多用于内存数据库系统
字典树:多用于内存数据库系统
日志结构合并树(LSM-tree):多用于NoSQL数据库系统的存储引擎

哈希索引数据结构

1
哈希表
哈希索引数据结构

外存哈希表image-20220517171037285

外存哈希表分类

image-20220517211355399

可扩展哈希表

image-20220517211456832

image-20220517211651367

插入

image-20220517212217097

image-20220517212500110

删除image-20220517212517570

线性哈希表

image-20220517214121658

image-20220517214211543

image-20220517214221085

image-20220517214245133

二者对比

image-20220517214259200

树索引结构
B+树

image-20220517214437003

image-20220517214541700

image-20220517214557404

B+树插入、删除,看教程,此处不详细说明。

B+树演示

1
https://cmudb.io/btree

其余

键压缩image-20220517214820891

前缀压缩image-20220517214843143

后缀截断image-20220517214926314

批量加载

image-20220517215000544

image-20220517215023090

LSM-Trees

B+树的原地更新image-20220517215143044

日志结构合并树image-20220517215251194

LSM树的基本结构image-20220517215332847

LSM的查找image-20220517215352335

缺点:当不可变文件非常大时,在文件上查找效率很慢

LSM的更新image-20220517215447877

分层LSM

image-20220517215513155

image-20220517215526939

image-20220517215545511

image-20220517215827832

image-20220517215845457

位图索引

image-20220517220627495

空间索引

image-20220517220638946

image-20220517220649102

九.查询执行

查询处理的基本过程

image-20220427155415469

原语操作:带有如何执行注释的关系代数操作。

查询执行计划:用于执行一个查询的原语操作序列

image-20220427162137086

外排

按照排序键对元组进行排序是DBMS非常重要的操作。

外排序image-20220517222109387

两趟多路外存归并排序

第一阶段:创建归并段

第二阶段:归并

记法image-20220517222433566

创建归并段image-20220517222516708

演示看PPT

算法分析image-20220517222852523

image-20220517222904328

多趟多路外存归并排序

image-20220517230415632

优化

image-20220517231952042

双缓冲image-20220517232002315

关系代数操作的执行

选择操作的执行

1
2
3
1.基于扫描的选择算法
2.基于哈希的选择算法
3.基于索引的选择算法

记法image-20220517232147225

基于扫描的选择算法

image-20220517232244556

image-20220517232257592

基于哈希的选择算法

前提image-20220517232530302

image-20220517232543905

image-20220517232551718

基于索引的选择算法

前提image-20220517232646680

image-20220517232703167

投影操作

image-20220517233036625

image-20220517233052558

去重操作

1
2
3
1.一趟去重算法
2.基于排序的去重算法
3.基于哈希的去重算法
一趟去重算法

image-20220518000726368

可在内存中用哈希表记录见过的元组,哈希键为整个元组。

image-20220518000816527

基于排序的去重算法

image-20220518000924102

image-20220518000947953

基于哈希的去重算法

image-20220518001143515

image-20220518001212003

聚集操作的执行

与去重一样

image-20220518001258445

集合差操作的执行

image-20220518001319436

一趟集合差算法

image-20220518001713665

image-20220518001802445

基于哈希的集合差算法

image-20220518001829640

image-20220518001850144

基于排序的集合差算法

image-20220518001912214

image-20220518001939501

连接操作的执行

image-20220518002200543

一趟连接算法

image-20220518002350004

image-20220518002448925

基于元组的嵌套循环连接

image-20220518002515100

image-20220518002602850

基于块的嵌套循环连接

image-20220518002627601

image-20220518002659923

排序归并连接

image-20220518002717370

image-20220518002834171

image-20220518002855040

经典哈希连接

image-20220518002921364

image-20220518002938211

image-20220518002946745

索引连接

image-20220518002958713

image-20220518003033410

查询计划的执行方法

image-20220518003117091

物化执行

image-20220518003143221

image-20220518003152780

流水线执行

image-20220518003224150

迭代器模型

image-20220518003921085

image-20220518003946545

image-20220518004014141

image-20220518004026684

十、查询优化

概论

查询优化:将一个关系代数表达式转换成一个可以快速执行的查询执行计划的过程。

查询优化的两个阶段:

1
2
逻辑查询优化;
物理查询优化;

逻辑查询计划:关系代数表达式

物理查询计划:带有“如何执行”注释的关系代数表达式

逻辑查询计划

代价image-20220519183907961

基于代价的查询优化

image-20220519184002601

查询计划枚举

image-20220519184108647

等价关系代数表达式

若两个关系代数式在任意数据库实例上的结果都相同,则这两个关系代数表达式等价。

关系代数表达式的等价变换规则

image-20220519184243787

$\theta$连接满足交换律,但不满足结合律。

image-20220519185127015

image-20220519185213924

image-20220519185228111

选择下推

image-20220519185536712

image-20220519185545426

image-20220519185557599

image-20220519185715855

有关投影的等价变换规则

image-20220519185920703

image-20220519185930743

投影下推

image-20220519190034491

image-20220519190144113

逻辑查询计划的代价模型

image-20220519190427400

逻辑查询计划的代价模型 VS 物理查询计划的代价模型

image-20220519190615185

基数估计

基数估计:估计查询结果的元组数

要求:准确;易计算;逻辑一致

逻辑一致性

1
2
单调性:一个操作的输入越大,操作结果的基数估计值越大
顺序无关性:最终结果与操作的执行顺序无关

image-20220519191017939

笛卡尔积操作的基数估计

投影操作数的基数估计

image-20220519191306473

选择操作的基数估计

image-20220519191449704

image-20220519191601407

二路自然连接的基数估计

image-20220519192052101

image-20220519192200710

image-20220519192215171

image-20220519192235596

集合操作的基数估计

image-20220519192916500

去重操作的基数估计

image-20220519193626982

属性值分布的精确近似

实际数据经常不满足均匀分布假设,导致基数估计的误差较大

直方图

image-20220519194206594

等宽直方图

image-20220519194229968

等高直方图

image-20220519194607250

压缩直方图

image-20220519194634006

连接顺序优化

连接关系的角色

image-20220519194857979

连接树

image-20220519195058941

左深连接树

image-20220519195259430

image-20220519195313193

image-20220519195321923

物理查询优化

image-20220519202315805

确定选择操作的物理执行算法

image-20220519202349918

索引扫描+过滤

image-20220519205009643

image-20220519205127235

多索引扫描+求交集

image-20220519205217297

image-20220519205439888

仅用索引

image-20220519205531523

image-20220519205539303

顺序扫描

image-20220519205556825

确定连接操作的物理执行算法

image-20220519205743686

一趟连接:适用于左关系可以全部读入缓冲池的可用页面。

索引连接:适用于左关系较小,右关系在连接属性上建有索引

排序归并连接:image-20220519210506654

哈希连接:image-20220519210520826

嵌套循环连接:image-20220519210536440

查询计划的执行模型

十一、并发控制

事务

image-20220519212340392

image-20220519212507673

事务的ACID性质

image-20220519212554791

持久性image-20220519212707574

一致性image-20220519212814773

隔离性image-20220519213222386

并发控制

调度

调度:调度是一个或多个事务的重要操作的序列。

串行调度:如果一个调度中不同事务的操作没有交叉,则该调度是串行调度

调度的正确性:单独执行每个事务都会将数据库从一种一致状态变为另一种一致状态

串行调度的正确性:任意串行调度都能保持数据库的一致性;不同的串行调度可能导致数据库处于不同的状态,但都是一致状态

异常

image-20220519215904279

脏写image-20220519220347168

脏读image-20220519220448009

不可重复读image-20220519220547543

等价调度

image-20220519220707492

可串行化调度

image-20220519221456198

可串行化调度的优点

image-20220519221529843

可串行化调度的缺点

image-20220519221843259

并发控制隔离级别

image-20220519222317093

在不同隔离级别下,一个事务修改过的对象的值对其他并发事务的可见程度不同

读未提交

未提交事务所做的修改对其他事务可见。

此级别下的异常

image-20220519222909526

读提交

只有已提交的事务所做的修改才对其他事物可见。

此级别下的异常

image-20220519223035088

可重复读

image-20220519223105963

此级别下的异常

image-20220519223154576

可串行化

image-20220519223217827

并发控制可串行化

冲突可串行化

image-20220519224200957

冲突

image-20220519224214607

image-20220519224702770

image-20220519224714126

image-20220519224722572

冲突等价

image-20220519224820353

冲突可串行化调度

image-20220519230707353

image-20220519231007196

image-20220519231147648

冲突可串行化测试

image-20220520091113545

视图可串行化比冲突可串行化松

并发控制协议

image-20220520091257930

并发控制协议分类

image-20220520091349724

基于锁的并发控制

image-20220520091554618

image-20220520091633199

image-20220520092008232

image-20220520092526558

两阶段锁协议

image-20220520093042993

基于2PL的调度是冲突可串行化调度

2PL的优缺点image-20220520093240929

级联终止image-20220520093334450

强两阶段锁SS2PL

image-20220520093452468

严格调度

image-20220520093543437

死锁

image-20220520094343334

死锁处理image-20220520094527771

死锁检测

image-20220520094601102

等待图

image-20220520094658374

死锁解除

image-20220520094725361

image-20220520094805814

死锁预防

image-20220520094926324

image-20220520095012899

image-20220520095107351

锁的效率问题

image-20220520095206317

锁的粒度

image-20220520095531284

意向锁

image-20220520095555600

相容矩阵

image-20220520095701510

多粒度锁协议

image-20220520100018302

锁升级

image-20220520100856436

幻读

动态数据库

image-20220520101217338

幻读image-20220520101317415

谓词锁

image-20220520101448152

next- key锁

image-20220520101509887

时间戳

image-20220520101553945

Basic TO

image-20220520101644060

image-20220520101739969

image-20220520101903477

image-20220520102008025

Thomas写规则

image-20220520102358567

image-20220520102654252

不可恢复调度

image-20220520102743606

Basic不足

image-20220520102950657

OCC(不重要)

image-20220520103139742

MVCC多版本并发控制

image-20220520103408606

只有写和写冲突。

十二、故障恢复

故障

image-20220520120415337

故障类型image-20220520120612468

事务故障

image-20220520120624784

系统故障

image-20220520120733427

存储介质故障

image-20220520120848519

缓冲池策略

image-20220520121202370

image-20220520122101774

steal/no-steal 策略

image-20220520122333980

force/no-force 策略

image-20220520122359902

no-force是不强制在提交前写回磁盘

no-steal是不允许在事务提交前写回磁盘

缓冲池策略

image-20220520122444003

image-20220520122920391

WAL

预写式日志(write-ahead log)WAL

image-20220520123122163

image-20220520123227057

只有当日志写到磁盘上,才能代表事务提交。

基于WAL的故障恢复

image-20220520123548000

事务的分类

image-20220520123612422

故障恢复时的行为

image-20220520123644356

WAL协议分类

image-20220520123737682

Undo Logging

image-20220520124852811

image-20220520123924132

故障恢复image-20220520124322486

image-20220520124333092

Redo Logging

image-20220520124907272

image-20220520124925559

故障恢复image-20220520125117852

image-20220520125328930

Redo+Undo Logging

image-20220520125503308

image-20220520125645629

故障恢复image-20220520125840485

image-20220520125856446

策略比较image-20220520130139202

组提交

image-20220520130353055

检查点

WAL的问题image-20220520130526774

检查点

image-20220520130820555

模糊检查点

image-20220520130844271

涉及检查点的故障恢复

image-20220520131212794

image-20220520131244758

image-20220520131254766

碳排放量数据统计

14-19年可通过CEAD获取

1
https://www.ceads.net.cn/news/20211256.html

1990-2015年的数据,可以通过MEIC获取

1
http://meicmodel.org/?page_id=560

注:MEIC可以获取碳排放量统计图片

对于之后的数据获取方法:

法一:

通过

WheatA小麦芽 - 农业气象大数据

例如想知道杭州城区历年的二氧化碳排放量有多少,如图所示。

image-20220418201114279

图1显示的是一个全球大气污染排放数据调用界面,我们把坐标定位到杭州城区东站附近(坐标:120.15°E,30.35°N),获取该地2020年逐月的CO2排放量数据,如图所示。

image-20220418201138181

图2显示了杭州市中心地段2020年逐月的CO2排放量,可以看到2020年1月该地区CO2总排放量为3.9kg/m2,按杭州城区面积560平方公里算,可推测出2020年1月城区二氧化碳总排放量约为200万吨。

法二:

根据各省市统计年鉴计算。

如果用IPCC的算法的话,一般情况下用的都是能源平衡表,也就是用终端消费量来算各种能源的二氧化碳排放量。

挂一个可能有用的网站,碳排放交易网。

法三:

1
https://blog.csdn.net/samLi0620/article/details/123499971

1997-2020年(其中2018-2020年为插值法估计)

(29.9元)

任务管理

任务管理概述

一个任务是一个处理器可以调度、执行和暂停的工作单位。它可以用来执行一个程序,一个任务或进程,一个操作系统服务工具,一个中断或异常处理程序,或一个内核或执行实用程序。

IA-32结构提供了一种机制,用于保存任务的状态,调度任务的执行,以及从一个任务切换到另一个任务。当在保护模式下运行时,所有的处理器执行都是在任务内进行的,即使是简单的系统也必须至少定义一个任务。更复杂的系统可以使用处理器的任务管理设施来支持多任务的应用。

一个过程调用包括将数据(以参数返回值的形式)与控制从代码的一部分传递到另一部分。除此之外,在进入时为过程的局部变量分配空间,在退出的时候释放这些空间。数据传递、局部变量的分配和释放通过操纵程序栈来实现。

操作系统实现宏观上并行任务的效果,其本质是微观上在多个任务之间切换。因此,当操作系统由任务A切换到任务B时,需要暂停任务A的执行,并将处理器执行任务A时各个寄存器的值保存到内存的某个位置上,这个过程叫做保存现场;之后将处理器上一次执行任务B时各个寄存器的值由内存中的某个位置回复到处理的寄存器当中,这个过程叫做恢复现场。当操作系统在调度时由任务A切换到任务B时,对任务A保存现场,对任务B恢复现场,这个整体的过程称之为:上下文切换。

在每一个任务在执行之前,操作系统都需要为其分配一个专属的内存区域供其使用,这个内存区域通常被称为此任务的栈(stack)。Cortex-M有两个堆栈寄存器,主栈指针(MSP)与进程栈指针(PSP)。主程序操作系统和各个中断函数使用的是MSP指针,而各个被调度的任务(进程)使用的是PSP指针。本质上它是处理器的一个寄存器,PSP寄存器的值就是内存中任务的栈地址。

任务的结构

一个任务由两部分组成:一个任务执行空间和一个任务状态段(TSS)。任务执行空间由一个代码段、一个堆栈段和一个或多个数据段组成(见图7-1)。如果操作系统或执行程序使用处理器的特权级别保护机制,任务执行空间也会为每个特权提供一个单独的堆栈。
TSS指定了组成任务执行空间的段,并为任务状态信息提供了一个存储位置信息。在多任务系统中,TSS还提供了一种连接任务的机制。
一个任务由其TSS的段选择器来识别。当一个任务被加载到处理器中执行时,它的段选择器、基地址、限制和段描述符属性被加载到任务的寄存器。如果任务实现了分页,任务所使用的页面目录的基地址被加载到控制寄存器CR3。

image-20220414193049801

任务状态

以下项目定义了当前执行的任务的状态:

  • 任务的当前执行空间,由段寄存器(CS、DS、SS、ES、GS、FS和GS)中的段选择器定义。
  • 通用寄存器的状态。
  • EFLAGS寄存器的状态。
  • EIP寄存器的状态。
  • 控制寄存器CR3的状态。
  • 任务寄存器的状态。
  • LDTR寄存器的状态。
  • I/O地图的基址和I/O地图(包含在TSS中)。
  • 特权0、1和2堆栈的堆栈指针(包含在TSS中)。
  • 与先前执行的任务的链接(包含在TSS中)。
    在调度任务之前,所有这些项目都包含在任务的TSS中,除了任务寄存器的状态。另外,LDTR寄存器的全部内容不包含在TSS中,只有LDT的段选择器。

任务的执行

软件或处理器可以通过以下方式之一调度一个任务的执行。

  • 用CALL指令明确调用一个任务。
  • 用JMP指令显式跳转到一个任务。
  • 隐式调用(由处理器)到一个中断处理任务。
  • 对一个异常处理任务的隐式调用。
  • 当EFLAGS寄存器中的NT标志被设置时,返回(用IRET指令启动)。

所有这些调度任务的方法都是用一个段选择器来识别要调度的任务,这个段选择器指向任务门或任务的TSS。当用CALL或JMP指令调度任务时,指令中的选择器可以直接选择TSS或持有TSS的选择器的任务门。当调度一个任务来处理一个中断或异常时,中断或异常的IDT条目必须包含一个任务门,它持有中断或异常处理程序TSS的选择器。
当一个任务被调度执行时,在当前运行的任务和被调度的任务之间会发生一个任务切换。在任务切换期间,当前执行的任务的执行环境(称为任务的状态或上下文)被保存在其TSS中,任务的执行被暂停。被派遣任务的上下文被加载到处理器中,该任务的执行从新加载的EIP寄存器所指向的指令开始。如果任务在系统上次初始化后没有运行过,EIP将指向任务代码的第一条指令;否则,它将指向任务最后执行的指令之后的下一条指令。
如果当前执行的任务(调用任务)调用了被派发的任务(被调用任务),则段选择器被存储在被调用任务的TSS中,以提供与调用任务的链接。
对于所有IA-32处理器,任务不是递归的。一个任务不能调用或跳转到自身。中断和异常可以通过任务切换到一个处理任务来处理。在这里,处理器执行一个任务来处理中断或异常,从中断处理任务或异常处理任务返回后,自动切换回被中断的任务。这种机制也可以处理在中断任务中发生的中断。
作为任务切换的一部分,处理器也可以切换到另一个LDT,允许每个任务对基于LDT的段有不同的逻辑到物理地址的映射。在任务切换时,页面目录基础寄存器(CR3)也被重新加载,允许每个任务有它自己的一套页表。这些保护设施有助于隔离任务并防止它们相互干扰。
如果不使用保护机制,处理器不提供任务之间的保护。这一点即使在操作系统也是如此,该系统使用多个特权级别进行保护。一个运行在特权级别3的任务,使用与其他任务相同的LDT和页表。

任务的数据结构

处理器定义了五个数据结构来处理与任务有关的活动。

  • 任务状态段(TSS)。
  • 任务门描述符。
  • TSS描述符。
  • 任务寄存器。
  • EFLAGS寄存器中的NT标志。

当在保护模式下运行时,必须为至少一个任务创建一个TSS和TSS描述符,并且TSS的段选择器必须被加载到任务寄存器中(使用LTR指令)。

任务状态段 Task-State Segment (TSS)

恢复一个任务所需的处理器状态信息被保存在一个叫做任务状态段(TSS)的系统段中。图7-2显示了为32位CPU设计的任务的TSS的格式。TSS的字段被分为两个主要类别:动态字段和静态字段。
image-20220414195850785

在任务切换期间,当一个任务被暂停时,处理器会更新动态字段。以下是动态字段。

  • 通用寄存器字段 - EAX, ECX, EDX, EBX, ESP, EBP, ESI, 和 EDI 寄存器在任务切换前的状态。
  • 分段选择器字段—在任务切换前存储在ES、CS、SS、DS、FS和GS寄存器中的分段选择器。
  • EFLAGS寄存器字段 - 任务切换前EFAGS寄存器的状态。
  • EIP(指令指针)字段 - 任务切换前EIP寄存器的状态。
  • 前一个任务链接字段—包含前一个任务的TSS的段选择器(在由调用、中断或异常启动的任务切换中更新)。这个字段(有时被称为后端链接字段)允许通过使用IRET指令将任务切换到前一个任务。处理器读取静态字段,但通常不改变它们。这些字段是在一个任务被创建时设置的。
    以下是静态字段。
  • LDT段选择器字段 - 包含任务的LDT的段选择器。
  • CR3控制寄存器字段 - 包含任务要使用的页面目录的基本物理地址。控制寄存器CR3也被称为页面目录基础寄存器(PDBR)。
  • 权限级别-0、-1和-2的堆栈指针字段—这些堆栈指针包括一个逻辑地址,由堆栈段的段选择器(SS0、SS1和SS2)和堆栈的偏移量(ESP0, ESP1和ESP2)组成。注意,这些字段的值对于一个特定的任务来说是静态的;而SS和ESP的值会在任务中发生堆栈切换时改变。
  • T(调试陷阱)标志(字节100,位0)—当设置时,T标志会使处理器在任务切换到这个任务时引发一个调试异常。
  • I/O地图基址字段 - 包含从TSS的基点到I/O权限位的图和中断重定向位图的16位偏移。当存在时,这些地图以更高的地址存储在TSS中。
  • 避免在处理器在任务切换时读取的TSS部分(前104字节)放置页面边界。如果边界出现在这个区域,处理器可能无法正确执行地址转换。在任务切换过程中,处理器在每个TSS的前104个字节中进行读写(使用连续的物理地址,从任务的物理地址开始)。所以,在TSS访问开始后,如果104字节中的一部分 不是物理上连续的,处理器将访问不正确的信息,而不会产生页面错误异常。
  • 与前一个任务的TSS、当前任务的TSS相对应的页面,以及每个任务的描述符表项都应该被标记为读/写。

如果包含这些结构的页面在任务切换开始前就已经存在于内存中,那么任务切换的速度会更快。

TSS 描述符

TSS,像所有其他段一样,是由段描述符定义的。图7-3显示了TSS的格式 。TSS描述符只能放在GDT中,它们不能放在LDT或IDT中。
试图使用设置了TI标志(表示当前的LDT)的段选择器访问一个TSS,会导致在CALLs和JMPs期间会产生一个一般保护异常(#GP);在IRETs期间会产生一个无效的TSS异常(#TS)。如果试图将一个TSS的段选择器加载到一个段寄存器中,也会产生一般保护异常。
类型字段中的繁忙标志(B)表示任务是否繁忙。一个繁忙的任务目前正在运行或暂停。类型字段的值为1001B表示一个不活动的任务;值为1011B表示一个繁忙的任务。
处理器使用繁忙标志来检测调用一个执行被中断的任务的尝试。为了确保只有一个繁忙标志与一个任务相关联,每个TSS应该只有一个TSS描述符指向它。

image-20220414201925534

基数、极限和DPL字段以及粒度和当前标志的功能与它们在数据段描述符中的使用类似。当32位TSS描述符中的G标志为0时,极限字段必须是32位TSS描述符中的极限。TSS描述符中G标志为0时,极限字段的值必须等于或大于67H,比TSS的最小尺寸少一个字节。
试图切换到一个TSS描述符的极限值小于67H的任务,会产生一个无效的TSS异常(#TS)。如果包括一个I/O权限位图或操作系统存储了额外的数据,则需要一个更大的限制。处理器不检查任务开关上是否有大于67H的限制;但是,当访问I/O权限位图或中断重定向位图时,它将进行检查。
任何可以访问TSS描述符的程序或过程(即其CPL在数字上等于或小于的DPL)可以通过调用或跳转来调度任务。
在大多数系统中,TSS描述符的DPL被设置为小于3的值,因此只有特权软件才能进行任务切换。然而,在多任务应用程序中,一些TSS描述符的DPLs可能被设置为3,以便允许在应用程序(或用户)权限级别进行任务切换。

任务寄存器

任务寄存器持有16位段选择器和整个段描述符(32位基本地址(在IA-32e模式下为64位 ),16位段限制和描述符属性),用于当前任务的TSS。
这个信息是从当前任务的GDT中的TSS描述符中复制过来的。图7-5显示了处理器访问TSS的路径 (使用任务寄存器中的信息)。任务寄存器有一个可见的部分(可以被软件读取和改变)和一个不可见的部分(由处理器维护,不能访问)。可见部分的段选择器指向GDT中的一个TSS描述符。处理器使用任务寄存器的不可见部分来缓存段描述符 。在寄存器中缓存这些值使得任务的执行更加有效。LTR(加载任务
寄存器)和STR(存储任务寄存器)指令加载和读取任务寄存器的可见部分。
LTR指令将段选择器(源操作数)加载到任务寄存器中,指向GDT中的TSS描述符。然后它用TSS描述符的信息加载任务寄存器的不可见部分。LTR是一个 特权指令,只有当CPL为0时才能执行。之后,当任务切换发生时,任务寄存器的内容会被隐含地改变。
STR(存储任务寄存器)指令将任务寄存器的可见部分存储在一个通用寄存器或内存中。这条指令可以被运行在任何权限级别的代码执行,以识别当前的运行的任务。然而,它通常只被操作系统软件使用。在处理器上电或复位时,段选择器和基地址被设置为默认值0;极限值
被设置为FFFH。

image-20220414203302131

任务门描述符

任务门描述符提供了对一个任务的间接的、受保护的引用(见图7-6)。它可以被放置在GDT、LDT或IDT中。任务门描述符中的TSS段选择器字段指向GDT中的一个TSS描述符。该段选择器中的RPL不被使用。任务门描述符的DPL在任务切换期间控制对TSS描述符的访问。当一个程序或过程通过任务门调用或跳转到一个任务时,指向任务门的门选择器的CPL和RPL域必须小于或等于任务门描述符的DPL。请注意,当任务门被使用时 ,目标TSS描述符的DPL不被使用。

image-20220414204423254

一个任务可以通过一个任务门描述符或一个TSS描述符来访问。这两种结构都满足以下需求。

  • 一个任务只需要一个繁忙标志 - 因为一个任务的繁忙标志是存储在TSS描述符中,每个任务应该只有一个TSS描述符。然而,可能有几个任务门会引用同一个TSS描述符。
  • 需要提供对任务的选择性访问—任务门满足这一需求,因为它们可以驻留在一个LDT中,并且可以有一个与TSS描述符的DPL不同的DPL。一个程序或过程如果没有足够的权限访问GDT中任务的TSS描述符(通常DPL为0)的程序或过程可以通过一个具有更高DPL的任务门来访问该任务。任务门给了操作系统更大的限制对特定任务的访问的自由度。
  • 需要一个独立的任务来处理中断或异常 - 任务门也可以驻留在IDT中。在IDT中,它允许中断和异常由处理任务来处理。当一个中断或异常向量指向一个任务门时,处理器会切换到指定的任务。图7-7说明了LDT中的任务门、GDT中的任务门和IDT中的任务门如何都能指向同一个任务。

image-20220414210542784

任务切换

处理器在四种情况中的一种将执行转移到另一个任务。

  • 当前程序、任务或过程执行JMP或CALL指令到GDT中的TSS描述符。
  • 当前程序、任务或过程执行JMP或CALL指令到GDT或当前LDT中的任务门描述符。
  • 中断或异常向量指向IDT中的一个任务门描述符。
  • 当EFLAGS寄存器中的NT标志被设置时,当前任务执行一个IRET。JMP、CALL和IRET指令,以及中断和异常,都是重定向程序的机制。对TSS描述符或任务门的引用(当调用或跳转到一个任务时)或NT标志的状态(当执行IRET时)都是重定向的机制。NT标志的状态(执行IRET指令时)决定是否发生任务切换。当切换到一个新的任务时,处理器会执行以下操作:
  1. 获得新任务的TSS段选择器,作为JMP或CALL指令的操作数,从任务门或前一个任务链接字段(对于用IRET指令启动的任务切换)获得新任务的TSS段选择器。
  2. 检查当前(旧)任务是否被允许切换到新任务。数据访问权限规则适用于JMP和CALL指令。当前(旧)任务的CPL和新任务的段选择器的RPL必须小于或等于被引用的TSS描述符或任务门的DPL。例外的情况,中断(由INT n指令产生的中断除外)和IRET指令被允许切换任务,而不考虑TSS描述符的DPL。对于INT n指令产生的中断,要检查DPL。
  3. 检查新任务的TSS描述符是否被标记为存在,并且有一个有效的限制(大于或等于67H)。
  4. 检查新任务是否可用(调用、跳转、异常或中断)或繁忙(IRET返回)。
  5. 检查当前(旧)TSS、新TSS和任务切换中使用的所有段描述符是否被分页到系统内存中。
  6. 如果任务切换是由JMP或IRET指令启动的,处理器将清除当前(旧)任务的TSS中的忙(B)标志;如果用CALL指令、异常或中断启动:忙(B)标志保持不变。
  7. 如果任务切换是由IRET指令启动的,处理器将清除EFLAGS寄存器中临时保存的NT标志;如果是由CALL或JMP指令、异常或中断启动的,则NT标志在EFLAGS寄存器中保持不变。
  8. 在当前任务的TSS中保存当前(旧)任务的状态。处理器在任务寄存器中找到当前TSS的基地址 ,然后将下列寄存器的状态复制到当前的TSS中:所有的通用寄存器,段寄存器中的段选择器,临时保存的EFLAGS寄存器的映像,以及指令指针寄存器(EIP)。
  9. 如果任务切换是由CALL指令、异常或中断启动的,处理器将设置EFLAGS寄存器中的NT标志。如果是用IRET指令或JMP指令启动的,NT标志将反映新任务中加载的EFLAGS的NT状态(见表7-2)。
  10. 如果任务切换是由CALL指令、JMP指令、异常或中断启动的,处理器就会在新任务的TSS描述符中设置繁忙(B)标志;如果是由IRET指令启动的,繁忙(B)标志就保持不变。
  11. 用段选择器和新任务的TSS的描述符加载任务寄存器。
  12. TSS状态被加载到处理器中。这包括LDTR寄存器,PDBR(控制寄存器CR3),EFLAGS寄存器,EFLAGS寄存器,
    EIP寄存器,通用寄存器,以及段选择器。在这个状态的加载过程中出现的故障可能会破坏架构状态。(如果没有启用分页,PDBR值会从新任务的TSS中读出,但它不会被加载到CR3中)。
  13. 与段选择器相关的描述符被加载和限定。与此相关的任何错误都发生在新任务的上下文中,并可能破坏架构状态。

注意事项
如果所有的检查和保存都成功进行了,处理器就会提交给任务开关。如果在步骤1到11中发生了不可恢复的错误,处理器不会完成任务切换,并确保处理器返回到执行启动任务切换的指令之前的状态。
如果一个不可恢复的错误发生在步骤12,架构状态可能会被破坏,但会试图将在先前的执行环境中处理该错误。如果一个不可恢复的错误发生在提交点之后(在步骤13),处理器完成了任务切换(不执行额外的访问和段可用性检查),并在开始执行新的任务之前产生适当的异常。
如果异常发生在提交点之后,异常处理程序必须完成任务切换本身然后才允许处理器开始执行新的任务。

  1. 开始执行新任务。(对于异常处理程序来说,新任务的第一条指令似乎没有被执行)。

当一个成功的任务切换发生时,当前执行的任务的状态总是被保存。如果该任务被恢复 ,执行将从保存的EIP值所指向的指令开始,并且寄存器被恢复到 任务暂停时的值。
当切换任务时,新任务的权限级别不会继承被暂停的任务的权限级别。新的任务以CS寄存器的CPL字段中指定的权限级别开始执行,CS寄存器是由TSS加载的。因为任务被它们独立的地址空间和TSS所隔离,并且因为特权规则控制对TSS的访问,所以任务在执行时,需要有足够的权限。
表7-1显示了处理器在切换任务时检查的异常条件。它还显示了如果检测到错误,每个检查都会产生异常,以及错误代码所引用的段。
image-20220414215039998

image-20220414215048323

注意

  1. NP是段不存在异常,#GP是一般保护异常,#TS是无效TSS异常,#SS是堆栈故障异常。

  2. 错误代码包含了这一列中引用的段描述符的索引。
  3. 如果一个段选择器在一个兼容类型的表中(GDT或LDT),在表的段限制内占据一个地址,那么它是有效的。
    并且指向兼容的描述符类型(例如,CS寄存器中的段选择器只有当它指向代码段描述符时才有效)。

每次发生任务切换时,控制寄存器CR0中的TS(任务切换)标志被设置。在产生浮点异常时,系统软件使用TS标志来协调浮点单元与处理器其他部分的行动。

任务链

TSS的前一个任务链接字段(有时称为 “反向链接”)和EFLAGS寄存器中的NT标志被用来返回到前一个任务的执行。EFLAGS.NT=1表示当前执行的任务被嵌套在另一个任务的执行中。
当CALL指令、中断或异常导致任务切换时:处理器将当前TSS的选择器复制到新任务的TSS的前一个任务链接字段;然后设置EFLAGS.NT=1。如果软件使用IRET指令来暂停新任务,处理器检查EFLAGS.NT=1;然后使用
它使用前一个任务链接字段中的值来返回到前一个任务。见图7-8。
当JMP指令引起任务切换时,新任务不被嵌套。前一个任务链接字段不被使用,并且EFLAGS.NT=0。当不需要嵌套时,使用JMP指令来调度一个新任务。

image-20220415161736123

表7-2显示了任务切换过程中的繁忙标志(在TSS段描述符中)、NT标志、前一个任务链接字段和TS标志(在控制寄存器CR0中)在任务切换期间。
NT标志可以被任何权限级别的软件所修改。一个程序有可能在设置NT标志的同时执行IRET指令。这可能会随机地调用当前任务的TSS的前一个链接字段中指定的任务。为了防止这种虚假的任务切换成功,操作系统应该把它所创建的每个TSS中的前一个任务链接字段初始化为0。

image-20220415162023949

使用繁忙标志来防止递归任务的切换

一个TSS只允许为一个任务保存一个上下文;因此,一旦一个任务被调用(派发),对任务的递归(或重入)调用该任务将导致该任务的当前状态丢失。TSS段中的繁忙标志 是为了防止重入式任务切换和随后的任务状态信息的丢失。处理器对繁忙标志的管理如下 :

  1. 当调度一个任务时,处理器设置新任务的繁忙标志。
  2. 如果在任务切换过程中,当前任务被放置在一个嵌套链中(任务切换是由一个CALL指令、一个中断或异常产生的),那么新任务的繁忙标志将被设置。
  3. 当切换到新的任务时(由CALL指令、中断或异常启动),处理器产生一个一般保护异常。如果新任务的繁忙标志已经被设置,处理器会产生一个一般保护的异常(#GP)。如果任务切换是由IRET指令发起的,那么异常就不会产生,因为处理器希望繁忙标志被设置。
  4. 当一个任务被跳转到一个新的任务(由任务代码中的JMP指令发起)或由任务代码中的IRET指令终止时,将产生一个异常。任务代码中的IRET指令终止时,处理器会清除繁忙标志,使任务回到 “不忙 “状态。

处理器通过防止一个任务切换到它自己或一个嵌套的任务链中的任何任务来防止递归任务切换。由于多个调用、中断或异常,嵌套的暂停任务链可能增长到任何长度。如果一个任务在这个链中,忙碌标志会阻止它被调用。繁忙标志可以在多处理器配置中使用,因为处理器遵循一个LOCK协议(在总线上或缓存中),当它设置或清除繁忙标志时。这个锁使两个处理器不会同时调用同一个任务。

修改任务链

在单处理器系统中,如果有必要从链接的任务链中删除一个任务,请使用以下程序来删除
使用以下程序来删除任务。

  1. 禁用中断。
  2. 改变抢占式任务(暂停要删除的任务的任务)的TSS中的前一个任务链接字段。假设抢占式任务是要删除的任务链中的下一个任务(较新的任务)。改变前一个任务的链接字段,使其指向链中下一个最老的任务的TSS,或者指向链中更老的任务。
  3. 清除被删除的任务的TSS段描述符中的繁忙(B)标志。如果有一个以上的任务被从链上删除,必须清除每个被删除的任务的繁忙标志。
  4. 启用中断。

在多进程系统中,必须在此过程中增加同步和序列化操作,以确保在改变前一个任务链接字段时,TSS和它的段描述符都被锁定并且繁忙标志被清除。

任务地址空间

一个任务的地址空间由该任务可以访问的段组成。这些段包括代码、数据、堆栈和在TSS中引用的系统段以及任务代码所访问的任何其他段。这些段被映射到处理器的线性地址空间,而线性地址空间又被映射到处理器的物理地址空间(直接或通过分页)。
TSS中的LDT段字段可以用来给每个任务提供它自己的LDT。给予一个任务它自己的LDT允许任务地址空间与其他任务隔离,将与该任务相关的所有段描述符放在该任务的LDT中。也可以让几个任务使用同一个LDT。这是一种节省内存的方式,允许特定的任务互相通信或控制,而不丢掉整个系统的保护屏障。因为所有的任务都可以访问GDT,所以也有可能创建共享段,通过该表的段描述符来访问。
如果分页功能被启用,TSS中的CR3寄存器(PDBR)字段允许每个任务有自己的一套页表,用于将线性地址映射到物理地址。或者,几个任务可以共享同一组页表。

将任务映射到线性和物理地址空间

任务可以通过两种方式之一被映射到线性地址空间和物理地址空间。

  • 一个线性到物理地址空间的映射在所有任务之间共享。- 当分页未被启用时,这是唯一的选择。没有分页,所有线性地址都映射到相同的物理地址。当启用时,这种形式的线性到物理地址空间映射是通过为所有任务使用一个页目录来获得。如果支持需求分页,线性地址空间可能超过可用的物理空间。
  • 每个任务都有自己的线性地址空间,被映射到物理地址空间。- 这种形式的映射是通过为每个任务使用不同的页面目录来完成的。因为PDBR(控制寄存器CR3)被加载到任务开关上,每个任务可能有一个不同的页面目录。

不同任务的线性地址空间可能映射到完全不同的物理地址。如果不同页面目录的条目 指向不同的页表,而页表指向内存的不同页面,那么这些任务就不会共享物理地址。
无论采用哪种方法来映射任务的线性地址空间,所有任务的TSS必须位于物理空间的一个共享区域,这个区域是所有任务都可以访问的。这种映射是必需的,当处理器在任务切换过程中读取和更新TSSs时不会改变。线性地址空间也应该被映射到物理空间的一个共享区域;否则,GDT的目的就会落空。
图7-9显示了两个任务的线性地址空间是如何通过共享页表可在物理空间中重叠通过共享页表。

image-20220415163751118

任务逻辑地址空间

为了允许任务之间共享数据,使用以下技术为数据段创建共享的逻辑-物理地址空间映射。

  • 通过GDT中的段描述符 - 所有任务必须能够访问GDT中的段描述符。如果GDT中的一些段描述符指向线性地址空间中的段,这些段被映射到所有任务共有的物理地址空间的一个区域,那么所有任务都可以共享这些段的数据和代码。
  • 通过一个共享的LDT - 如果两个或更多的任务的TSSs中的LDT字段指向同一个LDT,那么它们可以使用同一个LDT。如果共享LDT中的一些段描述符指向被映射到物理地址空间的一个共同区域的段 ,这些段的数据和代码可以在共享LDT的任务之间共享。这种共享方法比通过GDT共享更具选择性,因为共享可以被限制在特定的任务中。系统中的其他任务可能有不同的LDT,不允许他们访问共享段。
  • 通过不同的LDT中的段描述符,这些描述符被映射到线性空间的公共地址上 -如果这个线性地址空间的公共区域被映射到每个任务的物理地址空间的相同区域,这些段描述符允许任务共享段。这种段描述符 通常被称为别名。这种共享方法比上面列出的方法更具有选择性。因为,LDT中的其他段描述符可能指向独立的线性地址,而这些段描述符并没有被共享。

4.12

9.30-9.39 背单词

9.39-9.54 看编译原理慕课

10.02-11.07 线代第一讲

11.30-11.45 线代第一讲

13.26-14.56 午觉

15.00-15.28 15.38- 16.06 线代第一讲完成

16.22-17.00 背单词

17.16-17.35 看《Linux内核完全剖析》

17.45-20.00 健身

20.09-20.44背单词

21.20-21.51 看《Linux内核完全剖析》

21.56-22.08 看实验

22.11-22.20 线代第二章

4.13

8.49-8.56 英语单词

9.05-9.45 线代第二章

10.-11.45上课

12.39 吃完饭

12.40-14.26 睡午觉

14.31 -14.53 15.00-16.58 17.10-17.17线代第二章

17.18-17.33 英语单词

17.45-20.08 锻炼

20.20-22.00 讨论

22.10-22.36 英语单词

4.14

10.00-11.47 健身

12.40-12.54 线代第二章

12.55-13.45午觉

13.45-15.30 上课,顺便完成线代第二章

15.30-16.40 打电话与学长

16.40-17.45 看实验

18.30-21.00实验课

21.00-21.52 读书笔记四

22.00-22.30 背单词

4.15

9.00-10.00 考试

10.02-10.10 单词

10.40-11.00英语听力

12.20-13.48 睡午觉

13.59-14.43 做核酸

14.43-16.05 线代第三章

16.15-16.53 完成读书笔记四

17.45-19.41 健身

19.50-20.26 背单词

20.26-20.56 打电话

21.00-21.16 交报告

21.50-22.30 听力

4.16

9.10-9.20 单词

9.37-10.37 口语训练配音

10.40-11.46 线代第三章

12.26-13.45午觉

13.45-14.20核酸

14.20-15.26 完成线代第三章

15.30-17.00 看《Linux内核完全剖析》

17.00-17.30 单词

17.45-19.45 健身

4.17

9.00-10.40 开会

10.45-11.00背单词

15.00-16.45 线代第四章

4.18

15.45-17.19 完成线代第四章

17.19-17.46 单词

19.15-21.15 数据整理

4.19

9.09-9.26 背单词

9.27-9.54 线代第五讲,注:需要重新看视频

10.00-12.17 复习完编译原理第一章

14.00-15.10 开会

15.15-16.24 复习数据库ch0

16.45-16.49 17.00-17.36 翻译英语Text5

17.45-19.30 健身

19.30-22.07 开会

22.07-22.23 单词

4.20

8.50-9.00 背单词

9.08-10.00 数据库报告

10.00-11.45 上课

14.57-15.07 查询资料

15.07-17.30 编译原理实验

17.45-19.30 健身

20.00-21.00 开会

21.30-22.32 单词

4.21

13.45-16.30 编译原理实验

16.41-17.20 单词

18.36-19.00 20.31-21.30 背单词

21.31-22.30 翻译

4.22

9.00-11.00 14.30-17.45 数据库实验

19.50-21.00 单词

21.20-23.43 实验

4.23

11.00过来做比赛

17.45-19.30健身

20.00-22.00 单词

4.24

15.00-17.00 数据库

20.47-21.31单词

4.25

8.56-9.45 看《Linux内核完全剖析》

12.56-14.35 睡觉

14.36-15.40 18.20-21.11 完成数据库实验

21.20-22.24 写论文

4.26

9.20-11.45 看《Linux内核完全剖析》

14.20-15.35 写论文

15.35-17.40 看《Linux内核完全剖析》

20.25-22.44 操作系统实验一

4.27

8.10-8.20 单词

8.50-10.00 看《Linux内核完全剖析》

12.10-12.20 操作系统实验一

14.30-15.38 完成操作系统实验一

15.53-17.00 数据库实验四

20.05-23.47 实验

4.28

白天看实验,看了一天

20.30-23.59 写比赛论文

4.29

9.00-9.05 单词

9.05-9.50 写实验报告

9.51-11.00 实验

14.30-16.39 完成报告与数据库第二章复习

16.40-17.20 编译原理第二讲

20.00-20.56写论文

  1. 57-21.30 看《Linux内核完全剖析》
  2. 35-22.40 单词

4.30

13.00-13.30 单词

13.30-13.38 14.24-16.36 数据库第三章

20.30-21.52 写论文

5.1

14.46-15.03 复习编译原理第三章

15.03-15.48 改论文

5.2

9.00-9.45 单词

9..45-9.55 改论文

14.30-16.30 18.30-22.20 线代第五章完成

5.3

9.00-9.19 背单词

9.21-11.20 14.56—16.40 线代第六章

16.58-17.20数据库复习第四章

19.44-21.39 完成数据库第四章与部分第五章

22.10-22.40 英语听力

5.4

9.25-9.55 单词

15.10-17.16 做操作系统实验二

20.00-21.58 完成操作系统实验二

22.00-23.00 复习国际结算

5.5

8.53-9.10 单词

9.14-11.00 完成国际结算

14.47-17.20 数据库第五章

21.00-23.00 数据库第五章完成