程序和執行緒的概念 區別和聯絡

2022-07-15 06:42:09 字數 3841 閱讀 4406

程序(process)和執行緒(thread)是作業系統的基本概念,但是它們比較抽象,不容易掌握。

最近,我讀到一篇材料,發現有乙個很好的模擬,可以把它們解釋地清晰易懂。

程序與執行緒的乙個簡單解釋

在這個簡單易懂的模擬下,了解一下程序和執行緒的巨集觀概念:

程序,是併發執行的程式在執行過程中分配和管理資源的基本單位,是乙個動態概念,竟爭計算機系統資源的基本單位。每乙個程序都有乙個自己的位址空間,即程序空間或(虛空間)。程序空間的大小 只與處理機的位數有關,乙個 16 位長處理機的程序空間大小為 216 ,而 32 位處理機的程序空間大小為 232 。程序至少有 5 種基本狀態,它們是:初始態,執行態,等待狀態,就緒狀態,終止狀態。

執行緒,在網路或多使用者環境下,乙個伺服器通常需要接收大量且不確定數量使用者的併發請求,為每乙個請求都建立乙個程序顯然是行不通的,——無論是從系統資源開銷方面或是響應使用者請求的效率方面來看。因此,作業系統中線程的概念便被引進了。執行緒,是程序的一部分,乙個沒有執行緒的程序可以被看作是單執行緒的。執行緒有時又被稱為輕權程序或輕量級程序,也是 cpu 排程的乙個基本單位。

說到這裡,我們對程序與執行緒都有了乙個大體上的印象,現在開始說說二者大致的區別。

程序的執行過程是線狀的,儘管中間會發生中斷或暫停,但該程序所擁有的資源只為該線狀執行過程服務。一旦發生程序上下文切換,這些資源都是要被保護起來的。這是程序巨集觀上的執行過程。而程序又可有單執行緒程序與多執行緒程序兩種。我們知道,程序有 乙個程序控制塊 pcb ,相關程式段 和 該程式段對其進行操作的資料結構集 這三部分,單執行緒程序的執行過程在巨集觀上是線性的,微觀上也只有單一的執行過程;而多執行緒程序在巨集觀上的執行過程同樣為線性的,但微觀上卻可以有多個執行操作(執行緒),如不同**片段以及相關的資料結構集。執行緒的改變只代表了 cpu 執行過程的改變,而沒有發生程序所擁有的資源變化。除了 cpu 之外,計算機內的軟硬體資源的分配與執行緒無關,執行緒只能共享它所屬程序的資源。與程序控制表和 pcb 相似,每個執行緒也有自己的執行緒控制表 tcb ,而這個 tcb 中所儲存的執行緒狀態資訊則要比 pcb 表少得多,這些資訊主要是相關指標用堆疊(系統棧和使用者棧),暫存器中的狀態資料。程序擁有乙個完整的虛擬位址空間,不依賴於執行緒而獨立存在;反之,執行緒是程序的一部分,沒有自己的位址空間,與程序內的其他執行緒一起共享分配給該程序的所有資源

執行緒可以有效地提高系統的執行效率,但並不是在所有計算機系統中都是適用的,如某些很少做程序排程和切換的實時系統。使用執行緒的好處是有多個任務需要處理機處理時,減少處理機的切換時間;而且,執行緒的建立和結束所需要的系統開銷也比程序的建立和結束要小得多。最適用使用執行緒的系統是多處理機系統和網路系統或分布式系統。

執行緒在執行過程中與程序還是有區別的。每個獨立的執行緒有乙個程式執行的入口、順序執行序列和程式的出口。但是執行緒不能夠獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制。 

從邏輯角度來看,多執行緒的意義在於乙個應用程式中,有多個執行部分可以同時執行。但作業系統並沒有將多個執行緒看做多個獨立的應用,來實現程序的排程和管理以及資源分配。這就是程序和執行緒的重要區別。

1. 執行緒的執行特性。

執行緒只有 3 個基本狀態:就緒,執行,阻塞。

執行緒存在 5 種基本操作來切換執行緒的狀態:派生,阻塞,啟用,排程,結束。

2. 程序通訊。

單機系統中程序通訊有 4 種形式:主從式,會話式,訊息或郵箱機制,共享儲存區方式。

主從式典型例子:終端控制程序和終端程序。

會話式典型例子:使用者程序與磁碟管理程序之間的通訊。

關於多程序和多執行緒:

一.為何需要多程序(或者多執行緒),為何需要併發?

這個問題或許本身都不是個問題。但是對於沒有接觸過多程序程式設計的朋友來說,他們確實無法感受到併發的魅力以及必要性。

我想,只要你不是整天都寫那種int main()到底的**的人,那麼或多或少你會遇到**響應不夠用的情況,也應該有嚐過併發程式設計的甜頭。就像乙個快餐點的服務員,既要在前台接待客戶點餐,又要接**送外賣,沒有分身術肯定會忙得你焦頭爛額的。幸運的是確實有這麼一種技術,讓你可以像孫悟空一樣分身,靈魂出竅,樂哉樂哉地輕鬆應付一切狀況,這就是多程序/執行緒技術。

併發技術,就是可以讓你在同一時間同時執行多條任務的技術。你的**將不僅僅是從上到下,從左到右這樣規規矩矩的一條線執行。你可以一條線在main函式裡跟你的客戶交流,另一條線,你早就把你外賣送到了其他客戶的手裡。

所以,為何需要併發?因為我們需要更強大的功能,提供更多的服務,所以併發,必不可少。

二.多程序

什麼是程序。最直觀的就是乙個個pid,官方的說法就:程序是程式在計算機上的一次執行活動。

說得簡單點,下面這段**執行的時候

int

main()

進入main函式,這就是乙個程序,程序pid會列印出來,然後執行到return,該函式就退出,然後由於該函式是該程序的唯一的一次執行,所以return後,該程序也會退出。

看看多程序。linux下建立子程序的呼叫是fork();

#include #include 

#include

void

print_exit()

main ()

}

i am the child process, my process id is 15806

the exit pid:15806

i am the parent process, my process id is 15805

the exit pid:15805

這是gcc測試下的執行結果。

關於fork函式,功能就是產生子程序,由於前面說過,程序就是執行的流程活動。

那麼fork產生子程序的表現就是它會返回2次,一次返回0,順序執行下面的**。這是子程序。

一次返回子程序的pid,也順序執行下面的**,這是父程序。

(為何父程序需要獲取子程序的pid呢?這個有很多原因,其中乙個原因:看最後的wait,就知道父程序等待子程序的終結後,處理其task_struct結構,否則會產生殭屍程序,扯遠了,有興趣可以自己google)。

如果fork失敗,會返回-1.

額外說下atexit( print_exit ); 需要的引數肯定是函式的呼叫位址。

這裡的print_exit 是函式名還是函式指標呢?答案是函式指標,函式名永遠都只是一串無用的字串。

某本書上的規則:函式名在用於非函式呼叫的時候,都等效於函式指標。

說到子程序只是乙個額外的流程,那他跟父程序的聯絡和區別是什麼呢?

我很想建議你看看linux核心的註解(有興趣可以看看,那裡才有本質上的了解),總之,fork後,子程序會複製父程序的task_struct結構,並為子程序的堆疊分配物理頁。理論上來說,子程序應該完整地複製父程序的堆,棧以及資料空間,但是2者共享正文段。

關於寫時複製:由於一般 fork後面都接著exec,所以,現在的 fork都在用寫時複製的技術,顧名思意,就是,資料段,堆,棧,一開始並不複製,由父,子程序共享,並將這些記憶體設定為唯讀。直到父,子程序一方嘗試寫這些區域,則核心才為需要修改的那片記憶體拷貝副本。這樣做可以提高 fork的效率。

三.多執行緒

執行緒是可執行**的可分派單元。這個名稱**於「執行的線索」的概念。在基於執行緒的多工的環境中,所有程序有至少乙個執行緒,但是它們可以具有多個任務。這意味著單個程式可以併發執行兩個或者多個任務。

簡而言之,執行緒就是把乙個程序分為很多片,每一片都可以是乙個獨立的流程。這已經明顯不同於多程序了,程序是乙個拷貝的流程,而執行緒只是把一條河流截成很多條小溪。它沒有拷貝這些額外的開銷,但是僅僅是現存的一條河流,就被多執行緒技術幾乎無開銷地轉成很多條小流程,它的偉大就在於它少之又少的系統開銷。(當然偉大的後面又引發了重入性等種種問題,這個後面慢慢比較)。

關於多執行緒與多程序,執行緒安全,函式可重入詳見

程序執行緒的區別和聯絡

1 兩者都是多工程式設計方式,都能夠使用計算機的多核資源 2 程序的建立刪除消耗的計算機資源比執行緒要多 3 程序空間獨立,資料相互不干擾,有專門的ipc 程序間通訊 執行緒使用全域性變數進行通訊 4 乙個程序可以建立多個執行緒分支,兩者之間存在包含關係 5 多個執行緒公用程序的資源,在資源操作時往...

程序和執行緒的區別與聯絡

1.共同點 功能上都是用於實現多工併發程式設計的技術手段,執行緒的狀態包括就緒 執行與阻塞,與程序類似。從系統實現的角度看,程序實體和執行緒實體在linux核心中都是有task struct實現的,兩者的建立最終都是呼叫系統函式clone 2.區別 程序是資源分配的基本單位,執行緒是系統排程的基本單...

程序與執行緒的區別和聯絡

一 程式與程序 程式 一段靜態的 程序 程式的一次動態執行過程 二 程序與執行緒 程序 程序是程序實體 程式段 資料段 pcb 的執行過程,是系統進行資源分配和排程的乙個獨立單位 執行緒 又稱輕量級程序 lightweight process 是程序中某個單一順序的控制流 三 程序與執行緒的區別 2...