背景
這個(gè)系列的第三篇筆記對(duì)應(yīng)的是書(shū)中的《Mechanism: Limited Direct Execution》,主要內(nèi)容是對(duì)之前說(shuō)過(guò)的 time sharing 介紹了一點(diǎn)稍微深入的東西。
Challenges Of Time Sharing
Time sharing 從定義來(lái)說(shuō)很簡(jiǎn)單,就是單個(gè) CPU 運(yùn)行一個(gè) process 一段時(shí)間,然后在運(yùn)行其它 process 直到所有 process 結(jié)束。但是在建立這個(gè)機(jī)制之前,我們還需要考慮兩個(gè)問(wèn)題:
- performance
- control
第一點(diǎn)很容易理解,這幾乎是任何一個(gè)大型系統(tǒng)都要考慮的問(wèn)題,性能問(wèn)題。操作系統(tǒng)進(jìn)行 process 的切換會(huì)不會(huì)對(duì)性能產(chǎn)生影響。第二點(diǎn) control,這個(gè)在操作系統(tǒng)是特別重要的。因?yàn)檫@個(gè)涉及到如何停止一個(gè) process,并且切換到另一個(gè) process,涉及到如何限制一個(gè) program 的權(quán)限,操作系統(tǒng)不可能讓一個(gè) program 想做什么就做什么,想訪(fǎng)問(wèn)哪塊內(nèi)存就訪(fǎng)問(wèn)哪塊內(nèi)存。所以最終我們要解決的問(wèn)題就是,如何在做到保持各個(gè) process 的控制的同時(shí),有效率的運(yùn)行,切換 process?
Limited Direct Execution
操作系統(tǒng)的開(kāi)發(fā)者提出了一種技術(shù) - limited direct execution 來(lái)解決這個(gè)問(wèn)題。首先 direct execution 指的是直接在 CPU 上運(yùn)行這個(gè)程序
when the OS wishes to start a program running, it creates a process entry for it in a process list, allocates some memory for it, loads the program code into memory (from disk), locates its entry point (i.e., the main() routine or something similar), jumps to it, and starts running the user’s code
這個(gè)解決了效率問(wèn)題,但是并沒(méi)有解決第二個(gè)問(wèn)題。所以接下來(lái)我們著重講一下操作系統(tǒng)是如何解決 control 的問(wèn)題。這里具體要解決兩個(gè)問(wèn)題:
- 如何設(shè)定 user program 的權(quán)限
- 如何進(jìn)行 process 的切換
Restricted Operations
process 會(huì)有兩種不同的 mode, user mode 和 kernel mode。當(dāng) CPU 運(yùn)行 user program 的程序的時(shí)候,CPU 會(huì)處于 user mode,而這個(gè) mode 就規(guī)定了 user program 可以做的操作和權(quán)限。如果這個(gè)時(shí)候 user program 越界了,CPU 就會(huì)拋出一個(gè)異常,接著操作系統(tǒng)收到這個(gè)異常后,就有可能會(huì) kill 這個(gè) user program。而當(dāng) CPU 處于 kernel mode,CPU 可以接觸并管理整個(gè)硬件系統(tǒng)(操作系統(tǒng)運(yùn)行時(shí),CPU 是處于 kernel mode)。
但是,肯定會(huì)有這樣的一類(lèi)需求,就是當(dāng) CPU 處于 user mode,但是 user program 又希望做一些高權(quán)限的操作(比如,請(qǐng)求訪(fǎng)問(wèn)硬盤(pán))。這個(gè)時(shí)候 user program 可以通過(guò)調(diào)用 system call,將 CPU mode 提升為 kernel model。(這里有點(diǎn)讓我想到 runloop 里面的各種 mode),這篇文章詳細(xì)的介紹了這兩種mode
System Call
什么是 system call,像我們前面一章用過(guò)的 open,fork 函數(shù)都是 system call,看起來(lái)就是一個(gè)普通的方法,只是說(shuō)這個(gè)方法是由系統(tǒng)提供的。它與普通的方法區(qū)別在于,system call 最終都要執(zhí)行一個(gè) trap instruction,這個(gè)指令會(huì)將 processor mode 從 user mode 提升到 kernel mode,然后開(kāi)始執(zhí)行一些指令,執(zhí)行完之后,再執(zhí)行 return-from-trap 指令,返回 user program。不同的 system call 對(duì)應(yīng)著不同的執(zhí)行指令,這個(gè)對(duì)應(yīng)的關(guān)系是存儲(chǔ)在一張表里,也叫 trap table,這個(gè) table 的建立是在機(jī)器啟動(dòng)的時(shí)候,由操作系統(tǒng)來(lái)確定的。詳細(xì)的流程,可以看書(shū)中給的一副圖:

這樣,通過(guò) processor mode 和 system call 就解決了第一個(gè)問(wèn)題,現(xiàn)在再來(lái)看下如何解決第二個(gè)問(wèn)題。
Process Switching
首先,計(jì)算機(jī)中都會(huì)有個(gè)計(jì)時(shí)器,每隔一段時(shí)間,就會(huì)觸發(fā)一個(gè) timer interrupt,當(dāng)操作系統(tǒng)接收到這個(gè) interrupt 時(shí),就會(huì)進(jìn)行 process switch。
switch 的具體流程:

(1) 計(jì)時(shí)器發(fā)出 timer interrupt
(2) 保存 user register
(3) processor 提升到 kernel model
(4) 跳轉(zhuǎn)到 trap table 指定的指令
(5) 操作系統(tǒng)執(zhí)行 switch 函數(shù)
(6) 保存 kernel register
(7) 加載新的進(jìn)程的 kernel register
(8) 棧指針指向新的進(jìn)程的棧
(9) 加載新的進(jìn)程的 user register
(10) 執(zhí)行 B 程序
關(guān)于寄存器的分類(lèi),可以看這篇。
最后書(shū)里還講了關(guān)于 switch 函數(shù)的具體實(shí)現(xiàn),是用匯編實(shí)現(xiàn),這里不在陳述,有興趣的可以去原文看代碼。