同一進程中的線程究竟共享哪些資源



進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位. 


線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和
),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源. 


一個線程可以創建和撤銷另一個線程;     同一個進程中的多個線程之間可以並發執行.


進程在執行過程中擁有獨立的內存單元,而該進程的多個線程共享內存,從而極大地提高了程序的運行效率。 
每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。 


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

在很多現代操作系統中,一個進程的(虛)地址空間大小為4G,分為系統(內核?)空間和用戶空間兩部分,系統空間為所有進程共享,而用戶空間是獨立的,一般WINDOWS進程的用戶空間為2G。 


一個進程中的所有線程共享該進程的地址空間,但它們有
各自獨立的(/私有的)棧(stack),Windows線程的缺省堆棧大小為1M。堆(heap)的分配與棧有所不同,一般是一個進程有一個C運行時堆,這個堆為本進程中所有線程共享,windows進程還有所謂進程默認堆,用戶也可以創建自己的堆。 
用操作系統術語,線程切換的時候實際上切換的是一個可以稱之為線程控制塊的結構(TCB?),里面保存所有將來用於恢復線程環境必須的信息,包括所有必須保存的寄存器集,線程的狀態等。

 

堆: 是大家共有的空間,分全局堆和局部堆。全局堆就是所有沒有分配的空間,局部堆就是用戶分配的空間。堆在操作系統對進程初始化的時候分配,運行過程中也可以向系統要額外的堆,但是記得用完了要還給操作系統,要不然就是內存泄漏。


棧:是個線程獨有的,保存其運行狀態和局部自動變量的。棧在線程開始的時候初始化,每個線程的棧互相獨立,因此,棧是 thread safe的。操作系統在切換線程的時候會自動的切換棧,就是切換 SS/ESP寄存器。棧空間不需要在高級語言里面顯式的分配和釋放。


進程簡說:

進程就是程序的一次執行。

進程是為了在CPU上實現多道編程而發明的一個概念。

事實上我們說線程是進程里面的一個執行上下文,或者執行序列,顯然一個進程可以同時擁有多個執行序列,更加詳細的描述是,舞台上有多個演員同時出場,而這些演員和舞台就構成了一出戲,類比進程和線程,每個演員是一個線程,舞台是地址空間,這個同一個地址空間里面的所有線程就構成了進程。

比如當我們打開一個word程序,其實已經同時開啟了多個線程,這些線程一個負責顯示,一個接受輸入,一個定時進行存盤,這些線程一起運轉讓我們感到我們的輸入和屏幕顯示同時發生,而不用鍵入一些字符等好長時間才能顯示到屏幕上。

線程管理:

將線程共有的信息存放在進程控制塊中,將線程獨有的信息存放在線程控制塊中。

那么如何區分哪些信息是共享的?哪些信息是獨享的呢?

一般的評價標准是:如果某些資源不獨享會導致線程運行錯誤,則該資源就由每個線程獨享,而其他資源都由進程里面的所有線程共享。

線程共享資源

線程獨享資源

地址空間

程序計數器

全局變量

寄存器

打開的文件

子進程

狀態字

鬧鈴

 

信號及信號服務程序

 

記賬信息

 

一般情況下進程共享資源與獨享資源的划分

那么對於進程及線程的實現做如何解釋呢?

首先應該明白進程的調度,創建等實質上都是由操作系統實現的,所以說進程的實現只能由操作系統內核來實現,而不存在用戶態實現的情況。但是對於線程就不同了,線程的管理者可以是用戶也可以是操作系統本身,線程是進程內部的東西,當然存在由進程直接管理線程的可能性。因此線程的實現就應該分為內核態線程實現和用戶態線程實現。

================================================================================================================


內核態線程實現:

       線程是進程的不同執行序列,也就是說線程是獨立運行的基本單位,也是CPU調度的基本單位。

那么操作系統是如何實現管理線程的呢?

       首先操作系統向管理進程一樣,應該保持維護線程的所有資源,將線程控制塊存放在操作系統的內核空間中。那么此時操作系統就同時掌管進程控制塊和線程控制塊。


操作系統管理線程的好處是:

1.用戶編程簡單;

2.如果一個線程執行阻塞操作,操作系統可以從容的調度另外一個線程的執行。


內核線程的實現缺點是:

1.效率低,因為線程在內核態實現,每次線程切換都需要陷入到內核,由操作系統來調度,而有用戶態切換到內核態是要話費很多時間的,另外內核態實現會占用內核稀有的資源,因為操作系統要維護線程列表,操作系統所占內核空間一旦裝載后就無法動態改變,並且線程的數量遠遠大於進程的數量,隨着線程數的增加內核將耗盡;

2.內核態的實現需要修改操作系統,這個是誰都不想要做的事情;


====================================================================================================================

那么用戶態是如何實現管理線程的呢?

用戶態管理線程就是用戶自己做線程的切換,自己管理線程的信息,操作系統無需知道線程的存在。

在用戶態下進行線程的管理需要用戶創建一個調度線程。一個線程在執行完一段時間后主動把資源釋放給其他線程使用,而在內核台下則無需如此,因為操作系統可通過周期性的時鍾中斷把控制權奪過來,在用戶態實現情況下,執行系統的調度器也是線程,沒有能力奪取控制權。


用戶態實現有什么優點?

 首先是靈活,因為操作系統不用知道線程的存在,所以任何操作系統上都能應用;

其次,線程切換快,因為切換在用戶態進行,無需陷入帶內核態;

再次,不用修改操作系統實現容易。


用戶態實現的缺點呢?

       首先編程起來很詭異,由於在用戶台下各個進程間需要相互合作才能正常運轉。那么在編程時必須考慮什么情況下讓出CPU,讓其他的線程運行,而讓出時機的選擇對線程的效率和可靠性有很大影響,這個並不容易做到;

       其次,用戶態線程實現無法完全達到線程提出所要達到的目的:進程級多道編程;,如果在執行過程中一個線程受阻,它將無法將控制權交出來,這樣整個進程都無法推進。操作系統隨即把CPU控制權交給另外一個進程。這樣,一個線程受阻造成整個進程受阻,我們期望的通過線程對進程實施分身的計划就失敗了。這是用戶態線程致命的缺點。

       調度器激活:線程阻塞后,CPU控制權交給了操作系統,要激活受阻進程的線程,唯一的辦法就是讓操作系統在進程切換時先不切換,而是通知受阻的進程執行系統(即調用執行系統),並問其是否還有別的線程可以執行。如果有,將CPU控制權交給該受阻進程的執行系統線程,從而調度另一個可以執行的線程到CPU上。一個進程掛起后,操作系統並不立即切換到別的進程上,而是給該進程二次機會,讓其繼續執行。如果該進程只有一個線程,或者其所有線程都已經阻塞,則控制權將再次返回給操作系統。而現在,操作系統就會切換到其他線程了。

=============================================================================================================================


現在操作系統的線程實現模型:

鑒於用戶態與內核態都存在缺陷,現代操作將兩者結合起來。用戶態的執行負責進程內部線程在非阻塞時的切換;內核態的操作系統負責阻塞線程的切換,即我們同時實現內核態和用戶態線程管理。每個內核態線程可以服務一個或者更多個用戶態線程。


線程從用戶態切換到內核態:

什么情況下會造成線程從用戶態到內核態的切換呢?

首先,如果在程序運行過程中發生中斷或者異常,系統將自動切換到內核態來運行中斷或異常處理機制。

此外,程序進行系統調用也會從用戶態切換到內核態。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM