C語言程式設計師編寫的程式碼可以編譯為程式,程式通常存放在磁碟等儲存介質中。在 Linux 中,處於執行期的程式被稱作“程序”。
雖說程序是處於執行期的程式,但是程序並不僅僅侷限於可執行的C語言程式碼(Linux 稱其為程式碼段,text section),它還包括其他資源,例如用於存放全域性變數的資料段(data section)、具有記憶體對映的記憶體地址空間、要處理的資料、掛起的訊號、開啟的檔案,可能還會包括多個執行執行緒等等。
事實上,程序是 Linux 作業系統抽象概念的最基本的一種,Linux 最基礎最重要的工作之一就是管理系統中繁雜的各種程序。
上面提到的“執行執行緒”通常被簡稱為“執行緒”,它被程序包含,同一個程序可能有多個執行緒,每個執行緒都有自己獨立的程式計數器、程序棧以及相關的程序暫存器。雖說 Linux 核心管理的是程序,但其實最小的排程單位是執行緒。
早期傳統的 Unix 系統中,一個程序只能包含一個執行緒,所以當時程序排程和執行緒排程其實結果是一致的。
如今的作業系統中,程序包含多個執行緒是非常常見的。Linux 與一些其他作業系統不同,它對程序和執行緒並不明確區分,對於 Linux 來說,執行緒不過是一種比較特殊的程序而已。
包括 Linux,現代作業系統一般都會為程序提供兩種虛擬機制:虛擬處理器和虛擬記憶體。讀者應注意“虛擬”一詞,多個程序可能共同使用一個 CPU 和記憶體,但是“虛擬機制”會讓程序活在楚門的世界一樣,自以為自己獨佔 CPU 和全部記憶體。
應注意,執行緒之間可以共享虛擬記憶體,但是它們仍然擁有各自的虛擬 CPU。
到這裡,讀者應該明白了,編譯器生成的C語言程式本身並不是程序。程序實際上是處於執行期的程式,與相關資源的總和。
事實上,無論是程式不同,還是執行時的資料不同,都會產生不同的程序。舉例來說,同樣一個C語言程式,是可以產生兩個不同的程序的——它們的執行資源可能是不同的。反過來也是一樣的,多個不同的程序也可以共享同一份資源,例如開啟同一個檔案,對映同一塊記憶體空間等。
可能有讀者認為,直接執行一個程式不就產生新程序了嗎?這樣說沒有錯,但是不夠本質。在 Linux 作業系統中,透過 fork() 系統呼叫可以複製現有程序,併產生新程序。呼叫 fork() 的程序一般被稱作“父程序”,而 fork() 產生的新程序則被稱作“子程序”。
fork() 呼叫結束時,會從 Linux 核心返回兩次:一次返回到父程序,父程序恢復執行。一次返回到子程序,子程序開始執行,在這之後,父子程序的程序資源彼此隔離,不再共享。
不過一般來說,如果有需求建立新的程序,一般都是為了執行不同的新的程式。這一過程透過 exec() 函式族可以方便實現,它們可以為新程式建立新的地址空間,然後載入程式執行。
Linux 操作介面的 shell 終端其實也是一個程序,透過 shell 輸入的執行新程式命令(如 ./a.out )產生的新程序其實都是對應 shell 終端的子程序。
程式既然有新生,也就會有死亡,程式執行結束後,透過 exit() 系統呼叫退出執行,這個函式會殺死程序,並且將其佔用的資源釋放,通知其父程序“死亡資訊”。父程序則可以透過 wait() 函式族接收子程序的“死亡資訊”,並著手為子程序做後續的“收屍工作”,避免子程序程式設計“殭屍程序(zombie)”。
“殭屍程序”很難殺死,但是留著“殭屍程序”又會白白浪費系統資源。
C語言程式設計師編寫的程式碼可以編譯為程式,程式通常存放在磁碟等儲存介質中。在 Linux 中,處於執行期的程式被稱作“程序”。
程序雖說程序是處於執行期的程式,但是程序並不僅僅侷限於可執行的C語言程式碼(Linux 稱其為程式碼段,text section),它還包括其他資源,例如用於存放全域性變數的資料段(data section)、具有記憶體對映的記憶體地址空間、要處理的資料、掛起的訊號、開啟的檔案,可能還會包括多個執行執行緒等等。
事實上,程序是 Linux 作業系統抽象概念的最基本的一種,Linux 最基礎最重要的工作之一就是管理系統中繁雜的各種程序。
上面提到的“執行執行緒”通常被簡稱為“執行緒”,它被程序包含,同一個程序可能有多個執行緒,每個執行緒都有自己獨立的程式計數器、程序棧以及相關的程序暫存器。雖說 Linux 核心管理的是程序,但其實最小的排程單位是執行緒。
早期傳統的 Unix 系統中,一個程序只能包含一個執行緒,所以當時程序排程和執行緒排程其實結果是一致的。
執行緒如今的作業系統中,程序包含多個執行緒是非常常見的。Linux 與一些其他作業系統不同,它對程序和執行緒並不明確區分,對於 Linux 來說,執行緒不過是一種比較特殊的程序而已。
包括 Linux,現代作業系統一般都會為程序提供兩種虛擬機制:虛擬處理器和虛擬記憶體。讀者應注意“虛擬”一詞,多個程序可能共同使用一個 CPU 和記憶體,但是“虛擬機制”會讓程序活在楚門的世界一樣,自以為自己獨佔 CPU 和全部記憶體。
應注意,執行緒之間可以共享虛擬記憶體,但是它們仍然擁有各自的虛擬 CPU。
到這裡,讀者應該明白了,編譯器生成的C語言程式本身並不是程序。程序實際上是處於執行期的程式,與相關資源的總和。
事實上,無論是程式不同,還是執行時的資料不同,都會產生不同的程序。舉例來說,同樣一個C語言程式,是可以產生兩個不同的程序的——它們的執行資源可能是不同的。反過來也是一樣的,多個不同的程序也可以共享同一份資源,例如開啟同一個檔案,對映同一塊記憶體空間等。
程序的產生與消亡可能有讀者認為,直接執行一個程式不就產生新程序了嗎?這樣說沒有錯,但是不夠本質。在 Linux 作業系統中,透過 fork() 系統呼叫可以複製現有程序,併產生新程序。呼叫 fork() 的程序一般被稱作“父程序”,而 fork() 產生的新程序則被稱作“子程序”。
fork() 呼叫結束時,會從 Linux 核心返回兩次:一次返回到父程序,父程序恢復執行。一次返回到子程序,子程序開始執行,在這之後,父子程序的程序資源彼此隔離,不再共享。
不過一般來說,如果有需求建立新的程序,一般都是為了執行不同的新的程式。這一過程透過 exec() 函式族可以方便實現,它們可以為新程式建立新的地址空間,然後載入程式執行。
Linux 操作介面的 shell 終端其實也是一個程序,透過 shell 輸入的執行新程式命令(如 ./a.out )產生的新程序其實都是對應 shell 終端的子程序。
程式既然有新生,也就會有死亡,程式執行結束後,透過 exit() 系統呼叫退出執行,這個函式會殺死程序,並且將其佔用的資源釋放,通知其父程序“死亡資訊”。父程序則可以透過 wait() 函式族接收子程序的“死亡資訊”,並著手為子程序做後續的“收屍工作”,避免子程序程式設計“殭屍程序(zombie)”。
“殭屍程序”很難殺死,但是留著“殭屍程序”又會白白浪費系統資源。