Skip to content

Commit 6d8672b

Browse files
committed
docs: update in 20250421
1 parent 6b7b1ea commit 6d8672b

File tree

6 files changed

+469
-2
lines changed

6 files changed

+469
-2
lines changed

docs/cs/DB/chapter6.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ $$
9898

9999
![pEypw01.png](https://s21.ax1x.com/2025/03/31/pEypw01.png)
100100

101+
多元联系集可以通过引入一个新实体集,并建立新实体集与参与实体集之间的二元关系来代替:
102+
103+
![pEgedC4.png](https://s21.ax1x.com/2025/04/08/pEgedC4.png)
104+
101105
### Attributes
102106

103107
属性可取指的集合被称为属性的域(Domain)或值集(Value Set).
@@ -205,6 +209,9 @@ $$
205209

206210
![pEy9IbR.png](https://s21.ax1x.com/2025/03/31/pEy9IbR.png)
207211

212+
!!! tip "弱实体集的判定条件"
213+
如果一个实体集中的实体完全依赖于与另一个实体集之间的关系而存在,则可以使用弱实体集来表示该实体集.
214+
208215
!!! note "引入弱实体集的原因"
209216
TODO
210217

@@ -254,8 +261,65 @@ $$
254261

255262
## Reduction to Relational Schema
256263

264+
实体集和联系集都可以被统一地表示为数据库中的关系模式(Relational Schema).
265+
257266
### Entity Sets
258267

259268
#### Strong Entity Sets
260269

270+
将强实体集转化为关系模式只需要将<strong>强实体集的属性</strong>作为关系模式的属性即可,主键即为强实体集的主键.
271+
272+
对于复杂属性:
273+
274+
- 复合属性:分解为多个简单属性
275+
- 多值属性:创建新的关系模式,包括强实体集的主键和多值属性
276+
277+
!!! example
278+
对于 `instructor` 实体集的多值属性 `phone_number`,我们可以建立关系模式 `instructor_phone_number`
279+
280+
$$
281+
instructor\_phone\_number(\underline{ID}, \underline{phone\_number}).
282+
$$
283+
284+
285+
#### Weak Entity Sets
286+
287+
将弱实体集转化为关系模式需要将<strong>弱实体集的属性</strong>和<strong>标识实体集的主键</strong>作为关系模式的属性,主键由<strong>标识实体集的主键</strong>与<strong>弱实体集的分辨符</strong>组成.
288+
289+
除此之外,还需要建立从弱实体集对应的关系模式到标识实体集对应的关系模式的外键约束,采用级联删除模式.
290+
291+
### Relationship Sets
292+
293+
假设 $R$ 为建立在 $E_1, E_2, \ldots, E_n$ 上的联系集,具有描述性属性 $b_1, b_2, \ldots, b_m$,则其对应的关系模式的属性集合为
294+
295+
$$
296+
\text{primary_key}(E_1) \cup \text{primary_key}(E_2) \cup \cdots \cup \text{primary_key}(E_n) \cup \{b_1, b_2, \ldots, b_m\}.
297+
$$
298+
299+
二元联系集对应的关系模式的主键选取在 [Primary Key](./#primary-key) 一节中已说明,在此不再赘述.
300+
301+
对于多元联系集,关系模式的主键的选取遵循以下规则:
302+
303+
- 对于没有箭头的 $n$ 元联系集,其主键由 $n$ 个实体集的主键的并集构成.
304+
- 对于有箭头的 $n$ 元联系集,不在箭头侧的实体集的主键属性作为关系模式的主键.
305+
306+
联系集转化为关系模式时还需要建立外键约束:$R$ 中来自 $E_i$ 主键的属性需要参照关系模式 $E_i$ 的主键.
307+
308+
#### Redundancy of Schemas
309+
310+
弱实体集与强实体集之间的标示性联系,满足以下特性:
311+
312+
- 多对一
313+
- 无描述性属性
314+
- 弱联系集的主键包含强实体集的主键
315+
316+
对于这种情况,我们不需要为联系集单独创建一个关系模式,因为这样的关系模式的所有信息都可以从弱实体集的关系模式中获得,故是冗余的.
317+
318+
#### Combination of Schemas
319+
320+
对于满足以下要求的实体集 $A$ 和 $B$,以及建立在 $A$ 与 $B$ 上的联系集 $R$:
321+
322+
- $A$ 相对 $B$ 具有多对一 / 一对一关系
323+
- $A$ 中的所有实体都参与到 $R$ 中
261324

325+
则我们可以将联系集 $R$ 和实体集 $A$ 合并成一个关系模式,其属性集为 $A$ 的属性集合和 $R$ 的属性集合的并集,主键为 $A$ 的主键.

docs/cs/DB/chapter7.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
tags:
3+
- theory
4+
---
5+
6+
# Relational Database Design
7+
8+
## Good Form
9+
10+
We use normalization theory to decide whether a particular relation $R$ is in good form.
11+
12+
If R is not in good form, we need to decompose it into set of relations $\{R_1, R_2, \ldots, R_n\}$ such that
13+
14+
- $R_i$ is in good form
15+
- The decomposition is not lossy
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
---
2+
tags:
3+
- theory
4+
---
5+
6+
# Main Memory
7+
8+
!!! note "Address Binding"
9+
- 源代码层面的地址通常用某个符号(变量名)表示
10+
- Compiler 将符号绑定到可重定位的地址
11+
- Linker 将可重定位的地址绑定到绝对地址
12+
13+
PIE: Position Independent Executable
14+
15+
- PIE 类型的可执行文件中的地址都是相对地址,由 loader 加载到内存中后才确定绝对地址
16+
17+
Logical address: 逻辑地址,CPU 在寻址时使用的地址
18+
19+
Physical address: 物理地址,实际存储单元的地址
20+
21+
## Memory Management Unit (MMU)
22+
23+
MMU 将逻辑地址转换为物理地址
24+
25+
最简单的方法是加入一个重定位寄存器,保存 offset. 物理地址 = 逻辑地址 + offset
26+
27+
### Dynamic Loading
28+
29+
所有的 routine 都以可重定位格式存放在磁盘上,只有某个 routine 被调用时,其代码才会被加载进内存中
30+
31+
可以提高内存空间的利用率
32+
33+
由应用程序自行设计,OS 可以提供相关库
34+
35+
### Dynamic Linking
36+
37+
Static Linking: 编译时链接,将所有代码和数据都链接到可执行文件中
38+
39+
Dynamic Linking: 运行时链接
40+
41+
- 共享库(Shared Library): 编译时产生,包含多个 routine,可以被多个程序共享
42+
- 桩(Stub)
43+
- 延迟绑定(Lazy Binding)
44+
- GOT(Global Offset Table)
45+
46+
loader 加载程序时,先将代码加载到内存中,然后检查 metadata 得知该程序依赖哪些外部库,然后在 `LD_PATH` 下查找外部依赖库
47+
48+
## Memory Allocation
49+
50+
有限的内存资源需要用来支撑 OS 与 Application 的运行,因此需要高效的分配方式.
51+
52+
### Contiguous Allocation
53+
54+
- 目的:限制程序对超出范围的物理地址的访问
55+
- Base register: 基址寄存器,保存分配起始地址
56+
- Limit register: 限制寄存器,保存分配的内存大小
57+
- MMU 动态映射逻辑地址到物理地址
58+
59+
寻找可分配空间的算法:
60+
61+
- First-fit: 从基址开始,找到第一个大小足够的空闲空间
62+
- Best-fit: 从基址开始,找到大小最接近要求的空闲空间
63+
- Worst-fit: 从基址开始,找到最大的空闲空间
64+
65+
Best-fit 和 Worst-fit 都需要扫描整块地址空间.
66+
67+
以上三种方法具有内存碎片(Fragmentation)问题. First-fit 和 Best-fit 的利用率相对 worst-fit 高.
68+
69+
- External Fragmentation: 外部碎片,分配的内存空间不连续
70+
- Internal Fragmentation: 内部碎片,分配的内存空间大于程序需求的空间
71+
72+
### Paging
73+
74+
分配给一个程序的物理地址可以是不连续的,这样可以解决外部碎片问题,但是仍然有内部碎片问题.
75+
76+
将物理内存分成多个固定大小的块,称为 Frame
77+
将逻辑内存分成与 Frame 大小相同的块,称为 Page
78+
79+
OS 需要跟踪所有的空闲 Frame
80+
81+
通过页表来维护 Page 和 Frame 的映射关系
82+
83+
逻辑地址被分为页号(page number)与页内偏移(page offset)两部分
84+
85+
页号是页表的索引,对应某个 Frame 的编号
86+
87+
假设页表中页号 p 对应的 Frame 为 f, 则逻辑地址 $p + d$ 对应物理地址 $f + d$, 其中 d 为页内偏移
88+
89+
Frame Table: 标记物理内存中 Frame 的使用情况,通常会维护一个 Free Frame 链表.
90+
91+
![pEgc9I0.png](https://s21.ax1x.com/2025/04/09/pEgc9I0.png)
92+
93+
打开 paging 后,程序只能操控 virtual address,而不能直接操控 physical address. 因此,在打开 paging 前,我们需要让页表的虚拟地址与物理地址相等,以便打开 paging 后对页表的访问.
94+
95+
## Page table
96+
97+
Page Table 一般存储在内存中,寄存器 PTBR 指向 Page Table 的起始地址,寄存器 PTLR 存储页表的大小.
98+
99+
我们每条访存指令实际上要访问两次内存:
100+
101+
- 第一次从页表中查找逻辑地址对应的物理地址
102+
- 第二次从物理地址读取数据
103+
104+
为了加快访问,我们引入 TLB(Translation Look-aside Buffer),作为页表的缓存
105+
106+
![pEgckzF.png](https://s21.ax1x.com/2025/04/09/pEgckzF.png)
107+
108+
TLB 需要保证一致性:
109+
110+
- TLB 与内存中的 Page Table 的一致性
111+
- 多核 CPU 中每个 CPU 的 TLB 的一致性
112+
113+
每个进程都有自己的页表,操作系统内核也有自己的页表. 上下文切换时,需要更新 PTBR 寄存器,使其指向新进程的页表. TLB 也需要更新,此时有两种方式:
114+
115+
- 冷启动:进程切换时,将 TLB 全部清空,从页表中重新加载
116+
- 将 TLB 中的每个项增加 ASID(Address-Space Identifier)用于区分进程
117+
118+
!!! definition "Effective Access Time"
119+
120+
有效访问时间,指考虑页表和 TLB 的情况下,一次访存的平均耗时.
121+
122+
$$
123+
\text{EAT} = (\text{TLB Hit Ratio} + \text{TLB Miss Rate} \times 2) \times \text{Memory Access Time}
124+
$$
125+
126+
虚拟内存对应的物理内存不一定已经被分配,在页表中不一定能查到。若查不到,就会产生缺页异常(Page Fault Exception),控制权转移到操作系统,操作系统会先对程序请求访问的地址进行合法性校验,若地址合法,则分配物理内存,并更新页表;若地址不合法,则抛出段错误(Segmentation Fault).
127+
128+
129+
### Memory Protection
130+
131+
页表项一般包括:
132+
133+
- PFN(Page Frame Number): Page 对应的物理内存中 Frame 的编号
134+
- valid bits:表示该页表项存储的映射关系是否存在
135+
- permission bits(权限位):用于控制程序对该 page 对应的物理内存的访问权限,取值由操作系统控制. 根据操作类型(Read、Write、Execution)、指令特权态(Kernel,User)等可设置不同的权限位.
136+
137+
当程序访问某个 page 时,若在页表中查到了对应的页表项,则会根据权限位确定程序对该地址的访问是否合法,若合法,则可以访问该地址,否则会产生异常.
138+
139+
### Page Sharing
140+
141+
多个进程可以共享同一块物理内存,只需在进程各自的页表中设置对应的映射关系即可. 可能的应用场景包括:
142+
143+
- 相同程序启动多个进程,代码段可以共享
144+
- 进程间通信使用的共享内存
145+
- 公共库(如 libc)的代码
146+
147+
Linux 在 x86-64 架构上的进程在内核态和用户态之间共享页表
148+
149+
## Structure of page table
150+
151+
如果 Page size 取 4 KB,对于 32 位的系统,每个进程都需要 4 MB 的物理空间来存储页表,并且其中大部分页表项都不会被使用,造成空间浪费.
152+
153+
为了减少页表占用的空间,有以下几种方法:
154+
155+
### Hierarchical Page Tables
156+
157+
将页表分成多个层次,高层次的页表存储低层次的页表所在的 Frame id.
158+
159+
![pEgR0W6.png](https://s21.ax1x.com/2025/04/09/pEgR0W6.png)
160+
161+
逻辑地址被分为三段:
162+
163+
- page directory number
164+
- page table number
165+
- page offset
166+
167+
32 位系统中,page directory number 占 10 位,page table number 占 10 位,page offset 占 12 位,共 32 位.
168+
169+
一次寻址流程如下:
170+
171+
- 首先从 outer page table 中根据 page directory number 找到 inner page table 对应的 Frame 的地址
172+
- 再从 inner page table 中根据 page table number 找到 page 对应的 Frame 的地址
173+
- 最后在 Frame 中根据 page offset 找到数据
174+
175+
### Hashed Page Tables
176+
177+
![pEgRzlT.png](https://s21.ax1x.com/2025/04/09/pEgRzlT.png)
178+
179+
### Inverted Page Tables
180+
181+
![pEgRxpV.png](https://s21.ax1x.com/2025/04/09/pEgRxpV.png)
182+
183+
184+
## 64-bit RISC-V Linux Paging
185+
186+
SATP(Supervisor Address Translation and Protection)寄存器用于设置虚拟内存分页模式,其结构如下:
187+
188+
![pEgfpCt.png](https://s21.ax1x.com/2025/04/09/pEgfpCt.png)
189+
190+
- MODE:分页模式
191+
- ASID:地址空间标识符
192+
- PPN:顶层页表的物理页号
193+
194+
SV39 是 RISCV64 的一种分页模式,采用三级页表
195+
196+
197+
## Demand Paging
198+
199+
Demand Paging 是一种动态内存分配技术,只有当某个 Page 被访问时,系统才会将其加载进内存.
200+
201+
两种 Demand Paging 的策略:
202+
203+
- Lazy swapper
204+
- Pre-Paging:提前将进程需要的部分或全部 Page 加载进内存
205+
206+
### Page Fault
207+
208+
![pEghOkd.png](https://s21.ax1x.com/2025/04/09/pEghOkd.png)
209+
210+
!!! definition "EAT in demand paging"
211+
212+
Page fault rate $p = \dfrac{\text{Page Fault Times}}{\text{Page Access Times}}$
213+
214+
EAT in demand paging:
215+
216+
$$
217+
\begin{align*}
218+
\text{EAT} &= (1 - p) \times \text{Memory Access Time} + p \times (\text{Page Fault Overhead} + \\
219+
&{} \quad \text{Swap Page Out Cost} + \text{Swap Page In Cost} + \text{Instruction Restart Overhead}).
220+
\end{align*}
221+
$$
222+
223+
- Major page fault: 页被访问,但没有在内存中,需要从磁盘加载
224+
- Minor page fault: 页被访问,已经在内存中,但页表映射未建立
225+
226+
!!! example "Shared library for dynamic linking"
227+
公共库(例如 `libc.so`)在第一个调用它的进程启动时被加载到内存中,之后其他程序再次调用该公共库时,不需要再次将其加载到内存中,而只需要在新进程的页表中设置映射关系即可.
228+
229+
### Copy-on-Write
230+
231+
232+
### Page Fault Handler
233+
234+
当需要将一个 page 加载进内存时:
235+
236+
- 在磁盘上找到该 page
237+
- 找 Free Frame:
238+
- 如果存在空闲的 Frame,则分配给进程
239+
- 如果不存在,使用页替换策略选择一个 victim frame,如果 victim frame 被修改过,则先将其写回磁盘,然后分配给进程
240+
- 将 page 内容加载到新分配的 Frame 中
241+
- 重启被中断的进程
242+
243+
#### Page Replacement
244+
245+
当物理内存不足时,需要将某些 Page 从内存中换出到磁盘,以腾出空间.
246+
247+
Dirty Bit:当 Page 被修改时,设置 dirty bit,表示 Page 内容与磁盘中的内容不一致,需要被优先替换
248+
249+
替换算法:
250+
251+
- FIFO
252+
- LRU
253+
- Optimal
254+
255+
与 Cache 中的 [Block replacement](./chapter2.md#block-replacement) 策略类似.
256+
257+
LRU 实现:
258+
259+
- Counter-based
260+
- Stack-based
261+
262+
精确实现 LRU 的开销较大,我们可以采用 LRU 的近似实现:Additional-Reference-Bit Algorithm.
263+
264+
Second-chance algorithm
265+
266+
Page-Buffering algorithm
267+
268+
#### Allocation of Frames
269+
270+
Fixed allocation
271+
272+
- equal allocation
273+
- proportional allocation
274+
275+
276+
277+
## Non-Uniform Memory Access (NUMA)
278+
279+
280+
## Thrashing
281+
282+
!!! definition "Thrashing"
283+
如果一个进程分配得到的 Page 过少,导致 page fault 频繁发生,就会导致 CPU 利用率降低,
284+
285+
286+
## Kernel Memory Allocation
287+
288+
内核态的内存分配与用户态不同,不能使用 page fault 进行动态内存分配,

0 commit comments

Comments
 (0)