Operating System
Resource
https://pages.cs.wisc.edu/~remzi/OSTEP/Chinese/
Week 1
ASLR(Address Space Layout Randomization)
把 ASLR 關起來的方法
- PIE(Position-Independent Executable)
VDSO
Week 2
- How to run N process on M CPUs, where N >> M?
- plausible(似是而非的) solution: direct execution
- gain the full control of the machines
- how to switch from to ?
gain the full control of the machines
- In RISC-V there are three modes: user mode(U-mode), supervisor mode(S-mode), machine mode(M-mode)
- These are called privilege level
- CSR
- 在 RISC-V 中,exception 跟 Interrupt 都算是一種 trap。
- exceptions 是 synchronize 的,
- interrupts 是 asynchronize 的
- trap table
- return from trap
- 從 kernel mode 中 return 回來
- lower priviledge level
- restore states of the calling process
- jump back to PC after trap in user code
- LDE protocal
- 在 boot 的時候會初始化 trap table , CPU 會記得他的 location ,以便之後使用。
- 在 running process 的時候,kernel 可能會 allocating a node on the process list, allocating memory ,接著 CPU 會 switch to user mode ,並開始進行 process ,當需要做 system call ,它就會去 trap in OS ,之後藉由 return-from-trap 取得 user mode control 。
how to switch from to ?
- Cooperative Approach
- 我們假設所有 process 會用最理想的方式去執行,會自動讓出 CPU ,並 trap in system ,讓 OS 有控制權。
- 但萬一如果這隻 process 是惡意程式,或是有 bug 的程式,寫出一個無窮迴圈,這樣豈不是不能 trap in system 讓 OS 取得控制權了嗎?
- Non-Cooperative Approach
- lmbench 可以計算 system call 要花的時間
CSR
Week 3
- Scheduling policies
- set of process all arrive almost at once
- 會有一個 run queue 來去儲存這些 process
- execution time: 是只有程式執行的總時間。
- turnaround time: 是包含在等待被執行,以及執行的總時間。
- trunaround time is a performance materics
- FIFO 可能會不太好,當我們的 job 順序不一樣的時候,如果有一個執行時間非常長,可能會影響到後面的 job 。
- SJF(Shortest Job First)
- 依然會有 queue ,只是會對 queue 裡面的東西做排序。
- 是 optimal solution
- preemption
- response time
- preemption is try to shorter the response time
- responsivness ,我們希望他能更快的做出回應
- multi-level feedback queue
- 我們不知道 execution time
- 想要有好的 response time 和 turnaround time
- 我們會有多層的 priority 的 queue ,每一個 queue 實際上是做 Round Robin ,我們會先處理 priority 比較高的 queue ,而當我們在這個比較高的 priority 的 queue 已經運行比較長的時間,我們就會換到比較低的 priority 的 queue 去運行。
- 為了避免 starvation 的發生,我們會 reset 整個 priority of the queue 。
- 藉由過往的資訊來推斷
- 當一個 process 已經跑了很久了,我們就 reduce priority ,這邊會藉由之前的資訊,看一個 process 跑多久,來決定是否要 reduce priority ,這裡就是 feedback 。
- Rules
- if , do RR for A and B
- if , preempt B and run A
- start everyone at the top priority
- reduce priority level by one after a process has used up its time allotment.
- do (3) after some time.
- MLFQ
- Performance metrics
- proportional share(fairness)
- lottery scheduling
- Example: Proceess A 40% CPU time, Process B 60% CPU time
- stride scheduling
- idea: divide a large number by the number of tickets for each process.
- 根據不同的 stride ,每一次被 scheduled 的時候,會移動 stride 的大小
- Scheduling Policy
- CFS 是現在 Linux 正在使用的 scheduling policy
Week 4
- 最簡單的實作 virtual memory 的概念就是使用 base and bounds(limits) ,用相對的 base 做 offset 來取得資料。其中 base 就是記憶體位置的基準值, bound 就是他的最大值,可以藉由 bound 來檢查我們要取得的 offset 是否有超過範圍。
- 雖然 base and bounds 很快又能做到 protection ,但是卻會有 internal fragmentation 的問題,造成空間的浪費。
- internal fragmentation
- 就是一些在 virtual memory 中沒使用到的碎片
- external fragmentation
- 就是在做 segment 的時候,segment 之間的空間太小,導致也無法分配給其他記憶體
- segmentation
- best fit
- 會去迭代目前的 free list ,尋找與請求大小一樣或更大的 free memory ,那我們要從中找到最小的那個,希望能盡量不要浪費空間。這樣做我們可以找到目前與請求大小最接近的大小塊,但是在搜索的過程中會浪費時間。
- worst fit
- 這個和 best fit 相反,它會去找最大的 free memory ,分割並滿足需求後,把剩餘的記憶體加入 free list ,但樣做不僅還是要迭代一次 free list ,此外研究也指出他的 performance 非常差,會導致過多的碎片以及會有很大的開銷
- first fit
- 就是去尋找 free list 中第一個足夠大的 free memory ,並立刻返回。雖然有速度上的優勢,但是可能會導致有很多碎片,因此要如何管理 free list 的 order 會非常重要,有一種方法是 address-based order 。
- next fit
- 會去維護一個指針,指向上一次查詢結束的位置,這個想法是希望對 free memory 的查找操作擴散到整個 list 去,避免對於 list 的開頭頻繁的切割。
- some other technique
- segregated list
- slab allocater
- In Solaris by Jeff Bonwick
- merge 的方式
- binary buddy allocator
- 每次收到請求,都會把 memory 一分為二,直到可以滿足請求的大小,這種分配指允許分配 2 的次冪的大小的 free memory 。在 merge 的時候也會以 2 的次冪的大小來 merge 起來。
- 更複雜的方式
- 犧牲簡單性來換取性能
- balanced binary tree, splay trees, or partially-ordered trees
- RISC-V
- M-mode, S-mode, U-mode
- PMP(Physical Memory Protect)
- PMP register 會儲存不同區塊的 physical memory 的 Information
- user 可以看 PMP register 是否給 user 去 access 特定的 physical memory
- base an
- paging
- 各個 page 的 size 一樣,有點像是 restrict 的 segmentation
- 因此不會有 small external fragment
Paging
- Virtual Page number(VPN)
- Physical Frame Number(PFN)
- Physical Page Number(PPN)
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- address translation
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- page table
- control bit
- PTE(Page Table Entry)
- PTE 有效 bit 如果被標記成無效,代表該 page 沒有被 process 申請使用,正常的 process 不應該訪問該 address ,當 process 試圖訪問這樣的 page 時,就會導致 OS kill 掉這個 process 。
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- PTBR(page-table base register)
- page table 是存在實體記憶體的某個地方,想要做 address translation 時,我們就必需取到那個 table
- 會有一個 register 儲存 page table 在 physical address 的 base address 。
- entry in the page table(i.e, specific physical address of that PTE entry) = PTBR + VPN * sizeof(PTE)
- 讓 hardware 去取得 PTE 的 physical address 。
Week 5
- H/W involvement
- extract VPN from VA(fast)
- compute addr of PTE using PTBR(fast)
- fetch PTE(slow)
- extract PFN and form PA(fast)
- fetch PA -> register(slow)
- fetch 的速度很慢,base and bounds 很快,segmentation 也比較快,paging 的速度相對慢很多,這邊的 fetch 就是我們目前的 bottleneck ,有人想出可以使用 cache 來想辦法把兩個 fetch 減少成一個 fetch 的次數。
- OS involvement
- new process
- grow process
- process exit
- upon context switch
- TLB: Table Lookaside Buffer
- https://hackmd.io/@yq_MtXLqQ7quQb0BHoEY5g/r136tKlTa
- 是一個 address translation buffer
- fully associative
- TLB 是一個 cache
- TLB 在 CPU 裡面
- temporal locality
- spatial locality
- 當訪問 x 的 address 時,很可能再訪問 x 附近的 address
- TLB 的有效 bit 是代表 TLB 是不是有效的 mapping ,例如,系統啟動時,所有的 TLB 項通常被初始化為無效狀態,因為還沒有地址轉換映射被快取在這裡。一旦啟用虛擬記憶體,當程式開始運行,訪問自己的虛擬地址,TLB 就會慢慢地被填滿,因此有效的項很快會充滿 TLB。
- TLB 有效位在系統上下文切換時起到了很重要的作用,後面我們會進一步討論。通過將所有 TLB 項設置為無效,系統可以確保將要運行的進程不會錯誤地使用前一個進程的虛擬到物理地址轉換映射。
- Address Space Identifier(ASID) 可以視作 process identifier 來區分不同 process 。
- HW involvement
- extract VPN from VA
- check TLB
- case 1: we've found a valid mapping, TLB hit(of VPN & PFN) -> fast
- 2a: extract PFN from TLB entry and form PA(fast)
- 2b: fetch PA -> register(slow)
- case 2: we didn't find any valid mapping, TLB miss
- 2a: do same as if there's no TLB: fetch PTE using PTBR
- 2b: update TLB with translation info
- 2c: retry the (load) instruction
- TLB miss 會導致最差的 performance ,比沒使用 TLB 還要差
- 但為什麼 TLB 還能比原本的 performance 還要好呢?
- 因為 base on assumptions ,temporal locality 和 spatial locality ,根據 amortized analysis ,均攤下來還是有不錯的 performance
- 因此長時間的角度上來看 TLB miss 的 panalty 會被均攤掉
- TLB 的問題
- TLB 的大小有限,我們在什麼情況下要做 flush ?
- 我們可以用 OS 的角度去解決,例如在 context switch 的時候去處理
- 兩個 VPN 可能會有一樣的 virtual address
- 因此可以用 ASID 去做區分
- 或是可以使用 valid bit ,如果 valid bit 是 0 ,代表這個資料沒有用,代表說可以把它 flush 掉
- 通常幾 bit(n) 的電腦,Address Space 就是 2^n bytes
- page 通常是 4KB
- MiB(M bi byte): 2^20, MB: 10^6
- GiB: 2^30, GB: 10^7
Something learn in hw
- fork bomb
- kernel process table
- zombie process 的狀態會是 defunct
- 我們無法使用
kill -9 PID
的方式 kill 掉 defunct 的 process ,只能重新開機或是把他的 parent kill 掉
- hart: hardware thread (i.e. CPU)
- mhartid 是一個特別的 hardware 的 register ,它會紀錄目前在執行的 CPU 的 index 。
- kernel.ld 是 bootloader
Week 6
- SATP CSR ,虛擬儲存系統
- multi-level paging
- 為了 eliminate external fragmentation ,我們把 page table 切成多個
- 之前學的 paging 可以叫做 linear page table.
- PDBR(Page Directory base register) 是 base address for page table dirctory 。藉由 lookup page table directory ,然後再去看對應到 page table 的哪一個部分。第一個 level 是 directory ,第二個 table 是 page table 。
- PDBR 也會有 valid bit ,這裡的 PFN 是幫助我們去尋找我們的 page table 是存在哪一個 physical memory 上面。


- 這邊的 VPN 我們會切分成 page directory index 和 page table index
- Address Translation
- PDE addr = PDBR + (PDE index * sizeof(PDE)),其中 (PDE index * sizeof(PDE)) 是 page table directory 的 offset 。
- PTE addr = (PDE.PFN << shift) + PT index * (sizeof(PTE))
- PA = (PTE.PFN << shift) + offset
- workflow for mem-inst
- extract VPN
- check TLB for VPN
- TLB hit -> get PFN from TLB and fetch
- TLB miss
- 我們會用一個 bit 來記錄該 page 是否在 disk 上,記錄在 PTE 上面,所以我們不應該直接看 PTE 的 PFN ,應該先去查看 control bit ,例如 present bit
- handling page fault
- PFN = FindPhysicalPage()
- if(PFN == -1)
-
PFN - evictPage() // 把一個 physical page kick out
- Disk Read(PTE.Disk Address, PFN)
- PTE.present = 1;PTE.PFN=PFN
- Retry Instruction
Week 7
- present bit 告訴我們 page 是否存在 memory 中。
- page fault 通常代表訪問的虛擬地址空間的一部分,被 OS 交換到 disk 上面了。
- 當 page fault 發生了,OS 會讓 page fault handler 的這隻程式跑起來,處理 page fault。
- Belady's Anomaly 描述當 FIFO 的 cache size 增加,但 hit 的機率反而下降。
- 一個 criteria 去判斷一個 page fault 是否 optimal ,可以從高的 hit rate 或是低的 miss rate 來判斷
- replacement policies
- optimal
- FIFO
- random
- 或許 random 也是一個不錯的 solution ,不僅簡單,有時候也比 LRU 還要好
- LRU(Least Recently Used)
- 可以根據 spatial locality 或是 temporal locality ,過去的經驗來做判斷
- 隨著 cache size 的增長,hit rate 也會增加,一開始增加的幅度會比較高,但是增加到一定的量之後,就會慢慢的趨近平穩,然後不會有太大的變動
- 工作負載若不存在 locality ,使用的策略差異並不大

- LRU 的表現更好,它更能保持熱門的 page ,因為這些 page 過去常常被提及

- 這是一個 loop ,第一次 loop 進去 cache 的數值,到第二次依然會再次 miss ,然後還要重新放進 cache ,因此 LRU 和 FIFO 的表現很差,因為每一次的 iteration 都要重新放進去

- clock algorithm
- dirty bit 就是該格 PTE 是否有被 modified 。
- H/W:
- upon every page access set the page's use bit to 1
- OS: (lazy approach)
- if use bit = 1
- clear it to 0
- increase the clock pointer
- else
- evict the page(dirty bit)
- 可以藉由 clock algorithm 來判斷,會有一個 clock pointer 指向 cache 的一個 entry ,如果指向的那個的 use bit 是 1 ,就把它清成 0 ,然後把 clock pointer 加一,換下一個 entry 。當然在 clock algorithm 跑得過程中,依然可以把剛剛改成 0 的又把它改成 1 (因為我們可能過一陣子又用到他了,所以又把 use bit 變成 1 )。然後如果讀到 use bit 是 0 ,代表可以清掉 swap 了
Week 8
- kernel.ld is a bootloader
- hart: hardware thread ,可以視作 CPU
- mhartid 會存 CPU index
Week 9
- rip is the x86 program counter
- rip relative addressing: - position independent code
- non deterministic execution
- critical section
- race condition
- mutual exclusion,只會有一個 thread entered
- test and set
- 每一個 thread 都有自己的 stack
- 兩個 thread 可以有同一個 address space
- 一個 thread 如果要進入 critical section 就會去做 test and set 。
- test: lock is 0 or not ,如果是 0 ,就是代表我是可以進入 critical section 的那個 thread ,反之,代表有人在 critical section 。
- set: lock = 1
- 這必須要在 atomic execution
- 與其 busy waiting 的方式等待別人讓出 critical section ,不如在這段時間讓這個 thread 去做別的事情,不要等在那邊。就用 yielding 方式
- 或者可以用 sleep while waiting
- 以前不太想要用硬體來實作 lock ,但後來發現只需要少量的硬體就能實作 lock 了,後來轉向都在硬體上設計
- Peterson's algorithm 軟體上實作 lock 的演算法
Week 10

- a condition variable implements a queue of waiting threads
- use a lock with each condition variable
- pthread_cond_wait():
- assume the lock & hold when wait() is
- pthread_cond_signal():
- wake a single thread
- if no thread is waiting just return without doing anything
- a condition variable is paired with a state variable
- Producer/consumer
- mesa semantic
- Semaphore: updating a shared variable
- Semaphore wait (sem_wait(&s))
- Decrement the value of s by one
- The calling thread will wait(block) if s < 0
- Semaphore post (sem_post(&s))
- Increment the value of S by one
- Wake one of the waiting threads
- 也就是說 semaphore 會在 critical section 使該 shared variable 保持在一個數字,當有人要去 access cirtical section 時,會發現 decrement 該 shared variable 會使其小於 0 ,因此我們就會把該 thead block 住,等到 semaphre post ,會去 wake 剛剛被 block 的 thread 。
- sem_post, sem_wait 可以去設定我們指定 thread 的執行先後順序,這是 mutex lock 做不到的。
Week 11
- P implies Q
- P is the deaklock happens
- Q is neccessaries condition
- Q
- circular waiting
- hold and wait
- only locker-holder can unlock
- mutual exclusion
- 開發者需要注意第三項,only locker-holder can unlock ,這樣會破壞 mutual exclusion
- 我們需要保證任一個不是 true ,這樣我們的 program 就不可能發生 deadlock 。
- Inode table 上的 entry 叫做 metadata ,但要到達實際的 data ,我們需要 metadata 。
- file descriptor ,每一個 process 會記錄一個 fd list 。
- 然後 OS 會記錄一個 oft(open file table) ,不同 process 打開同一個檔案,可能會對應到不同的 file descriptor ,但是最終都會對應到 open file table 的同一個 entry ,最後這個 entry 又會指向 inode metadata
- name types
- regular 代表 files
- directory
- symbolic
- 一個 directory 在被創建的時候會出現有兩個 links ,一個 link 會指向自己,另一個 link 叫做
.
,也就是當前目錄,也會指向這個 directory 。
- 當我們在 f1 裡面建立一個 directory f2 ,也就是
f1/f2
,這個時候 f1 的 links 會變成 3 個,因為一個是自己本身,另一個是 .
,最後一個是 f2 的 ..
,也就是上一層目錄,因此會有 3 個 links 。
- 因此有多少目錄會決定 parent directory 有幾個 links
Week 12
- web service 最好不要使用 interrupt ,不然每次封包一來,就被 interrupt ,會導致無法執行其他底層事情。
- DMA 引擎會把數據傳給 device ,kernel 會告訴 DMA 記憶體位置在哪,以及要複製多少到哪一個 device 。完成後會拋出一個 interrupt 告訴 kernel 我完成了。這樣可以避免 PIO 的時間浪費
- hard drive layout
- 有多個 track 磁軌,每個 track 有多個 sector ,每個 sector 有 512 bytes ,多個 sector 組成 block 。
- inode 和 data 會放在 hard drive 上面
- 多個 block 可以組成 inode table, data region 。
- i-bmap 和 d-bmap 可以表示狀態,假設我有 1024 個 inode table blocks ,以及 1024 個 data blocks ,我的 i-bmap 和 d-bmap 各有 1024 個 bits ,分別表示 inode 和 data 的狀態。
- hrad link 不能跨 file system !
- file descriptor 是一個整數,在 xv6 中 file descriptor 就是一個 array 的 index 。
RAID
Week 13
- channel in a sleep lock,有很多 thread 成立,究竟要 wake 哪一個 thread ,就是 chan ,我們要判斷要 wake 哪一個 thread
- coroutines ,這裡有多個 routines , function 被稱作 routines ,告訴我們有兩個 functions ,會相互交換控制權
- journaling (logging) ,一次操作叫做 one transaction 。與其馬上寫到硬體上,不如寫一個計劃,我們要做什麼事。我們會記錄一個 transaction 是否 complete ,藉由記錄 commit(commit block) 。這個 commit 來記錄我們是否要去 perform 。
- 但這不保證不會有 data loss,這只保證 consistency
- pipe 是一個 circular queue ,nwrite 是當新增資料的時候會遞增,nread 是刪除資料的時候遞增,如果 nwrite 已經到了 nread 的位置,這時候 pipewrite-full
- 我們要怎麼確保一個 channel 是 unique ,我們如果要喚醒這個 channel 才能確定是他被喚醒
- 虛假喚醒(spurious wakeups)
- journaling 會有一個 header 來記錄有多少筆完整的 transaction ,要等到 transaction 完成才會更新 header ,如果 header 記錄的是 0 ,代表沒有完整的 transaction
- OOP 單體
- We’ve seen many students get confused by allocation structures such as
bitmaps. In particular, many often think that when you are simply read-
ing a file, and not allocating any new blocks, that the bitmap will still
be consulted. This is not true! Allocation structures, such as bitmaps,
are only accessed when allocation is needed. The inodes, directories, and
indirect blocks have all the information they need to complete a read re-
quest; there is no need to make sure a block is allocated when the inode
already points to it.
- 我想這段文字也是說明,為何會發生 inode leak 的原因。
Week 14
- satp 是一個特別的 hardware register
- 在 multi level paging 的時候,如果不是最後一個 page table ,那每一個 PPN 都是下一層的 page directory 的 base address 。
- Sv39 in RISC-V
- 39 代表 virtual memory 有 512 GB 的 memory
- invariant: make the size of each page directory = 4KB(i.e, the size of a page)
- 我們知道每個 PDE 多長,就知道我們需要幾個在 VA 裡面的 bits 才能被定位。
- 在 xv6 book 裡面寫到, Virtual Address 是 EXT L2 L1 L0 Offset
- 在 SV 39 之下,我們的 virtual address 有 39 bits ,其中因為每一個 PDE 是 4KB ,因此要給 12bits 去 locate 到 PDE ,接著會剩下 27bits ,這個時候我們會把它切成三份,使每一個都是 9 bits ,這里值得注意的是,不是因為我們有 L2 L1 L0 三塊,所以直接 27 / 3=9 ,而是有其他原因
- 因為 SV39 的標準,我們的 PDE 會有 8 bytes ,因此 4KB / 8 Bytes = 2^12 / 2^8 = 2^3 。

- SV39 會有 512GB virtual memory 和 64BP physical memory
Week 15
- Virtualization
- Use existing software resource
- Map the virtual resource to the real one
- Virtualization is isomorphism
- Rosetta Mac technology to translate code from x86 to arm
- We need to do state mapping, for example we need to translate the register and instructions, and we call this emulation.
- This technology also called binary translation
- Encapsulation
- Abstract hardware machine stats into virtual abstractions VM migration.
- Process Virtual Machines
- Usually refer the virtualizing software for process VMs as the runtime. So we can only care about the job.
- One is Java virtual machine. Which is run on the kernel.
- The other is binary translator
- I am curious about are process virtual machines and docker container similar?
- System virtual machines
- Provide a complete system hardware environment that can run an OS kernel
- Refer the virtualizing soft ware for system VMs as the VVM or hypervisor
- QEMU
- Rely on a dynamic binary transiator(DBT) for cross/same ISA emulation. When we have DBT, the QEMU will translate all the resource for you.
- Integrate with a hypervisor(ex: KVM) to support native execution
- In the 1960-70s, IBM System/360 the first mainframe computer that supports a wide-range of applications-was designed to run batch jobs(run one at a time)
- Hypervisors
- Type 1 hypervisors run directory
- XEN
- Xen refers to VMs to Domain
- We can directly to use the native Device Drive
- Type 2 hypervisors
- Hypervisor is built on top of or integrated with an existing OS kernel
- KVM integrates a user space QEMU
- hyperv is utilizing type 1 hypervisors
- Time sharing virtual CPUs
- From the perspective of a single CPU
- We can utilize Timer Interrupt hypervisor switches to VM2, and we can use the same method to VM1
- Container OS level virtualization, multiple isolated user level environment, which is use the technology different from Virutual Machine.
- VM has their own OS, but Conatiners use the same OS and there exists Comtainer Engine.
- If some malicious code spread into OS, VM is fine because they have their own OS.
- docker is a daemon application
- Cinfidential computing 機密運算
- A technology from Nvidia
- If a hacker take the disk out, we can don't care about, beacaute the data will lock in disk.
- Network could use cryptography to encrypt
- But the CPU can't.
- Confidential VMs on google cloud
- We can encrypt whole VM
- Without the protection, the VM can see everything.
- But with protectino, the VM can't see whole CPU and GPU.
- The attacker is the hypervisor. Your classmate holds a Virtual Machine, he can't access your virtual machine, becacuse of the OS isolated.
- The protection is isolated