轉載地址:https://my.oschina.net/hosee/blog/673628?p=%7b%7bcurrentPage+1%7d%7d算法
本文就將系統性的串聯起那些知識點,方便複習和回顧。本文適合已經有操做系統基礎的同窗,一塊兒回顧知識,本文並不詳細講解每一個算法,本文意在知識串聯。編程
經過一個例子來串聯全部的知識點:windows
寫了一個C語言程序:數組
#include
main()
{
puts("Hello World!\n");
}安全
目的是但願在屏幕中看到Hello World的字樣。數據結構
那麼在運行這個C語言程序時,操做系統作了什麼呢?異步
1. 首先要啓動程序執行,用戶要告訴操做系統執行程序ide
如何告知:函數
2. 操做系統知道用戶的請求以後,就會根據用戶提供的文件名到磁盤上找到這個程序的相關信息,找到信息以後,會去檢查這個程序是否是一個可執行文件,若是是可執行文件,操做系統會根據程序首部信息來肯定代碼和數據在可執行文件中的位置並計算出對應的磁盤塊地址。性能
文件系統是指操做系統中統一管理信息資源的一種軟件,管理文件的存儲、檢索、更新,提供安全可靠的共享和保護手段,而且方便用戶使用。
文件按性質和用途分類:普通文件,目錄文件,特殊文件(設備文件),管道文件,套接字。
文件的存儲介質:磁盤(包括SSD),磁帶,光盤,U盤……
物理塊是信息存儲、傳輸、分配的獨立單位。存儲設備劃分爲大小相等的物理塊,統一編號。
一次訪問磁盤的請求:
SSD沒有尋道和旋轉延遲的時間消耗,因此速度快。
文件控制塊:爲管理文件而設置的數據結構,保存管理文件所需的全部有關信息。
經常使用屬性:文件名,文件號,文件大小,文件地址,建立時間,最後修改時間,最後訪問時間,保護,口令,建立者,當前擁有者,文件類型,共享計數,各類標誌。
文件目錄:統一管理每一個文件的元數據,以支持文件名到文件物理地址的轉換。將全部文件的管理信息組織在一塊兒,即構成文件目錄。
目錄文件:將文件目錄以文件的形式存放在磁盤上。
目錄項:構成文件目錄的基本單元,目錄項能夠是FCB,目錄是文件控制塊的有序集合。
文件的物理結構:文件在存儲介質上的存放方式。
物理結構:
1. 連續結構:文件的信息存放在若干連續的物理塊中。
FCB中保存文件塊的起始塊號和長度。
優勢:支持隨機存取和順序存取,所需的尋道時間和尋道次數最少,能夠同時讀入多個塊,檢索一個塊很容易。
缺點:文件不能動態增加,不利於文件插入和刪除,有外部碎片(緊縮技術)
2. 連接結構:一個文件的信息存放在若干不連續的物理塊中,各塊之間經過指針鏈接,前一個物理塊指向下一個物理塊。
FCB只須要保存起始塊號
優勢:提升了磁盤空間利用率,有利於文件的插入和刪除,有利於文件動態擴充。
缺點:存取速度慢,不適於隨機存取,可靠性問題(如指針出錯),更多的尋道次數和尋道時間,連接指針佔有必定空間。
能夠對連接結構進行變形:文件分配表(FAT),早期windows和U盤使用的結構。
FAT存放了全部的連接指針,每個物理塊對應FAT的一行。
0表示空閒物理塊,-1表示文件最後一塊。
文件的起始塊號保存在文件的FCB中。
3. 索引結構:一個文件的信息存放在若干不連續物理塊中,系統爲每一個文件創建一個專用數據結構——索引表,並將這些物理塊的塊號存放在索引表中。
索引表就是磁盤塊地址數組,其中第i個條目指向文件的第i塊。
FCB中用一個字段保存索引表的位置。
索引結構優勢:保持了連接結構的優勢,解決了連接結構的缺點,既能順序存取,又能隨機存取,知足了文件動態增加,插入刪除的要求,能充分利用磁盤。
缺點:較多的尋道時間和尋道次數,索引表自己帶來了系統開銷。
索引表有可能很大,須要多個物理塊保存,就有多級索引和綜合索引。
多級索引:
UNIX三級索引結構:
訪問一個文件:文件名->文件目錄->FCB->磁盤
提升文件系統性能:
磁盤調度:當有多個訪盤請求等待時,採用必定的策略,對這些請求的服務順序調整安排。下降平均磁盤服務時間,公平,高效。
磁盤調度算法:
3. 爲了執行這個helloworld程序,操做系統會建立一個新的進程,並將該程序的可執行文件格式映射到該進程結構,表示由該進程來執行這個程序。
進程是具備獨立功能的程序關於某個數據集合上的一次運行活動,是系統進行資源分配和調度的獨立單位。
PCB,進程控制塊,操做系統用於管理控制進程的一個專門數據結構,進程與PCB是一一對應的。
PCB中有:
進程描述信息:進程標識符(惟一),進程名,用戶標識符,進程組關係
進程控制信息:優先級,代碼執行入口地址,程序的磁盤地址,運行統計信息(執行時間,頁面調度),進程間同步和通訊,進程的隊列指針,進程的消息隊列指針。
所擁有的資源和使用狀況:虛擬地址空間的情況,打開文件列表
CPU現場信息:寄存器值(通用寄存器,程序計數器PC,進程狀態字PSW,棧指針),指向該進程頁表的指針。
進程表:全部PCB的集合。
進程狀態:
操做系統爲每一類進程(就緒、等待……)創建一個或多個隊列,隊列元素爲PCB,伴隨進程狀態改變,其PCB從一個隊列進入另外一個隊列。
進程的建立:
操做系統爲每一個進程都分配了一個地址空間。
因爲性能,開銷等考慮,引入了線程的概念。
線程的開銷小,建立新線程花費的時間少,線程間切換花費時間少,線程之間互相通訊無須調用內核(同一進程的線程共享內存和文件)
線程是進程中的一個運行實體,是CPU的調度單位。
4. 操做系統將控制權交給調度程序,若是調度程序選中了helloworld程序,由操做系統爲該程序設置CPU上下文環境,並跳到程序開始處,準備執行該程序。那麼下一個指令週期就是執行helloworld程序了。
CPU調度:按必定的調度算法從就緒隊列中選擇一個進程,把CPU的使用權交給被選擇的進程。若是沒有就緒進程,系統會安排一個空閒進程。
CPU調度須要解決三個問題:調度算法、調度時機、調度過程。
調度算法:
佔有CPU的方式:
搶佔式和非搶佔式
時間片輪轉
典型系統的調度算法:
5. 當執行helloworld程序的第一條指令時,會發生缺頁異常(只有將代碼和數據讀入內存才能執行程序,執行第一條指令時,尚未將代碼數據讀入內存,那麼這個時候,硬件機制會捕獲出缺頁異常,而且把控制權交給操做系統)
6. 操做系統管理了計算機系統中的內存,(若是是頁式管理)操做系統會分配一頁物理內存,根據前面計算出的程序的磁盤塊地址,將helloworld程序從磁盤讀入內存,而後繼續執行helloworld程序。有的時候程序很大,一頁內存不夠,那麼會屢次產生缺頁異常,而後從磁盤中讀入程序到內存
咱們已經知道,每一個進程都有本身的進程地址空間,而且進程要裝入內存才能運行。那麼如何將進程地址空間裝入內存就是一個必須解決的問題。
經過上面的描述,咱們能夠知道,進程中的進程地址空間的地址,並非最終的物理地址。
所以須要地址重定位(地址轉換,從進程地址轉換成物理地址)來實驗進程的加載。
咱們把進程地址稱爲邏輯地址/相對地址/虛擬地址,而內存存儲單元中的地址稱爲物理地址/絕對地址/實地址,很明顯,只有物理地址可以直接尋址。
地址重定位分爲靜態重定位和動態重定位
靜態重定位:當用戶程序加載到內存時,一次性實現邏輯地址到物理地址的轉換。可是要求這個程序在內存中的位置不能改變。
動態重定位:在程序加載到內存中,不改變地址,仍然是邏輯地址。在程序執行過程中再進行地址轉換,即逐條指令執行完成轉換。由MMU(內存管理單元)來加速重定位。
如今已經能夠將程序加載到內存了,那麼該如何高效地分配內存給某個進程呢?
內存分配算法:
當內存歸還後,則面臨着回收問題,將先後空閒空間合併。
一種經典的內存分配方案:夥伴系統
將內存按2的冪進行劃分,組成若干的空閒塊鏈表,查找該鏈表找到能知足進程需求的最佳匹配塊。
基本內存管理方案
進程進入內存的連續區域:
單一連續區,內存利用率低
固定分區,浪費空間
可變分區,剩餘部分致使大量外碎片,碎片解決方案,緊縮技術(移動程序,將全部小的空閒區合併成較大空閒區)
進程進入內存不連續區域:
頁式存儲管理:
進程地址空間被劃分爲大小相等的部分,稱爲頁或者頁面。內存地址空間按一樣大小分爲大小相等的部分,稱爲頁框。
內存分配策略:以頁爲單位進行分配,並按進程須要的頁數來分配,邏輯上相鄰的頁,物理上不必定相鄰。
頁表記錄了從邏輯頁號到頁框號的映射關係。
每個進程一個頁表,存放在內存。頁表的起始地址在某個寄存器中。
頁式存儲管理中的地址轉換過程:CPU取到邏輯地址,自動劃分爲頁號和頁內地址,用頁號查頁表,獲得頁框號,再與頁內地址拼接成物理地址。
段式存儲管理:
用戶進程地址按程序自身邏輯關係劃分爲若干個程序段,每一個程序段都有一個段名。
內存空間被動態劃分爲不等長區域。
內存分配策略:以段爲單位進行分配,每段在內存中佔據連續空間,但各段之間能夠不相鄰。
與頁式不一樣的是,段號和段內地址不能自動劃分,須要顯示給出。
與頁式相同,使用段表來記錄關聯關係。
地址轉換過程與頁表也類似:CPU取到邏輯地址後,用段號查段表,獲得該段在內存中的起始地址,與段內偏移地址拼接計算出物理地址。
段頁式存儲管理:
用戶進程按段劃分,內存劃分同頁式存儲管理
段頁式存儲管理須要段表和頁表
段表記錄每一段的頁表起始地址和頁表長度。
頁表與頁式存儲管理相同
一個進程被分爲若干段,須要一個段表,而每一段按照頁式存儲管理分配,又對應一張頁表,因此一個進程對應一個段表和多個頁表。
總結:
那麼當內存不足時該如何管理呢?
內存「擴容」技術:內存緊縮(可變分區),覆蓋技術,交換技術(將某些進程暫時移到外存),虛擬存儲技術。
虛擬存儲技術:當進程運行時,先將其一部分裝入內存,另外一部分留在磁盤,當要執行的指令或者訪問的數據不在內存中時,由操做系統自動完成將它們從磁盤調入內存的工做。
把內存和磁盤結合起來,獲得更大的「內存」,就是虛存。
虛擬存儲技術和頁式存儲管理相結合,就產生了虛擬頁式存儲管理。
虛擬頁式存儲管理基本思想:
進程開始執行以前,不是裝入所有頁面,而是裝入一個或者零個頁面,以後根據進程須要,動態裝入其餘頁面,當內存已滿,而又須要裝入新的頁面,則根據某種算法置換內存中的某個頁面,以便裝入新的頁面。
因爲頁表數量太大,引入了多級頁表。
按照傳統的地址轉換方式:虛擬地址->查頁表->頁框號->物理地址,這樣每一個進程都要一個頁表。頁表佔據了不少空間。
解決這個問題:從物理地址出發,整個系統就創建一張頁表(由於物理地址大小固定),頁表項紀錄進程i的某虛擬地址與頁框號的映射關係。
可是仍然有一個問題存在,因爲多級頁表的存在,每次訪問頁表都要去訪問內存,那麼須要屢次訪問內存,因爲CPU的指令處理速度與內存指令的訪問速度差別大,CPU的速度得不到充分利用。
爲了解決這個問題,因爲程序訪問局部性原理,從而引入了快表(TLB),用來加快地址轉換的速度。
快表由cache組成,訪問速度快。
引入快表後的地址轉換過程:
虛頁號->查快表(並行比較)
若是命中,則找到頁表項
若是沒有命中,用虛頁號查頁表獲得頁表項
當獲得頁表項後看到有效位,若是有效位是1,說明該頁已經在內存中,則運行
若是是0,則拋出缺頁異常。
當缺頁時,操做系統就要將頁面調入內存,若是內存滿了,必需要將一些頁面暫時調出到外存中。
那麼置換的策略有哪些呢?
7. helloworld程序執行puts函數(系統調用),在顯示器上寫一字符串。
8. 因爲puts函數是系統調用,控制權又交到操做系統上。操做系統找到要將字符串送往的的顯示設備,一般設備是由一個進程控制的,因此,操做系統將要寫的字符串送給該進程。
CPU與I/O:
減小或緩解速度差距->緩衝技術
使CPU不等待I/O->異步I/O
讓CPU擺脫I/O操做->DMA,通道
9. 控制設備的進程告訴設備的窗口系統它要顯示字符串,窗口系統肯定這是一個合法的操做,而後將字符串轉換成像素,將像素寫入設備的存儲映像區。
10. 視頻硬件將像素轉換成顯示器能夠接受的一組控制/數據信號。
11. 顯示器解釋信號,激發液晶屏。
12. 在顯示器上看到hello world。
從上面的過程當中,咱們能發現,CPU上時而運行用戶程序,時而運行操做系統程序。運行操做系統程序,咱們稱CPU處在內核態,運行用戶程序,咱們稱CPU處在用戶態。
而這兩種CPU狀態之間的轉換:
從用戶態到內核態,只能經過中斷/異常/陷入進制(陷入指令是一條特殊的指令,提供給用戶程序的接口,用於調用操做系統的功能/服務,例如int,trap,syscall,sysenter/sysexit)
而內核態到用戶態,設置程序狀態字PSW.
中斷/異常機制,是操做系統的驅動力,咱們能夠說,操做系統是中斷驅動的。
中斷/異常的概念:CPU對系統發生的某個事件做出的反應。
CPU暫停正在執行的程序,保留現場後自動轉去執行相應事件的處理程序。處理完成後返回斷點,繼續執行剛纔被打斷的程序。
中斷和異常的區別在於,中斷是由外部引起的,而異常則是該程序本身產生的。
CPU什麼時候去響應中斷?CPU會在每一條指令執行最後,去掃描中斷寄存器,查看是否有中斷。如有中斷,中斷硬件將該中斷觸發器內容按規定編碼送入PSW的相應位,稱爲中斷碼,經過查中斷向量表引出中斷處理程序。
除此以外,固然還有進程互斥同步問題。
進程互斥:因爲各進程要求使用共享資源(變量、文件等),而這些資源須要排他性使用,各進程間競爭使用這些資源。這一關係稱爲進程互斥。
進程互斥軟件解決方案:
Dekker算法:
P進程:
pturn = true;
while(qturn)
{
if(turn == 2)
{
pturn = false;
while(turn == 2);
pturn = true;
}
}
臨界區
turn = 2;
pturn = false;
Q進程:
qturn = true;
while(pturn)
{
if(turn == 1)
{
qturn = false;
while(turn == 1);
qturn = true;
}
}
臨界區
turn = 2;
qturn = false;
pturn和qturn表示對應的進程想進臨界區,若是都想進臨界區,則經過turn來判斷本身是否要讓出CPU。從而實現互斥。
Peterson算法:
克服了Dekker算法強制輪流的缺點。
i表示進程號
進程i:
……
enter_region(i);
臨界區
leave_region(i);
……
int turn;//輪到誰
int interested[N];//興趣數組,初始都爲false,表示某個進程想進臨界區
void enter_region(int process)//假設這裏兩個進程的進程號是0和1
{
int other;//表示另外一個進程的進程號
other = 1 - process;
interested[process] = true;
turn = process;
while(turn == process && interested[other] == true);
}
void leave_region(int process)
{
interseted[process] = false;
}
這裏的turn變量要注意一下,turn表示輪到誰來進入臨界區,若是兩個進程都想進入臨界區,能夠發現trun變量會被後賦值的進程替換到先賦值的進程。
Peterson算法但願先想進臨界區的進程先進去,那麼在while循環中就產生了判斷,若是turn是當前進程號(表示該進程是後想進入臨界區的),則一直在while循環中等待,固然還須要判斷另外一個進程是否想進入臨界區(interested[other]==true),若是另外一個進程不想進入臨界區,就不必等待了。
Peterson算法Java實現:
public class Peterson implements Runnable {
private static boolean[] in = { false, false };
private static volatile int turn = -1;
public static void main(String[] args) {
new Thread(new Peterson(0), "Thread - 0").start();
new Thread(new Peterson(1), "Thread - 1").start();
}
private final int id;
public Peterson(int i) {
id = i;
}
private int other() {
return id == 0 ? 1 : 0;
}
@Override
public void run() {
in[id] = true;
turn = other();
while (in[other()] && turn == other()) {
System.out.println("[" + id + "] - Waiting...");
}
System.out.println("[" + id + "] - Working ("
+ ((!in[other()]) ? "other done" : "my turn") + ")");
in[id] = false;
}}
進程的同步:指系統中多個進程中發生的事件存在某種時序關係,須要相互合做,共同完成一項任務。
解決方法:
固然還有死鎖問題:
產生死鎖的必要條件:
資源分配圖:用有向圖描述系統資源和進程的狀態。
如:
若是資源分配圖中沒有環路,則系統中沒有死鎖,若是圖中存在環路,能可能存在死鎖。
若是每一個資源類中只包含一個資源實例,則環路是死鎖存在的充分必要條件。
死鎖預防:
死鎖避免:銀行家算法,安全狀態必定沒有死鎖發生。
銀行家算法總的來講就是,給每一個用戶貸款的錢不會超過銀行錢的總量,可是全部用戶貸款的錢的總和是能夠超過銀行錢的總量的。
死鎖檢測與解除:容許死鎖發生,可是操做系統會不斷監視死鎖是否真的發生。一旦死鎖發生,就會採用專門的措施,以最小代價來解除死鎖,恢復操做系統運行。
讓咱們再次總結一下HelloWorld程序的運行。
當咱們運行HelloWorld程序時,操做系統會根據文件名去找文件目錄,而後找到了FCB,經過FCB裏的物理地址找到磁盤上對應的文件。
那麼FCB是如何獲得文件的物理地址的呢?這和文件的物理結構有關,文件的物理結構有連續結構、鏈表結構、索引結構,不一樣結構中FCB保存的信息不一樣。
獲得物理地址之後,從磁盤上讀取文件須要通過尋道,旋轉延遲,數據傳輸三部分。那麼如何高效地從磁盤上讀取文件呢?就能夠運用不一樣的磁盤調度算法,譬如先來先服務,最短尋道時間優先,掃描算法,旋轉調度算法等等。
獲得文件後,操做系統會建立一個新的進程去執行這個程序。進程與PCB是一一對應的,PCB中保存了進程的各種信息,系統爲每一個進程分配一個地址空間,這個地址空間是虛擬地址。
有了進程去運行這個程序後,就等着CPU調度這個進程了。CPU調度算法有先來先服務,最短做業優先,最短剩餘時間優先,最高響應比優先,輪換調度等等。
當CPU選擇調度了這個程序,想要運行這個程序的第一條指令時,會發生缺頁異常,由於代碼數據尚未讀入內存,有的時候程序很大,一頁內存不夠,那麼會屢次產生缺頁異常,進程必須進入內存才能被運行,須要經過地址重定位將進程的虛擬地址轉換成物理地址,不一樣的內存管理方式會有不一樣的轉換方式,好比頁式存儲管理,段式存儲管理,段頁式存儲管理,加了虛擬存儲技術之後,還有虛擬頁式存儲管理,因爲使用虛擬存儲技術,在內存滿時,須要將一些頁面暫時調到外存,置換的算法有最佳頁面置換算法,先進先出算法,最近未使用算法,最近最少使用算法等等。
如今進程被加載到了內存,該如何高效地分配內存給這個進程呢?內存分配算法:首次匹配,下次匹配,最佳匹配,最差匹配。若是此時內存滿了,則會調用剛剛說的置換算法。
此時CPU已經成功運行了這個程序。以後須要顯示的字符串將會交給顯示設備的進程。最後是一系列硬件上的處理,成功讓顯示屏顯示HelloWorld。
來自 <https://my.oschina.net/hosee/blog/673628?p={{currentPage+1}}>