主要是把在重讀 《現代操做系統》 中以爲有價值的東西,以 Tips 的形式記錄下來。不可能面面俱到,可是若是有必定的基礎應該是會回想起不少知識的。具體解釋將會以連接形式補充。GitHub
相關閱讀 : 重拾數據結構node
主要是爲了支持僞併發能力git
CPU 利用率 = 1 - p ^ n
p : IO 等待時間比
n : 進程數github
每個進程有一個地址空間和一個控制線程,主要是使某個進程內的任務之間不被相互阻塞,實現一種進程內並行操做的假象。建立銷燬更加輕量級。算法
共享一組資源,協同完成任務。每一個線程有本身的堆棧區(由於要區分同一進程內的線程,CPU 調度要進行狀態的保存)編程
兩個或者多個進程讀寫某些共享數據緩存
將共享內存的訪問代碼稱爲臨界區,確保在每一個時刻兩個進程不可能同時處於臨界區中,這樣能夠避免競爭條件。核心思想爲互斥。安全
併發程序準確高效要知足一下四個條件數據結構
互斥實現方案併發
每一個進程進入臨界區後當即屏蔽全部中斷,這樣 CPU 沒法進行進程切換,就要離開臨界區是打開中斷。函數
設置一個共享鎖變量,初始值爲 0。當一個進程想要進入臨界區,必須檢測鎖的值是否爲 0,是則置 1 進入臨界區。不是則等待其餘進程退出臨界區時釋放鎖直到本身能獲取到鎖開始進入臨界區。
鎖變量仍是會產生競爭條件
一直循環等待直到出現容許該進程進入臨界區的條件纔開始運行,十分消耗 CPU 資源。
避免了競爭條件,可是臨界區外運行的程序會發生阻塞
用於忙等待的鎖稱爲自旋鎖。
A:
while (TRUE) {
while (turn != 0);
critical_region();
turn = 1;
noncritical_region();
}
B:
while (TRUE) {
while (turn != 1);
critical_region();
turn = 0;
noncritical_region();
}複製代碼
一種互斥算法
#define FALSE 0
#define TRUE 1
#define N 2
int turn;
int interested[N];
void enter_region(int process) {
int other;
other = 1 - process;
interested[process] = TRUE;
turn = process;
// 若是有另外一個程序進入臨界區的話則一直空循環
while (turn == process && interested[other] == TRUE);
}
void leave_region(int process) {
interested[process] = FALSE;
}複製代碼
前面的弊端是忙等待會消耗 CPU 資源。若是在等待進入臨界區時能夠掛起,等到某個信號到達再喚醒就能夠避免這種狀況了。
利用資源緩衝區實現進程間的協調
#define N 100
int count = 0;
void producer(void) {
int item;
while (TURE) {
item = produce_item();
if (count == N) {
sleep();
}
insert_item(item);
count = count + 1;
if (count == 1) {
wakeup(consumer);
}
}
}
void consumer(void) {
int item;
while (TURE) {
if (count == 0) {
sleep();
}
item = remove_item();
count = count - 1;
if (count == N - 1) {
wakeup(producer);
}
consume_item(item);
}
}複製代碼
引入一個信號量來累計喚醒次數,能夠爲 0 或正數
使用 down 和 up 操做代替 sleep 和 wakeup
#define N 100
typedef int semaphore
semaphore mutex = 1; // 控制對臨界區的訪問
semaphore empty = N; // 計數緩衝區的空槽數目
semaphore full = 0; // 計數緩衝區的滿槽數目
void producer(void) {
int item;
while (TRUE) {
utem = produce_item();
down(&empty);
down(&mutex);
insert_item(item);
up(&mutex);
up(&full);
}
}
void consumer(void) {
int item;
while (TRUE) {
down(&full);
down(&mutex);
item = remove_item();
up(&mutex);
up(&empty);
consume_item(item);
}
}複製代碼
僅僅適用於管理共享資源或一小段代碼
當有多個進程處於就緒態時就面臨調度的選擇。
內核管理線程時調度能夠認爲是線程級別的。
進程行爲有計算密集型
和I/O 密集型
。而如今因爲 CPU 改進速度加快,進程行爲更傾向於後者,因此應該多運行該類進程保持 CPU 的利用率。
批處理
交互式
aT0 + (1 - a)T1
)實時
線程調度
和系統支持的線程實現方式有關(理解 : 線程表存在哪的區別)
用戶級線程 : 內核並不知道,內核只是選中該進程,至於進程中跑哪一個線程由用戶態調度決定。
內核級線程 : 直接調度某個進程內的線程。
以上兩種方式在性能上有主要差異 : 前面說起 I/O 操做實際上是很耗時的,因此在進程間切換比在線程間切換更加耗時。由於線程輕量,而進程完成切換要完整的山下文切換,修改內存映像。並且同一進程內的線程 I/O 訪問 cache 的局部性更高,不一樣進程間切換的清理緩存,這也會消耗時間。
主要思想就是內存抽象
程序產生的地址爲虛擬地址,在沒有虛擬內存的操做系統上,直接將地址輸送到內存總線上。而有虛擬內存的操做系統上,把虛擬地址輸送到 MMU(Memory Management Unit),由 MMU 將虛擬地址映射爲爲物理地址。
虛擬地址空間 : 頁面 物理內存地址 : 葉框 4k大小
虛擬地址 = 虛擬頁號(高位) + 偏移量(低位)
頁表 : 把虛擬地址的頁面映射爲頁框,每一個進程都有本身的頁表
加速分頁方法 : 轉換檢測緩衝區(TLB)主要是優先在 TLB 中查找頁面號。
大內存頁表
最優頁面置換算法不可實現,由於沒法肯定將來。
設置訪問(讀、寫)位 R,頁面修改位 M。
設置一個檢測最老頁面位 R
鏈表實現頁面選擇
利用矩陣模擬 : 增長自身權重減小其餘權重,行置 1,列置 0。
老化算法
算法 | 註釋 |
---|---|
最優算法 | 不可實現,但可做爲基準 |
NRU(最近未使用)算法 | LRU 的很粗糙近似 |
FIFO(先進先出)算法 | 可能拋棄重要頁面 |
第二次機會算法 | 比 FIFO 有大的改善 |
時鐘算法 | 現實的 |
LRU(最近最少使用)算法 | 很優秀,但很難實現 |
NFU(最不常用)算法 | LRU 的相對粗略的近似 |
老化算法 | 很是近似 LRU 的有效算法 |
工做集算法 | 實現起來開銷很大 |
工做集時鐘算法 | 好的有效算法 |
進程發起系統調用,把文件映射到其虛擬地址空間的一部分。通常實現是開始不加載,在程序訪問時在按頁加載。
// Linux 待填
段是邏輯實體,大小不固定。
還有 Intel Pentuium 未介紹
34 位的 MULTICS 虛擬地址
段號 | 頁號 | 頁內偏移 |
---|---|---|
18 | 6 | 10 |
文件系統存放在磁盤上。多數磁盤劃分爲一個或多個分區,每一個分區中有一個獨立的文件系統。磁盤的 0 號盤扇區稱爲主引導記錄(Master Boot Record, MBR),用來引導計算機。在 MBR 的結尾是分區表,該表給出了每一個分區的其實和結束地址。表中的一個分區被標記爲活動分區。在計算機被引導時,BIOS 讀入並執行 MBR。MBR 作的第一件事是肯定活動分區,讀入它的第一個塊,稱爲引導塊,並執行。
整個分區:
MBR | 分區表 | 磁盤分區 | 磁盤分區 | 磁盤分區... |
---|---|---|---|---|
磁盤分區:
引導塊 | 超級塊 | 空閒空間管理 | i 節點 | 根目錄 | 文件和目錄 |
---|---|---|---|---|---|
把每一個文件做爲一連串連續數據塊存儲在磁盤上。
一個文件由幾個磁盤塊組成。
把每一個磁盤塊的指針字放在內存的一個表中
每一個文件賦予一個稱爲 i 節點(index-node)的數據結構,列出文件屬性和文件快的磁盤地址。
塊設備 : 以塊爲單位傳輸,可尋址
字符設備 : 以字符爲單位收發字符流,不可尋址
DMA 工做原理:
在進程對設備,文件等取得了排他性訪問權限的時候,有可能會出現死鎖。這類須要排他性使用的對象稱爲資源。
能夠從擁有它的進程中搶佔而不會產生任何反作用。(存儲器)
指在不引發相關的計算失敗的狀況下,沒法把他從佔有它的進程處搶佔過來。( CD 刻錄)
資源使用步驟:
若是一個進程集合中的每一個進程都在等待只能由該進程集合中的其餘進程才能引起的事件,那麼,該進程集合就是死鎖的。
發生資源死鎖的四個必要條件:
死鎖檢測主要是判斷當前空閒資源在某種合理分配下是否能使全部進程都運行完而且最終資源都可以釋放。
恢復方法 :
死鎖避免從本質上來講是不可能的,由於他要獲取將來的信息。
若是資源不被一個進程獨佔死鎖不會發生。(假脫機打印機)
開始執行前請求全部資源就不會形成等待。另外一種是請求資源時先釋放本身所持有的資源,再嘗試一次請求資源。
針對某些資源進行虛擬化,實現可搶佔。
保證每一個進程在任什麼時候刻只能佔用一個資源若是要請求另一個資源它必須先釋放第一個資源。另外一種是將全部資源統一編號,進程能夠在任什麼時候刻提出資源請求,可是請求必須按照資源編號順序(升序)提出。