詳解作業系統中程式與執行緒

風箏丶發表於2017-11-22

你好!這裡是風箏的部落格,

歡迎和我一起交流。


程式的定義:
程式是具有獨立功能的程式在某個資料集合上的一次執行活動,也是作業系統進行資源分配和保護的基本單位。
簡單的說,程式是一個程式的一次執行的過程。

程式的屬性:
1)動態性:程式具有生命週期,由建立而產生,由排程而執行,由事件而等待,由撤銷而消亡。
2)共享性:同一程式同時執行在不同的資料集合上構成不同程式,即多個不同的程式可執行相同的程式。
3)獨立性:程式有自己的虛擬空間、程式計數器和內部狀態。
4)制約性:程式因共享資源或協同工作產生相互制約關係,造成程式程式執行速度的不可預測性。
5)併發性:多程式的執行在時間上可重疊,在單處理器系統中可併發執行,在多處理器環境中可併發執行。

程式的目的:
1)刻畫程式的併發性
2)解決資源的共享性
可以說,程式是為了佔有系統資源和實現系統併發性引入的。

程式的狀態(Linux中):
1)執行態(TASK_RUNNING):程式當前正在執行,或者正在執行佇列中等待排程(排隊中)
2)等待態_可中斷(TASK_INTERRUPTIBLE):程式處於阻塞(睡眠sleep,主動放棄CPU)狀態,正在等待某些事件發生或能夠佔用某些資源。處於這種狀態下的程式可以被訊號中斷。接收到訊號或被顯式地喚醒呼叫喚醒之後,程式將轉變為執行態,繼續排隊等待排程
3)等待態_不可中斷(TASK_UNINTERRUPTIBLE):此程式狀態類似於可中斷的阻塞狀態,只是他不會處理訊號,把訊號傳遞到這種狀態下的程式不能改變它的狀態,即不可被訊號所中斷,不能被隨便排程
4)停止態(TASK_STOPPED),即暫停狀態,程式的執行被暫停,當程式受到SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU等訊號,就會進入暫停狀態,知道收到繼續執行訊號,轉變為執行態,繼續排隊等待排程
5)殭屍態(EXIT_ZOMBIE):子程式執行結束,父程式尚未使用wait 函式族(如使用wait()函式)等系統呼叫來回收退出狀態
注:
殭屍狀態下的子程式已經放棄了幾乎所有的記憶體空間,沒有任何可執行程式碼,也不能被排程,僅僅在程式列表中(即task_struct)保留一個位置,記載該程式的退出資訊供其父程式收集。即程式結束後,記憶體地址空間被釋放、task_struct 成員被釋放,但task_struct 這個空殼還存在,它就是殭屍,這個殭屍我們用kill 是殺不掉的。所以,一般在子程式結束後,我們會對其進行回收。回收的方法有三種:
1)誰建立誰回收,即用父程式來回收;
2)父程式不回收,通知核心來回收;
3)由init 程式來回收,當父程式先死掉,子程式成為孤兒程式,由 init 程式來認養;
當這三種條件都不滿足時,比如父程式不去回收子程式,自己卻未死掉,殭屍便會出現,這是非常棘手的,可以通過殺死父程式來殺死殭屍(不推薦使用);

程式映像:
1)程式控制塊:儲存程式的標誌資訊,現場資訊和控制資訊。建立是建立,撤銷時回收
2)程式程式塊:被程式執行的程式,程式一次執行所完成的功能
3)程式核心棧:存放中斷/異常現場,儲存函式呼叫的引數、區域性變數和返回地址
4)程式資料塊:程式的私有空間,存放各種私有資料,使用者棧也在此開闢
可見,每個程式由上述四個要素組成。

程式的優點:
1)順序程式的特點:具有封閉性和可再現性;
2)程式的併發執行和資源共享。多道程式設計出現後,實現了程式的併發執行和資源共享,提高了系統的效率和系統的資源利用率。
程式的缺點:
1)程式間記憶體無法共享(資源是私有的,如虛擬地址空間,檔案描述符和訊號處理等),通訊比較麻煩,導致多工之間的協作麻煩
2)任務切換,即程式間上下文切換,系統開銷比較大。(虛擬地址空間以及task_struct 都需要切換)
3)在建立或撤消程式時,系統都要為之分配和回收資源

所以,為了提高系統的效能,減少程式併發執行是所付出的時空開銷,使得併發顆粒度更細、併發性更好,引入執行緒的概念。

執行緒的概念:
把程式的“獨立分配資源”和“被排程分派執行”分離開來,前一項任務仍然由執行緒完成,作為系統資源分配和保護的獨立單位,無需頻繁的切換。後一項任務交給執行緒的實體完成,作為系統排程分派的基本單位,會被頻繁的排程切換。

執行緒的定義:
執行緒是程式能夠併發執行的實體,是程式的組成部分,也是多處理器排程和分派的基本單位。

執行緒的屬性:
有狀態及狀態轉換,所以需要提供一些狀態轉換操作
不執行時需要儲存上下文環境,所以需要程式計數器等暫存器
有自己的棧和棧指標
共享所在程式的地址空間和其它資源

可以認為,執行緒基本上不擁有系統資源,只擁有一點在執行中必不可少的資源(如程式計數器,一組暫存器和棧),它與同屬一個程式的其他的執行緒共享程式所擁有的全部資源,是CPU排程和分派的基本單位,它是比程式更小的能獨立執行的基本單位

執行緒的狀態(Linux中):
執行態、就緒態、等待態、終止態
注:
執行緒不是自願擁有單位,掛起態對於執行緒來說是沒有意義的(程式掛起後被換出記憶體,執行緒因共享空間也必須對換出去,可見掛起操作所引起的狀態是對程式級狀態而不是執行緒級狀態)

執行緒的優點:
1)快速執行緒切換:多執行緒切換隻需改變堆疊和暫存器,地址空間不變
2)通訊易於實現:共享程式的記憶體和檔案,可自由訪問全域性變數而不必經過核心
3)減少管理開銷:建立和撤銷無需再分配儲存空間各種資源
4)併發程度提高:適宜並行工作,使得多核和多處理器系統效能發揮更好
執行緒的缺點:
1)因為共享地址空間,如果其中一個執行緒出現錯誤(比如段錯誤),整個執行緒組都會崩掉!
2)排程時, 要儲存執行緒狀態,頻繁排程, 需要佔用大量的機時

.

程式與執行緒的區別:
程式和執行緒的主要差別在於它們是不同的作業系統資源管理方式。
程式有獨立的地址空間,一個程式崩潰後,在保護模式下不會對其它程式產生影響,而執行緒只是一個程式中的不同執行路徑。執行緒有自己的堆疊和區域性變數,但執行緒之間沒有單獨的地址空間,所以多程式的程式要比多執行緒的程式健壯,但在程式切換時,耗費資源較大,效率要差一些。
從邏輯角度來看,多執行緒的意義在於一個應用程式中,有多個執行部分可以同時執行。但作業系統並沒有將多個執行緒看做多個獨立的應用,來實現程式的排程和管理以及資源分配。這就是程式和執行緒的重要區別。

最後,作業系統的設計,可以歸結為三點:
1)以多程式形式,允許多個任務同時執行;
2)以多執行緒形式,允許單個任務分成不同的部分執行;
3)提供協調機制,一方面防止程式之間和執行緒之間產生衝突,另一方面允許程式之間和執行緒之間共享資源。

相關文章