以下內容從《操做系統精髓與設計原理》中總結提煉得出,刪除了大部分對於理解進程有干擾的文字,對進程知識結構進行的梳理。幾乎全部內容爲按照書本上摘抄下來的,我目前還總結提煉不出像做者這麼深入的看法。那麼就先學習等徹底理解透了,再用本身的語言表達出來。它山之石,能夠攻玉。php
進程的概念是操做系統的結構的基礎。Multics的設計者在20世紀60年代首次使用了這個技術詞語,它比做業更通用一些。關於進程的定義,以下所示:
1.一個正在執行的程序。
2.計算機中正在運行的程序的一個實例。
3.能夠分配給處理器並由處理器執行的一個實體。
4.由單一的順序的執行線程、一個當前狀態和一組相關的系統資源所描述的活動單元。css
也能夠把進程當成由一組元素組成的實體,進程的兩個基本的元素是程序代碼
(可能被執行相同程序的其餘進程共享)和代碼相關聯的數據集
。假設處理器開始執行這個程序代碼,且咱們把這個執行實體叫作叫作進程
。在進程執行時,任意給定一個時間,進程均可以惟一的被表徵爲如下元素。linux
1.標識符:跟這個進程相關的惟一標識符,用來區別其餘進程。
2、狀態:若是進程正在執行,那麼進程處於運行態。
3、優先級:相對於其餘進程的優先級
4、內存指針:包括程序代碼和進程相關數據的指針,還有和其餘進程共享內存塊的指針。
5、上下文數據:進程執行時處理器的寄存器中的數據。
6、I/O 狀態信息:包括顯示的I/O操做。分配給進程的I/O設備(例如磁帶驅動器)和被進程使用的文件列表等。
7、記帳信息:可能包括處理器時間綜合、使用的是時鐘數總和、時間限制、記帳號等。
以下圖:程序員
一、爲何設計了進程?
設計出一個可以協調各類不一樣活動的系統軟件是很是困難的。在任什麼時候刻都有許多做業在運行中,每一個做業都包括要求按照順序執行的不少步驟,所以分析時間的序列組合是不可的。因爲缺少可以在全部活動中進行協調和合做的系統級的方法,程序員只能基於他們對操做系統所控制的環境的理解,採用本身的特殊方法。然而這種方法是很脆弱的,尤爲對於一些程序設計中的小錯誤,由於這些錯誤只有在不多見的時間序列發生時纔會出現。因爲須要從應用程序軟件錯誤和硬件錯誤中區分出這些錯誤,於是診斷工做是很困難的。及時檢測出錯誤,也很難肯定緣由,由於很難在線錯誤產生的精確場景。通常而言,產生這類錯誤的4個主要緣由以下:
1.不正確同步
2.失敗互斥。
3.不肯定的程序操做
4.死鎖服務器
以上詳細描述請參閱:《操做系統精髓與設計原理》第六版第二章或查看網頁版】數據結構
解決這些問題須要一種系統級別的方法監控處理器中不一樣程序的執行。進程的概念爲
此提供了基礎。
所以進程能夠看作是由三部分組成的:
1.一段能夠執行的程序
2.程序所須要的相關數據
3.程序的執行上下文性能
二、瞭解進程執行上下文
執行上下文是進程的重重之中。執行上下文(execution context)
又稱做進程狀態(process state)
,是操做系統用來管理和控制進程所需的內部數據。這種內部信息和進程是分開的,由於操做系統信息不容許被進程直接訪問。上下文包括操做系統管理進程以及處理器正確執行進程所須要的全部信息。包括了各類處理器寄存器的內容,如程序計數器和數據寄存器。它還包括操做系統使用的信息,如進程優先級以及進程是否在等待特定 I/O事件的完成。學習
圖1
圖1 兩個進程A 和B ,存在於內存中某部分。也就是說給每一個進程(包含程序、數據和上下文信息)分配一塊存儲器區域,而且在由操做系統創建和維護的進程表中進行記錄。進程表中包含記錄每一個進程的表現,表項內容包括指向包含進程的存儲塊地址的指針,還包括該進程的部分或所有執行上下文。指向上下文的其他部分存放在別處,可能和進程本身保存在一塊兒,一般也可能保存在內存裏一塊獨立的區域中。進程索引寄存器(process index register)
包含當前正在控制處理器的進程在進程表中的索引。程序計數器
指向該進程中下一條待執行的指令。基址寄存器(base register)
和界限寄存器(limit register)
定義了該進程所佔據的存儲器區域:基址寄存器
中保存了該存儲器區域的開始地址,界限寄存器
中保存了該區域的大小(以字節或字爲單位)。程序計數器和全部的數據引用相對於基址寄存器
被解釋,而且不能超過界限寄存器
中的值,這就能夠保護內部進程間不會相互干涉。(解決了互斥的問題)spa
圖1進程索引寄存器
代表進程B正在執行。之前執行的進程被臨時中斷,在A中斷的同時,全部的寄存器的內容被記錄在它執行上下文環境中,之後操做系統就能夠執行進程切換,恢復進程A的執行。進程切換過程包括保存B的上下文和恢復A的上下文。當在程序計數器
中載入指向A的程序區域的值時,進程A自動恢復執行。操作系統
所以進程被當作數據結構來實現。一個進程能夠是正在執行,也但是等待執行。任什麼時候候整個進程狀態都包含在它的執行上下文環境中。這個結構使得能夠開發功能強大的技術,以確保在進程中進行協調和合做。在操做系統中可能會設計和併入一些新的功能(優先級,linux中nice值。)這能夠經過擴展上下文環境以包括支持這些特徵的新信息。
三、兩狀態進程模型
操做系統的基本職責是控制進程的執行。這包括肯定交替執行的方式和給進程分配資源在設計控制進程的程序時,第一步就是描述進程所表現出的行爲。
由前面的基礎知識介紹可知,在任什麼時候刻,一個進程要麼正在執行,要麼沒有執行,於是能夠構造最簡單的模型。一個進程能夠處於如下兩種狀態之一:運行態或未運行態。當操做系統建立一個新的進程時,它將該進程運行態加入到系統中,操做系統知道這個進程是存在的,而且正在等待執行機會。當前正在運行的進程時不時的被中斷,操做系統中的分派器
部分將選擇一個新進程運行。前一個進程從運行態轉換到未運行狀態,另一個集成轉換到運行態。以下圖.
從這個簡單的模型能夠意識到操做系統的一些設計元素。必須用某種方式來表示每一個進程,使得操做系統可以跟蹤它,也就是說,必須有一些與進程相關的信息,包括進程在內存中的當前狀態和位置,即進程控制塊
。未運行的進程必須保持在某種類型的隊列中,並等待它們的執行時機。結構中有一個隊列,隊列中的每一項都指向某個特定進程的指針,或隊列能夠由數據塊構成的鏈表組成,每一個數據塊表示一個進程。以下圖
所以能夠用該隊列圖描述分派器
的行爲。被中斷的進程轉移到等待進程隊列中,或者,若是進程已經結束或取消,則被銷燬(離開系統)。在任何一種狀況下,分派器
均從隊列中選擇一個進程來執行。
四、進程的建立和終止
進程建立
傳統地,操做系統建立進程的方式對用戶和應用程序都是透明的,這在當代操做系統中也很廣泛。可是容許一個進程引起另外一個進程的建立將是頗有用的。例如一個程序進程能夠產生另外一個進程,以接受應用程序產生的數據,並將數據組織成適合之後分析的格式。新進程與應用程序並行
的運行,並當獲得新的數據時被激活。這個方案對於構造應用程序是很是有用的,例如,服務器進程(如打印服務器、文件服務器)能夠爲它處理的每一個請求產生一個新進程。當操做系統爲另外一個進程的顯式請求產生一個新進程時,這個動做稱爲進程派生。
當一個進程派生另外一個進程時,前一個稱做父進程
,被派生的進程稱做子進程
。在典型的狀況下,相關進程須要像話之間通訊和合做。對程序員來講,合做是一個很是困難的任務。
進程終止
如下事件會致使進程終止,尤爲注意最後兩種事件。父進程終止與父進程請求終止子進程。
五、進程的五狀態模型
若是全部的進程都作好了執行準備。隊列是先進先出(first-in-first-out)
的表,對於可運行的進程處理器以一種輪轉(round-robin)
方式操做(依次給隊列中的每一個進程必定的執行時間,而後進程返回隊列,阻塞狀況除外)。可是存在着一些非運行狀態但已經就緒等待執行的進程,而同時存在另外的一些處於阻塞狀態等待I/O操做結束的進程。所以,若是使用單個隊列,分派器不能只考慮隊列中最老的進程,相反,他應該掃描這個列表,查找那些被阻塞且在隊列中時間最長的進程。
解決這種狀況的一種比較天然的方法是將非運行狀態分紅兩個狀態:就緒(ready)
和阻塞(blocked)
,此外應該增長兩個已經證實頗有用的狀態。
運行態:該進程正在執行。假設計算機只有一個處理器,所以一次最多隻有一個進程處於這個狀態。
就緒態:進程作好了準備,只要有機會就開始執行。
阻塞/等待態:進程在某些事件發生前不能執行,如I/O操做完成。
新建態:剛剛建立的進程,操做系統尚未把它加入到可執行進程組中。一般是進程控制塊已經建立但尚未加載到內存中的新進程。
退出態:操做系統從可執行進程組中釋放出的進程,或者是由於它自身中止了,或者是由於某種緣由被取消。
新建態
和退出態
對進程管理是很是有用的。新建狀態對應於剛剛定義的進程。例如,若是一位新用戶試圖登陸到分時系統中,或者一個新的批做業被提交執行,那麼操做系統能夠分兩步定義新進程。首先,操做系統執行一些必需的輔助工做,將標識符關聯到進程,分配和建立管理進程所須要的全部表。此時,進程處於新建狀態,這意味着操做系統已經執行了建立進程的必需動做,但尚未執行進程。
例如,操做系統可能基於性能或內存侷限性的緣由,限制系統中的進程數量。當進程處於新建態時,操做系統所須要的關於該進程的信息保存在內存中的進程表中,但進程自身還未進入內存,就是即將執行的程序代碼不在內存中,也沒有爲與這個程序相關的數據分配空間。當進程處於新建態時,程序保留在外存中,一般是磁盤中。
相似地,進程退出
系統也分爲兩步。首先,當進程到達一個天然結束點時,因爲出現不可恢復的錯誤而取消時,或當具備相應權限的另外一個進程取消該進程時,進程被終止;終止使進程轉換到退出態,此時,進程再也不被執行了,與做業相關的表和其餘信息臨時被操做系統保留起來,這給輔助程序或支持程序提供了提取所需信息的時間。一個實用程序爲了分析性能和利用率,可能須要提取進程的歷史信息,一旦這些程序都提取了所須要的信息,操做系統就再也不須要保留任何與該進程相關的數據,該進程將從系統中刪除。
六、UNINX的獨特進程
UNINX 中有兩個獨特的進程。進程0是一個特殊的進程,實在系統啓動時建立的。實際上,這是預約義的一個數據結構,在啓動時被加載,是交換進程。此外,進程0產生進程1,稱做初始進程,進程1是系統中的全部其餘進程的祖先。當新的交互用戶登陸到系統是,由進程1爲該用戶建立一個用戶進程。隨後,用戶進程能夠建立子進程,從而構成一棵分支書,所以任何應用程序都是由一組相關進程組成的。
七、進程控制結構:
此部分對於瞭解線程特別重要。
此部分對於瞭解線程特別重要。
此部分對於瞭解線程特別重要。
一個進程至少包括足夠的內存空間,以保存該進程的程序和數據;此外,程序的執行一般涉及用於跟蹤過程調用和過程間參數傳遞的棧。最後,與每一個進程相關聯的還有操做系統用於控制進程的許多屬性,一般:
屬性的集合稱做進程控制塊
。
程序、數據、棧、屬性的集合稱做進程映像
下圖通過了個人從新繪製,但願可以比書本上更加易懂。
以上爲進程控制塊、進程映像的關係。後續的文章會繼續沿着進程、線程的方向去走。爭取整理出一套涉及PHP進程、子進程、線程、協程的相關理論與實踐文章。 吃飯去嘍。