進程:進程可以看做正在執行的程序。進程需要一定的資源來完成更其任務。
進程是大多數系統中的工作單元。這樣的系統有一組進程組成操作系統進程執行系統代碼,用戶進程執行用戶代碼,所有進程可以並發執行。
程序是被動實體,進程是活動實體,它有一個程序計數器用來表示下一個要執行的命令和相關資源集合。
進程的狀態:
新的:進程正在被創建 運行:指令正在被執行 等待:進程等待某個事件的發生(如I/O完成或收到信號) 就緒:進程等待分配處理器 終止:進程完成執行重要:一次只有一個進程可在一個處理器上運行,但是多個進程可處於就緒或等待狀態。
進程塊控制(process control block,PCB):每個進程在操作系統內用進程控制塊來表示,其包含許多與一個特定進程相關的信息。
進程狀態:狀態可包括新的,就緒,運行,等待,停止
程序計數器:計數器表示進程要執行的下個指令的地址。
CPU寄存器:根據計算機結構體系的不同,寄存器的數量和類型也不同。他包括累計器,索引寄存器,堆棧指針,通用寄存器和其他條件碼信息寄存器。
CPU調度信息:包括進程優先級,調度隊列的指針等
內存管理信息:根據操作系統所使用的內存系統,該類信息包括基址和界限寄存器的值,頁表或段表。
記賬信息:包括CPU時間,實際使用時間,時間界限,記賬數據,作業或進程數量
I/O狀態信息:包括分配給進程I/O設備列表,打開的文件列表等等。
多道程序設計的目的就是無論何時都有進程在運行,從而使CPU利用率達到最大。
進程調度:選擇一個可用的進程到CPU上執行。
調度隊列:進程進入系統時,會被加到作業隊列中,該隊列包括系統中的所有進程。駐留在內存中就緒的,等待運行的進程保存在就緒隊列中。該隊列通常用鏈表來實現,頭結點指向鏈表的第一個個和最後一個PCB塊的指針。每個PCB包含一個指向就緒隊列的下一個PCB的指針域。
等待特定I/O設備的進程列表稱為設備隊列。
討論進程調度的常用表示方法是隊列圖。
當進程分配到CPU並執行時,可能發生的情形:
進程可能發出一個I/O請求,並被放到I/O隊列中。 進程可能創建一個新的子進程,並等待期結束 進程可能會由於中斷而強制釋放CPU,並被放回到就緒隊列中。調度程序
長期調度程序(long-term scheduler) 或作業調度程序(job shceduler)從該池中選擇進程,並裝入內存以准備執行。
短期調度程序(short-term scheduler)或CPU調度程序從准備執行的進程中選擇進程並為之分配CPU.
上下文切換:將CPU切換到另一個進程需要保存當前進程的狀態並恢復另一個進程狀態。
進程創建
進程在執行過程中,能通過創建進程系統調用創建多個新進程。大多數操作系統根據一個唯一標識符(process identifier,pid)來識別進程,pid通常是一個數值。
當進程創建新進程時,有兩種執行可能:
父進程與子進程並發執行 父進程等待,直到某個或全部子進程執行完畢並發和並行的區別:?
新進程的地址空間也有兩種可能:
子進程是父進程的復制品(具有與父進程相同的程序和數據) 子進程裝入另一個新程序在UNIX操作系統中,每個進程都有唯一的標識符。通過fork()系統調用,可創建新進程。新進程通過復制原來進程的地址空間而成。這種機制允許父進程與子進程方便的進行通信。兩個進程(父進程和子進程)都繼續執行位於系統調用fork()之後的指令。但是,有一點不同:對於新子進程,系統調用fork()的返回值為0;而對於父進程,返回值為子進程的進程標識符(非零)。
通常,在系統調用fork()之後,一個進程會使系統調用exec(),以用新程序來取代進程內存空間。系統調用exec()將二進制文件裝入內存(消除了原來包含系統調用exec()的程序的內存映射),並開始執行。采用這種方式,兩個進程能互相通信,並能按各自的方法執行。
進程終止
當進程完成執行後最後的語句並系統調用exit()請求操作系統刪除自身是,進程終止。這時,進程可以返回狀態值(通常為整數)到父進程(通過系統調用wait())。
進程間的通信的兩種基本模式:共享內存和消息傳遞
共享內存系統
采用共享內存的進程間通信需要通信進程建立共享內存區域。通常,一塊共享內存區域駐留在生成共享內存段進程的地址空間。其他希望使用這個共享內存段進行通信的進程必須將此放到他們自己的地址空間上。
eg: POSIX,表示可移植操作系統接口(Portable Operating System Interface ,縮寫為 POSIX ),POSIX標准定義了操作系統應該為應用程序提供的接口標准,是IEEE為要在各種UNIX操作系統上運行的軟件而定義的一系列API標准的總稱,其正式稱呼為IEEE 1003,而國際標准名稱為ISO/IEC 9945。
POSIX標准意在期望獲得源代碼級別的軟件可移植性。換句話說,為一個POSIX兼容的操作系統編寫的程序,應該可以在任何其它的POSIX操作系統(即使是來自另一個廠商)上編譯執行。
消息傳遞系統
消息傳遞工具:發送消息,接收消息,通信線路
命名:直接通信,間接通信(郵箱) 同步:消息傳遞可以是阻塞或非阻塞(也稱為同步或異步)緩沖:不管通信是直接還是間接的,通信進程所交換的信息都駐留在臨時隊列中,簡單的講,隊列實現有三種方法:
零容量 :隊列的最大長度為0;因此,線路中不能有任何消息處於等待。即必須阻塞發送,直到接收者接收到消息。
有限容量:隊列長度為有限的n;因此,最多只能有n個消息駐留在隊列中,如果發送新消息是隊列未滿,那麼該消息可以放在隊列中(或者復制消息或者保存消息的指針),其發送者可以繼續執行而不必等待。不過線路容量有限。如果線路滿,則必須阻塞發送者直到隊列中的空間可用為止。
無限容量:隊列長度可以無限,因此不管多少消息都可在其中等待,從不阻塞發送者。
eg: Mach [mɑk],Mach是一個由卡內基梅隆大學開發的用於支持操作系統研究的操作系統內核,是基於共享內存的 IPC系統.
線程:是CPU使用的基本單元,它由線程ID,程序計數器,寄存器集合和棧組成。它與屬於統一進程的其他線程共享代碼段、數據段和其他操作系統資源。
多線程的優點:
響應度高 共享資源:默認共享他們所屬進程的內存和資源。 經濟:線程可以共享資源,創建和替換速度比進程塊。 多處理體系結構的利用:能充分利用多處理器體系結構,以便每個進程能並行運行在不同的處理器上。線程支持:用戶層的用戶線程和內核層的內核線程;
用戶線程和內核線程之間的關系模型:
多對一模型:將許多用戶級線程映射到一個內核線程。線程管理是在用戶空間進行的,因而效率比較高。但是如果一個線程執行了阻塞系統調用,那麼整個進程會阻塞。而且,因為任意時刻只有一個線程能訪問內核,多個線程不能並行運行在多處理器上。(Solaries) 一對一模型:將每個用戶線程映射到一個內核線程。該模型在一個線程執行阻塞系統調用時,能允許另一個線程繼續執行,所以它提供比多對一模型更好的並發功能;他也允許多個線程能並行的運行在多處理器系統上.但缺點是每創建一個用戶線程就需要創建一個相應的內核線程,開銷大,限制了系統所支持的線程數量。(Linux 和 Windows) 多對多模型:多路復用了許多用戶線程到同樣數量或更小數量的內核線程上。線程庫:為程序員提供創建和管理線程的API.
實現方法:
在用戶空間中提供一個沒有內核支持的庫。 執行一個由操作系統直接支持的內核級庫。目前使用三種主要的線程庫是:
POSIX Pthread(用戶級或內核級) Win32(內核級) Java:用戶級在UNIX中,fork()用兩種形式,一種復制所有線程,另一種只復制調用了系統調用fork()的線程。
系統調用exec():如果一個線程調用了系統調用exec(),那麼exec()參數所指定的程序會替換整個進程,包括所有線程。
線程取消:是在線程完成之前來終止線程的任務。
目標線程取消:
異步取消(asynchronous cancellation):一個線程立即終止 目標線程。 延遲取消(deferred cancellation):目標線程不斷的檢查它是否應終止,這允許目標線程有機會以有序方式來終止自己。信號:在UNIX中用來通知進程某個特定事件已發生了。
信號分為同步信號和異步信號。
信號處理程序:默認處理程序和自定義處理程序。
信號發送:
發送信號到信號所應用的線程。 發送信號到進程內的每個線程。 發送信號到進程內某些固定線程。 規定一個特定線程以接收進程的所有信號。線程池:主要思想是在進程開始時創建一定數量的線程,並放入到池中以等待工作。當服務器收到請求時,他會喚醒池中的一個線程(如果有可以用的線程),並將要處理的請求傳遞給它。一旦線程完成了服務,它會返回到池中等待以等待工作。如果池中沒有可用的線程,那麼那麼服務器會一直等待直到有空線程為止。
輕量級進程(LWP):多線程中內核與線程庫之間的通信,在許多實現多對多的模型和二級模型系統在用戶和內核線程之間設置一種中間數據結構。對於用戶線程庫,LWP表現為一種應用程序程序可以調度用戶線程來運行的虛擬處理器。每個LWP與內核線程相連,該內核線程被操作系統調度到物理處理器上運行。如果內核線程阻塞,LWP也阻塞,相應的與該LWP相連的用戶線程也阻塞。
調度激活器(scheduler activation):內核提供一組虛擬處理器(LWP)給應用程序,應用程序可調度用戶線程到一個可用的虛擬處理器上。
一個線程通常包含:
一個線程ID,以唯一標識線程。 一組寄存器集合,以表示處理器狀態。 一個用戶棧,以供線程在用戶模式下運行;一個內核堆棧,以供線程在內核模式下運行。 一個私有存儲區域,為各種運行時庫和動態鏈接庫所用。寄存器集合,棧和私有存儲區通常稱為上下文。
Linux 提供了具有傳統進程復制功能的系統調用 fork(),還提供用系統調用clone()創建線程的功能,Linux並不區分進程和線程。
clone()被調用時,它被傳遞一組標志,以決定父任務與子任務之間發生多少共享。
CPU調度是多道程序操作系統的基礎。通過在進程之間切換CPU,操作系統可以提高計算機的吞吐率。
多道程序設計:道程序設計技術是在計算機內存中同時存放幾道相互獨立的程序,使它們在管理程序控制下,相互穿插運行,兩個或兩個以上程序在計算機系統中同處於開始到結束之間的狀態。與之相對應的是單道程序,即在計算機內存中只允許一個的程序運行。
每當CPU空閒時,操作系統就必須從就緒隊列中選擇一個進程來執行。進程選擇由短期調度程序或CPU調度程序執行。調度程序從內存中選擇一個能夠執行的進程,並為之分配CPU.
CPU調度決策發生的四種環境:
當一個CPU從運行狀態切換到等待狀態(I/O請求或調用wait) 當一個進程從運行狀態切換到就緒狀態(當出現中斷) 當一個進程從等待狀態切換到就緒狀態(I/O完成) 當一個進程終止時。分派程序(dispatcher):分派程序是一個模塊,用來將CPU的控制交給由短期調度程序選擇的進程。其功能包括:
切換上下文 切換到用戶模式 掉轉到用戶程序的合適位置,以重新啟動程序。CPUd調度算法准則:
CPU使用率 吞吐量 周轉時間 等待時間 響應時間CPU調度處理是從就緒隊列中選擇進程並為之分配CPU的問題。
調度算法包括:
先到先服務調度(first-come,first-served(FCFS) Scheduling algorithm):可使用FIFO隊列來容易實現。FCFS調度的代碼編寫簡單且容易理解。但其平均等待時間通產較長。 最短作業優先調度(shortest-job-first(SJF) scheduling algorithm):當cpu空閒時,它會賦給具有最短CPU區間的進程。SJF調度算法可證明微微诶最佳的,這是因為對於給定的一組進程,SJF的平均等待時間最小。SJF的難點是無法知道下一個CPU區間的長度。一種方法是近似SJF,預測。SJF可能是搶占的或非搶占的。 優先級調度(priority scheduling algorithm):每個進程都有一個優先級與其關聯。優先級調度可以是搶占或非搶占的。但其主要問題是:無窮阻塞(indefinite blocking)或饑餓(starvation)。 輪轉法(round-robin,RR):調度算法是專門為分時系統設計的。其類似於FCFS調度,但是增加了搶占以切換進程。定義一個較小的時間單元,稱為時間片(time quantum, or time slice).時間片通常為10-100ms.將就緒隊列作為循環隊列。CPU調度程序循環就緒隊列,為每個進程分配不超過一個時間片的CPU.RR算法的性能很大程度上依賴於時間片的大小。在極端情況下,如果時間片非常大,那麼RR算法與FCFS算法一樣。如果時間片很小,那麼RR算法稱為處理器共享,在理論上講,n個進程對於用戶都有它自己的處理器,速度為真正處理器速度的1/n。 多級隊列調度(multilevel queue scheduling algorithm):將就緒隊列分成多個獨立隊列。根據進程的屬性,如內存大小,進程優先級,進程類型,一個進程被永久的分配到一個隊列。每個隊列有自己的調度算法。隊列和隊列之間必須有調度,通常采用固定優先級搶占調度。 多級反饋隊列調度算法(mutilevel feedback queue scheduling algorithm):與多級隊列調度相反,其允許進程在隊列之間移動。主要思想是根據CPU區間的特點以區分進程。如果進程使用過多的CPU時間,那麼它會被轉移到更低優先級隊列。此外,在較低優先級隊列中等待時間過長的進會被轉移到更高優先級隊列。非對稱多處理器(asymmetric multiprocessing):在一個多處理器中,CPU調度的方法是讓一個處理器(主服務器)處理所有的調度決定,I/O處理以及其他活動,其他的處理器值執行用戶代碼。
對稱多處理器(symmetric multiprocessing,SMP):即每個處理器自我調度。所有進程可能處於一個共同的就緒隊列中,或每個處理器都有它自己的私有就緒進程隊列。無論如何,調度通過每個處理器檢查共同就緒隊列並選擇一個進程來執行。
處理器親和性:由於使緩存無效或重構代價高,對大多數SMP系統試圖避免將進程從一個處理器移至另一個處理器,而是努力使一個進程子啊同一個處理器上運行,被稱為處理器親和性。
負載平衡(load balanceing):設法將工作負載平均的分配到SMP系統中的所有處理器。
負載平和通常有兩種方法:
push migration:一個特定的任務周期性的檢查每個處理器上的負載,如果發現不平衡,即通過將進程從超載處理器移到(或推送到)空閒或不太忙的處理器,從而平均低分配負載。當空閒處理器從一個忙的處理器上推送(pull)一個等待任務時,發生 pull migration:當空閒處理器從一個忙的處理器上推送(pull)一個等待任務時,發生pull miggration。提供多個物理處理器,SMP系統允許同時運行幾個線程。另一種方法是提供多個邏輯(而不是物理)處理器來實現。這種方法被稱為對稱多線程(SMT),在Intel 處理器上,被稱為超線程(hyperthreading)技術。
SMT的思想是在同一個物理處理器上生成多個邏輯處理器,下個操作系統呈現一個多邏輯處理器的試圖,即使系統僅有單處理器。
用戶線程和內核賢線程的區別之一就是他們說是如何被調度的。
在執行多對一和多對多的模型時,線程庫調度用戶級線程到一個有效LWP上運行,被稱為進程競爭范圍(process-contention scope,PCS),因為CPU競爭發生在屬於相同進程的線程之間。
為了決定調度哪個內核線程到CPU,內核采用系統競爭范圍(system-contention scope,SCS).采用SCS調度方法,競爭CPU發生在系統的所有線程中。
Solaris :采用基於優先級的線程調度。
Windos XP:基於優先級的,搶占調度算法來調度線程。
Linux調度:搶占的,基於優先級的算法,具有兩個獨立的優先級范圍:從0~99的real-time范圍和從100~140的nice范圍。其映射到全局
優先級,其中數值越低表明優先級越高。Linux給較高的優先級分配較長的時間片,給較低的優先級分配較段的時間片。
多個進程並發訪問和操作同一數據且執行結果與訪問發生的特定順序有關,稱為競爭條件(race condition)。為了避免競爭條件,需要確保一段時間內只有一個進程能操作變量,其必須進行一定形式的同步。
臨界區(critial section)特點:
互斥(mutual exclusion):如果進程P在其臨界區執行,其他進程都不能在其臨界區執行。 前進(progress):如果沒有進程在其臨界區內執行且有進程序進入臨界區,那麼只有那些不再剩余區內執行的進程可參加選擇,以確定誰能在下一個進入臨界區,且這種選擇不能無限推遲。 有限等待(bounded waiting):從一個進程做出進入臨界區的請求知道請求被允許為止,其他進程允許進入臨界區的次數有上限。兩種處理操作系統內臨界區問題的方法:
搶占內核(preemptive kernel):搶占內核允許處於內核模式的進程被搶占。 非搶占內核(nonpreemptive kernel):不允許處於內核模式的進程被搶占。鎖:在進入臨界區之前得到鎖,而在其退出臨界區是釋放鎖。
許多現代操作系統提供了特殊硬件指令以允許能原子地(不可中斷地)檢查和修改子的內容或交換兩個字的內容。
信號量(semaphore):一種同步工具,信號量S是個整數變量,除了初始化外,他只能通過兩個標准原子操作:wait()和signal()來訪問。
死鎖(deadlock):在多道程序環境下,多個進程可能競爭一定數量的資源。某個進程申請資源,如果這時資源不可用,那麼該進程進入等待狀態。如果所申請的資源被其他等待進程占有,那麼該等待進程有可能再也無法其狀態。
在正常模式下,進程只能按如下順序使用資源:
申請 使用 釋放當出現死鎖時,進程永遠不能完成,並且系統資源被阻礙使用,阻止了其他作業開始執行。
死鎖問題可用稱為系統資源分配圖的有向圖進行更為精確的描述。
若分配圖沒有環,那麼系統就沒有進程死鎖。如果分配圖有環,那麼可能存在死鎖。
死鎖預防(deadlock prevention):是一組方法,以確保至少一個必要條件不成立;
死鎖避免(deadlock avoidance):要求操作系統事先得到有關進程申請資源和使用資源的額外信息。