進程不僅是執行中的程序代碼,還包括當前活動(經過程序計數器的值和處理器寄存器的內容來表示)、進程堆棧段(包括臨時數據如函數參數、返回地址和局部變量)、數據段(包括全局變量)、堆(在進程運行期間動態分配的內存)。java
內存中的進程結構:程序員
程序不是進程,程序是存儲在磁盤上的包含一系列指令的文件內容(被動實體),而進程是有一個程序計數器用於表示下一個要執行的命令和相關資源集合(活動實體)。服務器
多個進程能夠與同一程序相關,但進程之間相互獨立。網絡
PCB:每一個進程在操做系統內用進程控制塊(process control block,PCB,也稱爲任務控制塊)來表示。數據結構
進程狀態:新建、運行、等待、就緒、終止。併發
一次只有一個進程能夠再一個處理器上運行,但有多個進程可處於就緒或等待狀態。app
程序計數器:表示進程要執行的下個指令的地址。異步
CPU寄存器:包括累加器、索引寄存器、堆棧指針、通用寄存器和其餘條件碼信息寄存器,根據不一樣的計算機體系結構有不一樣的類型和數量。分佈式
CPU調度信息:包括進程優先級、帶哦度隊列的指針和其餘調度參數。ide
內存管理信息:包括基址和界限寄存器的值、頁表或段表。
記帳信息:包括CPU時間、實際使用時間、時間界限、記帳數據、做業或進程數量等。
I/O狀態信息:包括分配給進程的I/O設備列表、打開的文件列表等。
出現中斷時,須要保存程序計數器和CPU寄存器的狀態信息。
進程調度:從多個可用進程集合中選擇一個可用的進程到CPU上執行。
Linux操做系統的PCB經過C結構task_struct表示,內核中全部活動進程由task_struct的雙向鏈表表示,爲當前正在運行的進程保留一個指針current。
做業隊列:包括系統中的全部進程,進程進入系統時會被加入到做業隊列。
設備隊列:等待特定I/O設備的進程列表,每一個設備都有本身的設備隊列。
就緒隊列:包括等待運行的進程。一般用鏈表實現,頭結點指向鏈表的第一個和最後一個PCB塊的指針,每一個PCB包括一個指向就緒隊列的下一個PCB的指針域。
隊列圖:討論進程調度的經常使用表示方法,長方形表示隊列(就緒隊列和設備隊列),圓形表示資源,箭頭表示系統內進程流向。
新進程開始於就緒隊列,在就緒隊列中等待直到被選中執行或派遣;
進程分配到CPU並執行時,可能發生的幾種事件:
·發出I/O請求並被放到I/O隊列中
·建立一個新的子進程並等待其結束
·因爲中斷而強制釋放CPU並被放回到就緒隊列
進程終止時將從全部隊列中刪除,釋放PCB和資源。
調度程序(scheduler):執行按某種方式從調度隊列中選擇進程的程序。
長期調度程序(long-term scheduler或做業調度程序job scheduler):批處理系統中進程提交後一般被放到大容量存儲設備(磁盤)的緩衝池中保存以便之後執行,長期調度程序從該池中選擇進程並裝入內存,以準備執行。
長期調度程序控制多道程序設計的程度(內存中的進程數量);
長期調度程序受資源分配考慮,尤爲是內存管理的影響;
長期調度程序選擇的進程主要包括I/O爲主的進程(I/O-bound process)和CPU爲主的進程(CPU-bound process);
I/O爲主的進程時間主要花費在執行I/O方面,與等待隊列有關;
CPU爲主的進程時間主要花費在執行計算方面,與就緒隊列有關;
應合理選擇一個包含I/O爲主進程和CPU爲主進程的組合,使系統平衡。
短時間調度程序(short-term scheduler或CPU調度程序):從準備執行的進程(就緒隊列)中選擇進程,併爲之分配CPU。
主要差異:執行頻率。短時間調度程序執行頻繁,一般每100ms執行一次;長期調度程序執行不頻繁,可能有數分鐘間隔。
中期調度程序(medium-term scheduler):用交換(swapping)的手段,將進程從內存中換出,下降多道程序設計的程度。以後從新換入內存,並從中斷處繼續執行。
上下文切換(context switch):將CPU切換到另外一個進程時保存當前進程狀態並恢復另外一個進程的狀態;
發生中斷時,內核保存舊進程的上下文(以便下次恢復),裝入經調度須要執行並已保存的新進程的上下文;
進程上下文用進程的PCB表示;
上下文切換時間爲額外開銷,與硬件支持有關;
pid:大多數操做系統根據一個惟一的進程標識符(process identifier,pid)識別進程,一般是一個整數值。
操做系統必須爲父進程建立子進程提供機制,父進程在繼續以前能夠等待子進程終止,也能夠併發執行;
併發執行的優勢:信息共享、運算速度、模塊化和便利性等;
子進程可能從操做系統直接得到資源,也可能只從父進程得到資源;
父進程可能必須在其子進程之間分配資源,限制子進程只能使用父進程資源從而防止系統超載;
操做系統內併發執行的進程能夠是獨立進程或協做進程;
獨立進程:不能影響其餘進程或被其餘進程影響;
協做進程:能影響其餘進程或被其餘進程影響;
IPC(進程間通訊機制,interprocess communication):容許協做進程相互交換數據與信息的機制,有兩種基本模式(1)共享內存(2)消息傳遞;
共享內存模式:創建一塊供協做進程共享的內存區域,進程經過向共享區域讀寫數據交換信息;(速度較快,僅在創建共享內存區時須要系統調用,通訊時常規內存訪問不須要來自內核的幫助)
消息傳遞模式:經過在協做進程間交換消息來實現通訊;(優勢:不須要避免衝突,適合交換少許數據;對計算機間通訊更易於實現)(缺點:系統調用頻繁,須要更多內核介入的時間消耗)
共享內存要求通訊進程共享一些變量來交換信息,主要由應用程序員提供通訊,操做系統只需提供共享內存;
共享內存解決生產者-消費者問題:爲容許生產者進程與消費者進程併發執行,必需要有一個緩衝駐留在生產者進程和消費者進程的共享內存區域內,供生產者填充並被消費者使用。當消費者使用一項時,生產者能生產另外一項;生產者和消費者必須同步,以避免消費者消費一個未生產出來的項;
無限緩衝(unbounded-buffer):對緩衝大小沒有限制,消費者可能不得不等待新項,但生產者老是能夠產生新項;
有限緩衝(bounded-buffer):緩衝大小固定,若是緩衝爲空消費者必須等待,若是緩衝爲滿,生產者必須等待;
有限緩衝的使用(該方法容許最大緩衝項數BUFFER_SIZE-1):
int in=0, out=0;
邏輯指針變量in指向緩衝中下一個空位,out指向緩衝中第一個滿位;
(in+1)%BUFFER_SIZE == out時緩衝爲滿;
生產者進程用局部變量nextProduced存儲產生的新項:
while (true) { //produce an item in nextProduced while (((in+1)%BUFFER_SIZE) == out) ; buffer[in] = nextProduced; in = (in+1)%BUFFER_SIZE; }
消費者進程用局部變量nextConsumed存儲要使用的新項:
while (true) { while (in == out) ; nextConsumed = buffer[out]; out = (out+1)%BUFFER_SIZE; //consume the item in nextConsumed }
消息傳遞系統
消息傳遞系統容許進程交換信息,提供通訊責任在於操做系統自己;
進程間經過消息傳遞通訊必需要有通訊線路(communication link),邏輯實現線路包括直接或間接通訊、同步或異步通訊、自動或顯示緩衝等;
直接通訊:須要通訊的每一個進程必須明確命名通訊的接收者或發送者(對稱尋址);
原語定義:send(P, message); receive(Q, message);
直接通訊線路具備屬性:
1. 須要通訊的每對進程之間自動創建線路,僅需知道相互通訊的標識符;
2. 一個線路只與兩個進程相關;
3. 每對線程之間只有一個線路;
變形:非對稱尋址,只要發送者命名接收者,接收來自任何進程的消息;
原語定義:send(P, message); receive(id, message);
對稱/非對稱尋址的缺點:限制了進程定義的模塊化,改變進程的名稱可能必須檢查全部其餘進程定義。
間接通訊:經過端口或郵箱(一個抽象對象)發送和接收消息,進程能夠向郵箱中存放/刪除消息,每一個郵箱都有一個惟一的標識符;
原語定義:send(mailbox, message); receive(mailbox, message);
間接通訊線路屬性:
1. 兩個進程至少共享一個郵箱時才能通訊;
2. 一個線路能夠與兩個或更多進程關聯;
3. 兩個通訊進程間能夠有多個不一樣線路,每一個線路對應一個郵箱;
進程或操做系統能夠擁有郵箱;
若是郵箱爲進程全部,須要區分爲進程全部,須要區分擁有者(經過郵箱接收消息)和使用者(向郵箱發送消息),當擁有郵箱的進程終止時郵箱消失;
郵箱的擁有者默認爲建立郵箱的進程,但經過系統調用,擁有權和接收權可能傳遞給其餘進程;
由操做系統擁有的郵箱是獨立存在的,不屬於某個特定進程,操做系統需提供機制容許建立/刪除郵箱和經過郵箱發送/接收消息;
阻塞send:發送進程阻塞,直到消息被接收進程或郵箱接收
非阻塞send:發送進程發送消息並繼續操做
阻塞receive:接收者阻塞,直到有消息可用
非阻塞receive:接收者收到一個有效消息或空消息
send()和receive()可進行多種組合
不管直接或間接通訊進程,交換的信息都駐留在臨時隊列中,隊列實現有三種方法:
1. 零容量:隊列最大長度爲0,線路中不能有任何消息處於等待狀態,必須阻塞發送,直到接收者接收到消息。
2. 有限容量:隊列長度爲有限的n,最多隻能有n個消息駐留。發送消息時若是隊列未滿,消息可存放在隊列中,發送者可繼續執行;若是隊列滿,必須阻塞發送,直到隊列中空間可用。
3. 無限容量:隊列長度能夠無限,從不阻塞發送。
零容量稱爲沒有緩衝的消息系統,其餘狀況稱爲自動緩衝。
共享內存和消息傳遞也可用於客戶機-服務器系統通訊,此外,客戶機-服務器系統通訊還有三種通訊方法:Socket、遠程過程調用(RPC)、Java遠程發發調用(RMI);
Socket:通訊的端點,由IP地址和端口號鏈接組成,一對通訊進程使用一對Socket,每端各有一個通訊頻道;
低於1024的服務器端口用於實現標準服務,客戶機發出鏈接請求時賦予大於1024的端口號;
服務器監聽端口,收到客戶請求,接受來自客戶端Socket的鏈接,創建鏈接傳輸數據包;
全部的鏈接都有惟一的一對Socket;
Socket通訊經常使用高效,但只容許在通訊線程之間交換無結構的字節流,屬於較爲低級的分佈式進程通訊。
RPC(遠程過程調用):用於網絡及鏈接系統,基於(IPC)消息通訊方案提供遠程服務;
與IPC不一樣,交換的消息有很好的數據結構,不只僅是數據包;
消息傳遞給遠程系統上監聽端口號的RPC服務器,返回結果經過另外一個消息傳遞給請求者;
每一個獨立的遠程過程都有一個stub(存根),RPC系統在客戶端提供stub;
客戶端調用遠程過程(調用遠程應用的方法)àRPC調用合適的stub並傳遞相應參數àstub定位服務器的端口並編組(marshal)參數àstub傳遞消息(以消息傳遞的方式)給服務器à服務器端一個類似的stub接收消息並調用服務器端的過程à必要時返回值傳回給客戶端;
許多RPC系統都定義了數據的及其無關標書,如外部數據表示(XDR),用於處理客戶機和服務器系統數據表示差異問題;
因爲普通網絡錯誤可能會致使RPC重複屢次執行,處理方法是操做系統確保一個消息恰好執行一次;
首先經過爲每一個消息附加時間戳,服務器經過時間戳歷史檢驗重複消息保證消息最多執行一次;
在最多一次協議基礎上,客戶機週期性重發RPC調用直到接收到該調用的ACK,確保客戶端已經接收到RPC並已執行,保證消息執行恰好一次;
RPC方案中客戶端須要知道與其綁定的服務器端口,有兩種方法:
1. 綁定信息以固定端口地址的形式預先肯定:編譯時每一個RPC調用都有一個固定端口號,編譯後服務器不能改變所請求服務的端口號;
2. 經過集合點機制(rendezvous mechanism)動態綁定:操做系統在固定的RPC端口上提供集合點(也稱爲matchmaker)服務程序,客戶端將包含RPC名稱的消息發送給rendezvous,請求所需執行的RPC端口地址->rendezvous返回端口號(可一直將RPC調用發送給該端口,直到進程終止或服務器崩潰,該方法須要初始請求的額外開銷,但更靈活)。
RMI:遠程方法調用(remote method invocation),相似RPC的java特性,容許線程調用遠程(位於另外一JVM上的)對象的方法;
RMI與RPC的區別:
1. RMI基於對象,支持調用遠程對象,RPC只能調用遠程的子程序或函數;
2. RMI可將對象做爲參數傳遞,而RPC參數是普通數據結構;
客戶機調用遠程方法的過程:
調用客戶機中的存根(stub),建立包含服務器上要調用的方法名稱和編排參數的包,發送給服務器端;
骨幹(skeleton)接收stub發送的包,從新編排參數,調用服務器上所要執行的方法(方法的真正實現駐留在服務器上),方法完成後skeleton編排返回值(或異常),打包返回給客戶端;
stub從新編排返回值,傳遞給客戶機;