1. 程式人生 > >[作業系統] 程序與執行緒

[作業系統] 程序與執行緒

一、程序

      程序的引入多個程式在執行時,需要共享系統資源,從而導致各程式在執行過程中出現相互制約的關係,程式的執行表現出間斷性的特徵。
      這些特徵都是在程式的執行過程中發生的,是動態的過程,而傳統的程式本身是一組指令的集合,是一個靜態的概念,無法描述程式在記憶體中的執行情況,即我們無法從程式的字面上看出它何時執行,何時停頓,也無法看出它與其它執行程式的關係,因此,程式這個靜態概念已不能如實反映程式併發執行過程的特徵。為了深刻描述程式動態執行過程的性質,人們引入“程序(Process)”概念。

      程序是一個具有獨立功能的程式關於某個資料集合的一次執行活動。它可以申請和擁有系統資源,是一個動態的概念,是一個活動的實體。它不只是程式的程式碼,還包括當前的活動,通過程式計數器的值和處理暫存器的內容來表示。
      程序是作業系統中最基本、重要的概念。是多工程式系統出現後,為了刻畫系統內部出現的動態情況,描述系統內部各道程式的活動規律引進的一個概念,所有多道程式設計作業系統都建立在程序的基礎上。

程序的組成

  • 程序ID,程序組ID,使用者ID,組ID
  • 環境
  • 工作目錄
  • 程式指令
  • 暫存器
  • 堆疊(Stack)
  • 堆(Heap)
  • 檔案描述符
  • 訊號操作
  • 共享庫
  • 程序間通訊工具 : 訊息佇列、管道、訊號量、共享記憶體

動態性:程序的實質是程式的一次執行過程,程序是動態產生,動態消亡的。
併發性:任何程序都可以同其他程序一起併發執行
獨立性:程序是一個能獨立執行的基本單位,同時也是系統分配資源和排程的獨立單位;
非同步性:由於程序間的相互制約,使程序具有執行的間斷性,即程序按各自獨立的、不可預知的速度向前推進
結構特徵:程序由程式、資料和程序控制塊三部分組成。

程序與程式

  • 程式是指令的有序集合,其本身沒有任何執行的含義,是一個靜態的概念。而程序是程式在處理機上的一次執行過程,它是一個動態的概念。
  • 程式可以作為一種軟體資料長期存在,而程序是有一定生命期的。程式是永久的,程序是暫時的。
  • 程序更能真實地描述併發,而程式不能;程序是由程式和資料兩部分組成的。
  • 程序具有建立其他程序的功能,而程式沒有。
  • 在傳統的作業系統中,程式並不能獨立執行,作為資源分配和獨立執行的基本單元都是程序。

程序的基本狀態及狀態之間的關係

狀態:執行、阻塞、掛起阻塞、就緒、掛起就緒
狀態之間的轉換:

  • 準備就緒的程序,被CPU排程執行,變成執行態;
  • 執行中的程序,進行I/O請求或者不能得到所請求的資源,變成阻塞態;
  • 執行中的程序,程序執行完畢(或時間片已到),變成就緒態;
  • 將阻塞態的程序掛起,變成掛起阻塞態,當導致程序阻塞的I/O操作在使用者重啟程序前完成(稱之為喚醒),掛起阻塞態變成掛起就緒態,當用戶在I/O操作結束之前重啟程序,掛起阻塞態變成阻塞態;
  • 將就緒(或執行)中的程序掛起,變成掛起就緒態,當該程序恢復之後,掛起就緒態變成就緒態;

程序間的通訊方式

  1. 管道(pipe)及有名管道(named pipe):管道可用於具有親緣關係的父子程序間的通訊,有名管道除了具有管道所具有的功能外,它還允許無親緣關係程序間的通訊。
  2. 訊號(signal):訊號是在軟體層次上對中斷機制的一種模擬,它是比較複雜的通訊方式,用於通知程序有某事件發生,一個程序收到一個訊號與處理器收到一箇中斷請求效果上可以說是一致的。
  3. 訊息佇列(message queue):訊息佇列是訊息的連結表,它克服了上兩種通訊方式中訊號量有限的缺點,具有寫許可權得程序可以按照一定得規則向訊息佇列中新增新資訊;對訊息佇列有讀許可權得程序則可以從訊息佇列中讀取資訊。
  4. 共享記憶體(shared memory):可以說這是最有用的程序間通訊方式。它使得多個程序可以訪問同一塊記憶體空間,不同程序可以及時看到對方程序中對共享記憶體中資料得更新。這種方式需要依靠某種同步操作,如互斥鎖和訊號量等。
  5. 訊號量(semaphore):主要作為程序之間及同一種程序的不同執行緒之間得同步和互斥手段。
  6. 套接字(socket):這是一種更為一般得程序間通訊機制,它可用於網路中不同機器之間的程序間通訊,應用非常廣泛。

二、執行緒

      執行緒(thread)是程序上下文(context)中執行的程式碼序列,是程序中的一個實體,是被系統獨立排程和分派的基本單位 ,又被稱為輕量級程序(light weight process)。在支援多執行緒的系統中,程序成為資源分配和保護的實體,而執行緒是被排程執行的基本單元。
      執行緒只擁有一點在執行中必不可少的資源,但它可與同屬一個程序的其它執行緒共享程序所擁有的全部資源。
      一個執行緒可以建立和撤消另一個執行緒,同一程序中的多個執行緒之間可以併發執行。由於執行緒之間的相互制約,致使執行緒在執行中呈現出間斷性。
      執行緒是程式中一個單一的順序控制流程。在單個程式中同時執行多個執行緒完成不同的工作,稱為多執行緒。

程序內的執行緒

  • 一個執行緒對共享的系統資源進行修改,在這個程序內的其它執行緒也可以見到這種修改。
  • 對於同一個資料,可能有兩個值相同的指標指向這個資料。
  • 程序內的多個執行緒可以對同一個記憶體單元進行讀和寫操作,所以必須要採取顯式同步機制。
  • 在同一個程序的地址空間下,執行緒間的通訊消耗更小。

  • 程式在作業系統中作為程序方式存在、獲取資源、執行。
  • 在一個程序內,執行緒可以建立其它執行緒。每個執行緒有各自的棧(stack)。
  • 一個程序內所有的執行緒共享程式碼段和資料段。

執行緒的生命週期

  • 執行緒的標識:通常用一個整數來標識一個執行緒
  • 執行緒的建立:自動建立從main函式開始的主執行緒,呼叫函式庫介面建立一個新的執行緒(pthread_create)
  • 執行緒的終止:執行完畢,或者呼叫了pthread_exit,主執行緒退出導致整個程序會終止

執行緒的狀態

  • 就緒(ready):執行緒等待可用的處理器。
  • 執行(running):執行緒正在被執行。
  • 阻塞(blocked):執行緒正在等待某個事件的發生(比如I/O的完成,試圖加鎖一個被上鎖的互斥量)。
  • 終止(terminated):執行緒從起始函式中返回或者呼叫pthread_exit。
    這裡寫圖片描述

多執行緒的優點

  • 建立一個執行緒比建立一個程序的代價要小
  • 執行緒的切換比程序間的切換代價小
  • 充分利用多處理器
  • 資料共享
  • 資料共享使得執行緒之間的通訊比程序間的通訊更高效
  • 快速響應特性
  • 在系統繁忙的情況下,程序通過獨立的執行緒及時響應使用者的輸入

執行緒的同步與互斥

      當有多個執行緒的時候,經常需要去同步這些執行緒以訪問同一個資料或資源。例如,假設有一個程式,其中一個執行緒用於把檔案讀到記憶體,而另一個執行緒用於統計檔案中的字元數。當然,在把整個檔案調入記憶體之前,統計它的計數是沒有意義的。但是,由於每個操作都有自己的執行緒,作業系統會把兩個執行緒當作是互不相干的任務分別執行,這樣就可能在沒有把整個檔案裝入記憶體時統計字數。為解決此問題,你必須使兩個執行緒同步工作。
      所謂同步,是指散步在不同程序之間的若干程式片斷,它們的執行必須嚴格按照規定的某種先後次序來執行,這種先後次序依賴於要完成的特定的任務。如果用對資源的訪問來定義的話,同步是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源。
      所謂互斥,是指散佈在不同程序之間的若干程式片斷,當某個程序執行其中一個程式片段時,其它程序就不能執行它們之中的任一程式片段,只能等到該程序執行完這個程式片段後才可以執行。如果用對資源的訪問來定義的話,互斥某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。

由於執行緒共享同一程序的記憶體空間,多個執行緒可能需要同時訪問同一個資料。如果沒有正確的保護措施,對共享資料的訪問會造成資料的不一致和錯誤。
常用的同步機制:

  • 臨界區(critical section)
  • 訊號量(simphore)
  • 互斥量(mutex)
  • 管程(monitor)

訊號量(simphore)
訊號量被定義為一個整數變數,用兩個原子的操作wait和signal來操作訊號量
wait:當執行wait時,如果訊號量的值大於0,wait操作把訊號量的值減1並返回;如果當前訊號量的值為非正數則wait會等待。
signal : signal操作對訊號量的值加1,並喚醒哪些等待的程序

互斥量(mutex)
在同一時刻只能有一個執行緒能夠對互斥量加鎖 ,執行緒用互斥量對共享變數counter的互斥訪問:

pthread_mutex_t  count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(  &count_mutex ) ;
    counter++ ;
pthread_mutex_unlock( &count_mutex );

三、程序與執行緒的區別與聯絡

  • 子程序和父程序有不同的程式碼和資料空間,而多個執行緒則共享資料空間,每個執行緒有自己的執行堆疊和程式計數器為其執行上下文.
  • 多執行緒主要是為了節約CPU時間,發揮利用,根據具體情況而定. 執行緒的執行中需要使用計算機的記憶體資源和CPU

程序和執行緒的關係:
(1)一個執行緒只能屬於一個程序,而一個程序可以有多個執行緒,但至少有一個執行緒。
(2)資源分配給程序,同一程序的所有執行緒共享該程序的所有資源。
(3)處理機分給執行緒,即真正在處理機上執行的是執行緒。
(4)執行緒在執行過程中,需要協作同步。不同程序的執行緒間要利用訊息通訊的辦法實現同步。執行緒是指程序內的一個執行單元,也是程序內的可排程實體.

程序與執行緒的區別:
(1)排程:執行緒作為排程和分配的基本單位,程序作為擁有資源的基本單位
(2)併發性:不僅程序之間可以併發執行,同一個程序的多個執行緒之間也可併發執行
(3)擁有資源:程序是擁有資源的一個獨立單位,執行緒不擁有系統資源,但可以訪問隸屬於程序的資源.
(4)系統開銷:在建立或撤消程序時,由於系統都要為之分配和回收資源,導致系統的開銷明顯大於建立或撤消執行緒時的開銷。