【Linux 线程】同一个进程中的线程共享哪些资源
進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位.?
線程是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源.?
一個(gè)線程可以創(chuàng)建和撤銷另一個(gè)線程; ? ? 同一個(gè)進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行.
進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而該進(jìn)程的多個(gè)線程共享內(nèi)存,從而極大地提高了程序的運(yùn)行效率。?
每個(gè)獨(dú)立的線程有一個(gè)程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制。?
從邏輯角度來看,多線程的意義在于一個(gè)應(yīng)用程序中,有多個(gè)執(zhí)行部分可以同時(shí)執(zhí)行。但操作系統(tǒng)并沒有將多個(gè)線程看做多個(gè)獨(dú)立的應(yīng)用,來實(shí)現(xiàn)進(jìn)程的調(diào)度和管理以及資源分配。這就是進(jìn)程和線程的重要區(qū)別。
在很多現(xiàn)代操作系統(tǒng)中,一個(gè)進(jìn)程的(虛)地址空間大小為4G,分為系統(tǒng)(內(nèi)核?)空間和用戶空間兩部分,系統(tǒng)空間為所有進(jìn)程共享,而用戶空間是獨(dú)立的,一般WINDOWS進(jìn)程的用戶空間為2G。?
一個(gè)進(jìn)程中的所有線程共享該進(jìn)程的地址空間,但它們有各自獨(dú)立的(/私有的)棧(stack),Windows線程的缺省堆棧大小為1M。堆(heap)的分配與棧有所不同,一般是一個(gè)進(jìn)程有一個(gè)C運(yùn)行時(shí)堆,這個(gè)堆為本進(jìn)程中所有線程共享,windows進(jìn)程還有所謂進(jìn)程默認(rèn)堆,用戶也可以創(chuàng)建自己的堆。?
用操作系統(tǒng)術(shù)語,線程切換的時(shí)候?qū)嶋H上切換的是一個(gè)可以稱之為線程控制塊的結(jié)構(gòu)(TCB?),里面保存所有將來用于恢復(fù)線程環(huán)境必須的信息,包括所有必須保存的寄存器集,線程的狀態(tài)等。
?
堆:是大家共有的空間,分全局堆和局部堆。全局堆就是所有沒有分配的空間,局部堆就是用戶分配的空間。堆在操作系統(tǒng)對(duì)進(jìn)程初始化的時(shí)候分配,運(yùn)行過程中也可以向系統(tǒng)要額外的堆,但是記得用完了要還給操作系統(tǒng),要不然就是內(nèi)存泄漏。
棧:是每個(gè)線程獨(dú)有的,保存其運(yùn)行狀態(tài)和局部自動(dòng)變量的。棧在線程開始的時(shí)候初始化,每個(gè)線程的棧互相獨(dú)立,因此,棧是 thread safe的。操作系統(tǒng)在切換線程的時(shí)候會(huì)自動(dòng)的切換棧,就是切換 SS/ESP寄存器。棧空間不需要在高級(jí)語言里面顯式的分配和釋放。
進(jìn)程簡(jiǎn)說:
進(jìn)程就是程序的一次執(zhí)行。
進(jìn)程是為了在CPU上實(shí)現(xiàn)多道編程而發(fā)明的一個(gè)概念。
事實(shí)上我們說線程是進(jìn)程里面的一個(gè)執(zhí)行上下文,或者執(zhí)行序列,顯然一個(gè)進(jìn)程可以同時(shí)擁有多個(gè)執(zhí)行序列,更加詳細(xì)的描述是,舞臺(tái)上有多個(gè)演員同時(shí)出場(chǎng),而這些演員和舞臺(tái)就構(gòu)成了一出戲,類比進(jìn)程和線程,每個(gè)演員是一個(gè)線程,舞臺(tái)是地址空間,這個(gè)同一個(gè)地址空間里面的所有線程就構(gòu)成了進(jìn)程。
比如當(dāng)我們打開一個(gè)word程序,其實(shí)已經(jīng)同時(shí)開啟了多個(gè)線程,這些線程一個(gè)負(fù)責(zé)顯示,一個(gè)接受輸入,一個(gè)定時(shí)進(jìn)行存盤,這些線程一起運(yùn)轉(zhuǎn)讓我們感到我們的輸入和屏幕顯示同時(shí)發(fā)生,而不用鍵入一些字符等好長(zhǎng)時(shí)間才能顯示到屏幕上。
線程管理:
將線程共有的信息存放在進(jìn)程控制塊中(PCB),將線程獨(dú)有的信息存放在線程控制塊中(TCB)。
那么如何區(qū)分哪些信息是共享的?哪些信息是獨(dú)享的呢?
一般的評(píng)價(jià)標(biāo)準(zhǔn)是:如果某些資源不獨(dú)享會(huì)導(dǎo)致線程運(yùn)行錯(cuò)誤,則該資源就由每個(gè)線程獨(dú)享,而其他資源都由進(jìn)程里面的所有線程共享。
那么對(duì)于進(jìn)程及線程的實(shí)現(xiàn)做如何解釋呢?
首先應(yīng)該明白進(jìn)程的調(diào)度,創(chuàng)建等實(shí)質(zhì)上都是由操作系統(tǒng)實(shí)現(xiàn)的,所以說進(jìn)程的實(shí)現(xiàn)只能由操作系統(tǒng)內(nèi)核來實(shí)現(xiàn),而不存在用戶態(tài)實(shí)現(xiàn)的情況。但是對(duì)于線程就不同了,線程的管理者可以是用戶也可以是操作系統(tǒng)本身,線程是進(jìn)程內(nèi)部的東西,當(dāng)然存在由進(jìn)程直接管理線程的可能性。因此線程的實(shí)現(xiàn)就應(yīng)該分為內(nèi)核態(tài)線程實(shí)現(xiàn)和用戶態(tài)線程實(shí)現(xiàn)。
?
[內(nèi)核態(tài)線程實(shí)現(xiàn)]:
線程是進(jìn)程的不同執(zhí)行序列,也就是說線程是獨(dú)立運(yùn)行的基本單位,也是CPU調(diào)度的基本單位。那么操作系統(tǒng)是如何實(shí)現(xiàn)管理線程的呢?
???????首先操作系統(tǒng)向管理進(jìn)程一樣,應(yīng)該保持維護(hù)線程的所有資源,將線程控制塊存放在操作系統(tǒng)的內(nèi)核空間中。那么此時(shí)操作系統(tǒng)就同時(shí)掌管進(jìn)程控制塊和線程控制塊。
操作系統(tǒng)管理線程的好處是:
1.用戶編程簡(jiǎn)單;
2.如果一個(gè)線程執(zhí)行阻塞操作,操作系統(tǒng)可以從容的調(diào)度另外一個(gè)線程的執(zhí)行。
內(nèi)核線程的實(shí)現(xiàn)缺點(diǎn)是:
1.效率低,因?yàn)?span style="color:#ff0000;">線程在內(nèi)核態(tài)實(shí)現(xiàn),每次線程切換都需要陷入到內(nèi)核,由操作系統(tǒng)來調(diào)度,而有用戶態(tài)切換到內(nèi)核態(tài)是要話費(fèi)很多時(shí)間的,另外內(nèi)核態(tài)實(shí)現(xiàn)會(huì)占用內(nèi)核稀有的資源,因?yàn)椴僮飨到y(tǒng)要維護(hù)線程列表,操作系統(tǒng)所占內(nèi)核空間一旦裝載后就無法動(dòng)態(tài)改變,并且線程的數(shù)量遠(yuǎn)遠(yuǎn)大于進(jìn)程的數(shù)量,隨著線程數(shù)的增加內(nèi)核將耗盡;
2.內(nèi)核態(tài)的實(shí)現(xiàn)需要修改操作系統(tǒng),這個(gè)是誰都不想要做的事情;
?
那么用戶態(tài)是如何實(shí)現(xiàn)管理線程的呢?
用戶態(tài)管理線程就是用戶自己做線程的切換,自己管理線程的信息,操作系統(tǒng)無需知道線程的存在。
在用戶態(tài)下進(jìn)行線程的管理需要用戶創(chuàng)建一個(gè)調(diào)度線程。一個(gè)線程在執(zhí)行完一段時(shí)間后主動(dòng)把資源釋放給其他線程使用,而在內(nèi)核態(tài)下則無需如此,因?yàn)椴僮飨到y(tǒng)可通過周期性的時(shí)鐘中斷把控制權(quán)奪過來,在用戶態(tài)實(shí)現(xiàn)情況下,執(zhí)行系統(tǒng)的調(diào)度器也是線程,沒有能力奪取控制權(quán)。
用戶態(tài)實(shí)現(xiàn)有什么優(yōu)點(diǎn)?
?首先是靈活,因?yàn)椴僮飨到y(tǒng)不用知道線程的存在,所以任何操作系統(tǒng)上都能應(yīng)用;
其次,線程切換快,因?yàn)榍袚Q在用戶態(tài)進(jìn)行,無需陷入帶內(nèi)核態(tài);
再次,不用修改操作系統(tǒng)實(shí)現(xiàn)容易。
用戶態(tài)實(shí)現(xiàn)的缺點(diǎn)呢?
???????首先編程起來很詭異,由于在用戶態(tài)下各個(gè)進(jìn)程間需要相互合作才能正常運(yùn)轉(zhuǎn)。那么在編程時(shí)必須考慮什么情況下讓出CPU,讓其他的線程運(yùn)行,而讓出時(shí)機(jī)的選擇對(duì)線程的效率和可靠性有很大影響,這個(gè)并不容易做到;
???????其次,用戶態(tài)線程實(shí)現(xiàn)無法完全達(dá)到線程提出所要達(dá)到的目的:進(jìn)程級(jí)多道編程;,如果在執(zhí)行過程中一個(gè)線程受阻,它將無法將控制權(quán)交出來,這樣整個(gè)進(jìn)程都無法推進(jìn)。操作系統(tǒng)隨即把CPU控制權(quán)交給另外一個(gè)進(jìn)程。這樣,一個(gè)線程受阻造成整個(gè)進(jìn)程受阻,我們期望的通過線程對(duì)進(jìn)程實(shí)施分身的計(jì)劃就失敗了。這是用戶態(tài)線程致命的缺點(diǎn)。
???????調(diào)度器激活:線程阻塞后,CPU控制權(quán)交給了操作系統(tǒng),要激活受阻進(jìn)程的線程,唯一的辦法就是讓操作系統(tǒng)在進(jìn)程切換時(shí)先不切換,而是通知受阻的進(jìn)程執(zhí)行系統(tǒng)(即調(diào)用執(zhí)行系統(tǒng)),并問其是否還有別的線程可以執(zhí)行。如果有,將CPU控制權(quán)交給該受阻進(jìn)程的執(zhí)行系統(tǒng)線程,從而調(diào)度另一個(gè)可以執(zhí)行的線程到CPU上。一個(gè)進(jìn)程掛起后,操作系統(tǒng)并不立即切換到別的進(jìn)程上,而是給該進(jìn)程二次機(jī)會(huì),讓其繼續(xù)執(zhí)行。如果該進(jìn)程只有一個(gè)線程,或者其所有線程都已經(jīng)阻塞,則控制權(quán)將再次返回給操作系統(tǒng)。而現(xiàn)在,操作系統(tǒng)就會(huì)切換到其他線程了。
現(xiàn)在操作系統(tǒng)的線程實(shí)現(xiàn)模型:
用戶態(tài)的執(zhí)行負(fù)責(zé)進(jìn)程內(nèi)部線程在非阻塞時(shí),即我們同時(shí)實(shí)現(xiàn)內(nèi)核態(tài)和用戶態(tài)線程管理。每個(gè)內(nèi)核態(tài)線程可以服務(wù)一個(gè)或者更多個(gè)用戶態(tài)線程。
線程從用戶態(tài)切換到內(nèi)核態(tài):
什么情況下會(huì)造成線程從用戶態(tài)到內(nèi)核態(tài)的切換呢?
首先,如果在程序運(yùn)行過程中發(fā)生中斷或者異常,系統(tǒng)將自動(dòng)切換到內(nèi)核態(tài)來運(yùn)行中斷或異常處理機(jī)制。
此外,程序進(jìn)行系統(tǒng)調(diào)用也會(huì)從用戶態(tài)切換到內(nèi)核態(tài)。
?
轉(zhuǎn)自:https://www.cnblogs.com/baoendemao/p/3804677.html
轉(zhuǎn)載于:https://www.cnblogs.com/xuelisheng/p/10112743.html
總結(jié)
以上是生活随笔為你收集整理的【Linux 线程】同一个进程中的线程共享哪些资源的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue单选,多选,多选的内容显示在页面可
- 下一篇: Python,Pandas,Bokeh