進程的非正式定義很是簡單:進程就是運行中的程序。程序自己是沒有生命週期的,它只是存在磁盤上面的一些指令(也多是一些靜態數據)。人們經常但願同時運行多個程序,一個正常的系統可能會有上百個進程同時在運行。數據結構
操做系統經過虛擬化(virtualizing)CPU來提供這種假象。經過讓一個進程只運行一個時間片,而後切換到其餘進程,操做系統提供了存在多個虛擬CPU的假象。這就是時分共享(time sharing)CPU技術,容許用戶如願運行多個併發進程。潛在的開銷就是性能損失,由於若是CPU必須共享,每一個進程的運行就會慢一點。併發
操做系統爲正在運行的程序提供的抽象,就是所謂的進程(process)。正如咱們上面所說的,一個進程只是一個正在運行的程序。在任什麼時候刻,咱們均可以清點它在執行過程當中訪問或影響的系統的不一樣部分,從而歸納一個進程。函數
爲了理解構成進程的是什麼,咱們必須理解它的機器狀態(machine state):程序在運行時能夠讀取或更新的內容。進程的機器狀態有一個明顯組成部分,就是它的內存。指令存在內存中,正在運行的程序讀取和寫入的數據也在內存中。所以進程能夠訪問的內存(稱爲地址空間,address space)是該進程的一部分。性能
進程的機器狀態的另外一部分是寄存器。許多指令明確地讀取或更新寄存器,所以,它們對於執行該進程很重要。例如,程序計數器(ProgramCounter,PC)(有時稱爲指令指針,Instruction Pointer或IP)告訴咱們程序當前正在執行哪一個指令;相似地,棧指針(stack pointer)和相關的幀指針(frame pointer)用於管理函數參數棧、局部變量和返回地址。spa
最後,程序也常常訪問持久存儲設備。此類I/O信息可能包含當前打開的文件列表。操作系統
操做系統運行程序必須作的第一件事是將代碼和全部靜態數據(例如初始化變量)加載(load)到內存中,也即加載到進程的地址空間中。程序最初以某種可執行格式駐留在磁盤上。所以,將程序和靜態數據加載到內存中的過程,須要操做系統從磁盤讀取這些字節,並將它們放在內存中的某處。指針
將代碼和靜態數據加載到內存後,操做系統在運行此進程以前還須要執行其餘一些操做。必須爲程序的運行時棧(run-time stack或stack)分配一些內存。生命週期
操做系統也可能爲程序的堆(heap)分配一些內存。在C程序中,堆用於顯式請求的動態分配數據。程序經過調用malloc()來請求這樣的空間,並經過調用free()來明確地釋放它。進程
操做系統還將執行一些其餘初始化任務,特別是與輸入/輸出(I/O)相關的任務。例如,在UNIX系統中,默認狀況下每一個進程都有3個打開的文件描述符(file descriptor),用於標準輸入、輸出和錯誤。事件
經過將代碼和靜態數據加載到內存中,經過建立和初始化棧以及執行與I/O設置相關的其餘工做,OS如今爲程序執行搭好了舞臺。而後它有最後一項任務:啓動程序,在入口處運行,即main()。經過跳轉到main()例程,OS將CPU的控制權轉移到新建立的進程中,從而程序開始執行。
簡而言之,進程能夠處於如下3種(穩定)狀態之一。
操做系統是一個程序,和其餘程序同樣,它有一些關鍵的數據結構來跟蹤各類相關的信息。例如,爲了跟蹤每一個進程的狀態,操做系統可能會爲全部就緒的進程保留某種進程列表(process list),以及跟蹤當前正在運行的進程的一些附加信息。操做系統還必須以某種方式跟蹤被阻塞的進程。當I/O事件完成時,操做系統應確保喚醒正確的進程,讓它準備好再次運行。
操做系統追蹤進程的一些重要信息。對於中止的進程,寄存器上下文將保存其寄存器的內容。當一個進程中止時,它的寄存器將被保存到這個內存位置。經過恢復這些寄存器(將它們的值放回實際的物理寄存器中),操做系統能夠恢復運行該進程。
除了運行、就緒和阻塞以外,還有其餘一些進程能夠處於的狀態。有時候系統會有一個初始(initial)狀態,表示進程在建立時處於的狀態。另外,一個進程能夠處於已退出但還沒有清理的最終(final)狀態(在基於UNIX的系統中,這稱爲殭屍狀態)。
注:存儲關於進程的信息的個體結構稱爲進程控制塊(Process Control Block,PCB)。