這篇文章主要介紹“Linux進(jìn)程與線程的區(qū)別”,在日常操作中,相信很多人在Linux進(jìn)程與線程的區(qū)別問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Linux進(jìn)程與線程的區(qū)別”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
嵐皋網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。創(chuàng)新互聯(lián)從2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
0.首先,簡要了解一下進(jìn)程和線程。對于操作系統(tǒng)而言,進(jìn)程是核心之核心,整個(gè)現(xiàn)代操作系統(tǒng)的根本,就是以進(jìn)程為單位在執(zhí)行任務(wù)。系統(tǒng)的管理架構(gòu)也是基于進(jìn)程層面的。在按下電源鍵之后,計(jì)算機(jī)就開始了復(fù)雜的啟動(dòng)過程,此處有一個(gè)經(jīng)典問題:當(dāng)按下電源鍵之后,計(jì)算機(jī)如何把自己由靜止啟動(dòng)起來的?本文不討論系統(tǒng)啟動(dòng)過程,請讀者自行科普。操作系統(tǒng)啟動(dòng)的過程簡直可以描述為上帝創(chuàng)造萬物的過程,期初沒有世界,但是有上帝,是上帝創(chuàng)造了世界,之后創(chuàng)造了萬物,然后再創(chuàng)造了人,然后塑造了人的七情六欲,再然后人類社會開始遵循自然規(guī)律繁衍生息。。。操作系統(tǒng)啟動(dòng)進(jìn)程的階段就相當(dāng)于上帝造人的階段。本文討論的全部內(nèi)容都是“上帝造人”之后的事情。第一個(gè)被創(chuàng)造出來的進(jìn)程是號進(jìn)程,這個(gè)進(jìn)程在操作系統(tǒng)層面是不可見的,但它存在著。號進(jìn)程完成了操作系統(tǒng)的功能加載與初期設(shè)定,然后它創(chuàng)造了1號進(jìn)程(init),這個(gè)1號進(jìn)程就是操作系統(tǒng)的“耶穌”。1號進(jìn)程是上帝派來管理整個(gè)操作系統(tǒng)的,所以在用pstree查看進(jìn)程樹可知,1號進(jìn)程位于樹根。再之后,系統(tǒng)的很多管理程序都以進(jìn)程身份被1號進(jìn)程創(chuàng)造出來,還創(chuàng)造了與人類溝通的橋梁——shell。從那之后,人類可以跟操作系統(tǒng)進(jìn)行交流,可以編寫程序,可以執(zhí)行任務(wù)。。。
而這一切,都是基于進(jìn)程的。每一個(gè)任務(wù)(進(jìn)程)被創(chuàng)建時(shí),系統(tǒng)會為他分配存儲空間等必要資源,然后在內(nèi)核管理區(qū)為該進(jìn)程創(chuàng)建管理節(jié)點(diǎn),以便后來控制和調(diào)度該任務(wù)的執(zhí)行。
進(jìn)程真正進(jìn)入執(zhí)行階段,還需要獲得CPU的使用權(quán),這一切都是操作系統(tǒng)掌管著,也就是所謂的調(diào)度,在各種條件滿足(資源與CPU使用權(quán)均獲得)的情況下,啟動(dòng)進(jìn)程的執(zhí)行過程。
除CPU而外,一個(gè)很重要的資源就是存儲器了,系統(tǒng)會為每個(gè)進(jìn)程分配獨(dú)有的存儲空間,當(dāng)然包括它特別需要的別的資源,比如寫入時(shí)外部設(shè)備是可使用狀態(tài)等等。有了上面的引入,我們可以對進(jìn)程做一個(gè)簡要的總結(jié):
進(jìn)程,是計(jì)算機(jī)中的程序關(guān)于某數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。它的執(zhí)行需要系統(tǒng)分配資源創(chuàng)建實(shí)體之后,才能進(jìn)行。
隨著技術(shù)發(fā)展,在執(zhí)行一些細(xì)小任務(wù)時(shí),本身無需分配單獨(dú)資源時(shí)(多個(gè)任務(wù)共享同一組資源即可,比如所有子進(jìn)程共享父進(jìn)程的資源),進(jìn)程的實(shí)現(xiàn)機(jī)制依然會繁瑣的將資源分割,這樣造成浪費(fèi),而且還消耗時(shí)間。后來就有了專門的多任務(wù)技術(shù)被創(chuàng)造出來——線程。
線程的特點(diǎn)就是在不需要獨(dú)立資源的情況下就可以運(yùn)行。如此一來會極大節(jié)省資源開銷,以及處理時(shí)間。
1.好了,前面的一段文字是簡要引入兩個(gè)名詞,即進(jìn)程和線程。本文討論目標(biāo)是解釋清楚進(jìn)程和線程的區(qū)別,關(guān)于二者的技術(shù)實(shí)現(xiàn),請讀者查閱相關(guān)資料。
下面我們開始重點(diǎn)討論本文核心了。從下面幾個(gè)方面闡述進(jìn)程和線程的區(qū)別。
1).二者的相同點(diǎn)
2).實(shí)現(xiàn)方式的差異
3).多任務(wù)程序設(shè)計(jì)模式的區(qū)別
4).實(shí)體間(進(jìn)程間,線程間,進(jìn)線程間)通信方式的不同
5).控制方式的異同
6).資源管理方式的異同
7).個(gè)體間輩分關(guān)系的迥異
8).進(jìn)程池與線程池的技術(shù)實(shí)現(xiàn)差別
接下來我們就逐個(gè)進(jìn)行解釋。
1).二者的相同點(diǎn)
無論是進(jìn)程還是線程,對于程序員而言,都是用來實(shí)現(xiàn)多任務(wù)并發(fā)的技術(shù)手段。二者都可以獨(dú)立調(diào)度,因此在多任務(wù)環(huán)境下,功能上并無差異。并且二者都具有各自的實(shí)體,是系統(tǒng)獨(dú)立管理的對象個(gè)體。所以在系統(tǒng)層面,都可以通過技術(shù)手段實(shí)現(xiàn)二者的控制。而且二者所具有的狀態(tài)都非常相似。而且,在多任務(wù)程序中,子進(jìn)程(子線程)的調(diào)度一般與父進(jìn)程(父線程)平等競爭。
其實(shí)在Linux內(nèi)核2.4版以前,線程的實(shí)現(xiàn)和管理方式就是完全按照進(jìn)程方式實(shí)現(xiàn)的。在2.6版內(nèi)核以后才有了單獨(dú)的線程實(shí)現(xiàn)。
2).實(shí)現(xiàn)方式的差異
進(jìn)程是資源分配的基本單位,線程是調(diào)度的基本單位。
這句經(jīng)典名言已流傳數(shù)十年,各種操作系統(tǒng)教材都可見此描述。確實(shí)如此,這就是二者的顯著區(qū)別。讀者請注意“基本”二字。相信有讀者看到前半句的時(shí)候就在心里思考,“進(jìn)程豈不是不能調(diào)度?”,非也!進(jìn)程和線程都可以被調(diào)度,否則多進(jìn)程程序該如何運(yùn)行呢!
只是,線程是更小的可以調(diào)度的單位,也就是說,只要達(dá)到線程的水平就可以被調(diào)度了,進(jìn)程自然可以被調(diào)度。它強(qiáng)調(diào)的是分配資源時(shí)的對象必須是進(jìn)程,不會給一個(gè)線程單獨(dú)分配系統(tǒng)管理的資源。若要運(yùn)行一個(gè)任務(wù),想要獲得資源,最起碼得有進(jìn)程,其他子任務(wù)可以以線程身份運(yùn)行,資源共享就行了。
簡而言之,進(jìn)程的個(gè)體間是完全獨(dú)立的,而線程間是彼此依存的。多進(jìn)程環(huán)境中,任何一個(gè)進(jìn)程的終止,不會影響到其他進(jìn)程。而多線程環(huán)境中,父線程終止,全部子線程被迫終止(沒有了資源)。而任何一個(gè)子線程終止一般不會影響其他線程,除非子線程執(zhí)行了exit()系統(tǒng)調(diào)用。任何一個(gè)子線程執(zhí)行exit(),全部線程同時(shí)滅亡。
其實(shí),也沒有人寫出只有線程而沒有進(jìn)程的程序。多線程程序中至少有一個(gè)主線程,而這個(gè)主線程其實(shí)就是有main函數(shù)的進(jìn)程。它是整個(gè)程序的進(jìn)程,所有線程都是它的子線程。我們通常把具有多線程的主進(jìn)程稱之為主線程。
從系統(tǒng)實(shí)現(xiàn)角度講,進(jìn)程的實(shí)現(xiàn)是調(diào)用fork系統(tǒng)調(diào)用:
pid_t fork(void);
線程的實(shí)現(xiàn)是調(diào)用clone系統(tǒng)調(diào)用:
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */
);
其中,fork()是將父進(jìn)程的全部資源復(fù)制給了子進(jìn)程。而線程的clone只是復(fù)制了一小部分必要的資源。在調(diào)用clone時(shí)可以通過參數(shù)控制要復(fù)制的對象??梢哉f,fork實(shí)現(xiàn)的是clone的加強(qiáng)完整版。當(dāng)然,后來操作系統(tǒng)還進(jìn)一步優(yōu)化fork實(shí)現(xiàn)——寫時(shí)復(fù)制技術(shù)。在子進(jìn)程需要復(fù)制資源(比如子進(jìn)程執(zhí)行寫入動(dòng)作更改父進(jìn)程內(nèi)存空間)時(shí)才復(fù)制,否則創(chuàng)建子進(jìn)程時(shí)先不復(fù)制。
實(shí)際中,編寫多進(jìn)程程序時(shí)采用fork創(chuàng)建子進(jìn)程實(shí)體。而創(chuàng)建線程時(shí)并不采用clone系統(tǒng)調(diào)用,而是采用線程庫函數(shù)。常用線程庫有Linux-Native線程庫和POSIX線程庫。其中應(yīng)用最為廣泛的是POSIX線程庫。因此讀者在多線程程序中看到的是pthread_create而非clone。
我們知道,庫是建立在操作系統(tǒng)層面上的功能集合,因而它的功能都是操作系統(tǒng)提供的。由此可知,線程庫的內(nèi)部很可能實(shí)現(xiàn)了clone的調(diào)用。不管是進(jìn)程還是線程的實(shí)體,都是操作系統(tǒng)上運(yùn)行的實(shí)體。
最后,我們說一下vfork() 。這也是一個(gè)系統(tǒng)調(diào)用,用來創(chuàng)建一個(gè)新的進(jìn)程。它創(chuàng)建的進(jìn)程并不復(fù)制父進(jìn)程的資源空間,而是共享,也就說實(shí)際上vfork實(shí)現(xiàn)的是一個(gè)接近線程的實(shí)體,只是以進(jìn)程方式來管理它。并且,vfork()的子進(jìn)程與父進(jìn)程的運(yùn)行時(shí)間是確定的:子進(jìn)程“結(jié)束”后父進(jìn)程才運(yùn)行。請讀者注意“結(jié)束”二字。并非子進(jìn)程完成退出之意,而是子進(jìn)程返回時(shí)。一般采用vfork()的子進(jìn)程,都會緊接著執(zhí)行execv啟動(dòng)一個(gè)全新的進(jìn)程,該進(jìn)程的進(jìn)程空間與父進(jìn)程完全獨(dú)立不相干,所以不需要復(fù)制父進(jìn)程資源空間。此時(shí),execv返回時(shí)父進(jìn)程就認(rèn)為子進(jìn)程“結(jié)束”了,自己開始運(yùn)行。實(shí)際上子進(jìn)程繼續(xù)在一個(gè)完全獨(dú)立的空間運(yùn)行著。舉個(gè)例子,比如在一個(gè)聊天程序中,彈出了一個(gè)視頻播放器。你說視頻播放器要繼承你的聊天程序的進(jìn)程空間的資源干嘛?莫非視頻播放器想要窺探你的聊天隱私不成?懂了吧!
3).多任務(wù)程序設(shè)計(jì)模式的區(qū)別
由于進(jìn)程間是獨(dú)立的,所以在設(shè)計(jì)多進(jìn)程程序時(shí),需要做到資源獨(dú)立管理時(shí)就有了天然優(yōu)勢,而線程就顯得麻煩多了。比如多任務(wù)的TCP程序的服務(wù)端,父進(jìn)程執(zhí)行accept()一個(gè)客戶端連接請求之后會返回一個(gè)新建立的連接的描述符DES,此時(shí)如果fork()一個(gè)子進(jìn)程,將DES帶入到子進(jìn)程空間去處理該連接的請求,父進(jìn)程繼續(xù)accept等待別的客戶端連接請求,這樣設(shè)計(jì)非常簡練,而且父進(jìn)程可以用同一變量(val)保存accept()的返回值,因?yàn)樽舆M(jìn)程會復(fù)制val到自己空間,父進(jìn)程再覆蓋此前的值不影響子進(jìn)程工作。但是如果換成多線程,父線程就不能復(fù)用一個(gè)變量val多次執(zhí)行accept()了。因?yàn)樽泳€程沒有復(fù)制val的存儲空間,而是使用父線程的,如果子線程在讀取val時(shí)父線程接受了另一個(gè)客戶端請求覆蓋了該值,則子線程無法繼續(xù)處理上一次的連接任務(wù)了。改進(jìn)的辦法是子線程立馬復(fù)制val的值在自己的棧區(qū),但父線程必須保證子線程復(fù)制動(dòng)作完成之后再執(zhí)行新的accept()。但這執(zhí)行起來并不簡單,因?yàn)樽泳€程與父線程的調(diào)度是獨(dú)立的,父線程無法知道子線程何時(shí)復(fù)制完畢。這又得發(fā)生線程間通信,子線程復(fù)制完成后主動(dòng)通知父線程。這樣一來父線程的處理動(dòng)作必然不能連貫,比起多進(jìn)程環(huán)境,父線程顯得效率有所下降。
PS:這里引述一個(gè)知名的面試問題:多進(jìn)程的TCP服務(wù)端,能否互換fork()與accept()的位置?請讀者自行思考。
關(guān)于資源不獨(dú)立,看似是個(gè)缺點(diǎn),但在有的情況下就成了優(yōu)點(diǎn)。多進(jìn)程環(huán)境間完全獨(dú)立,要實(shí)現(xiàn)通信的話就得采用進(jìn)程間的通信方式,它們通常都是耗時(shí)間的。而線程則不用任何手段數(shù)據(jù)就是共享的。當(dāng)然多個(gè)子線程在同時(shí)執(zhí)行寫入操作時(shí)需要實(shí)現(xiàn)互斥,否則數(shù)據(jù)就寫“臟”了。
4).實(shí)體間(進(jìn)程間,線程間,進(jìn)線程間)通信方式的不同
進(jìn)程間的通信方式有這樣幾種:
A.共享內(nèi)存 B.消息隊(duì)列 C.信號量 D.有名管道 E.無名管道 F.信號
G.文件 H.socket
線程間的通信方式上述進(jìn)程間的方式都可沿用,且還有自己獨(dú)特的幾種:
A.互斥量 B.自旋鎖 C.條件變量 D.讀寫鎖 E.線程信號
G.全局變量
值得注意的是,線程間通信用的信號不能采用進(jìn)程間的信號,因?yàn)樾盘柺腔谶M(jìn)程為單位的,而線程是共屬于同一進(jìn)程空間的。故而要采用線程信號。
綜上,進(jìn)程間通信手段有8種。線程間通信手段有13種。
而且,進(jìn)程間采用的通信方式要么需要切換內(nèi)核上下文,要么要與外設(shè)訪問(有名管道,文件)。所以速度會比較慢。而線程采用自己特有的通信方式的話,基本都在自己的進(jìn)程空間內(nèi)完成,不存在切換,所以通信速度會較快。也就是說,進(jìn)程間與線程間分別采用的通信方式,除了種類的區(qū)別外,還有速度上的區(qū)別。
另外,進(jìn)程與線程之間穿插通信的方式,除信號以外其他進(jìn)程間通信方式都可采用。
線程有內(nèi)核態(tài)線程與用戶級線程,相關(guān)知識請參看我的另一篇博文《Linux線程的實(shí)質(zhì)》。
5).控制方式的異同
進(jìn)程與線程的身份標(biāo)示ID管理方式不一樣,進(jìn)程的ID為pid_t類型,實(shí)際為一個(gè)int型的變量(也就是說是有限的):
/usr/include/unistd.h:260:typedef __pid_t pid_t;
/usr/include/bits/types.h:126:# define __STD_TYPE typedef
/usr/include/bits/types.h:142:__STD_TYPE __PID_T_TYPE __pid_t;
/usr/include/bits/typesizes.h:53:#define __PID_T_TYPE __S32_TYPE
/usr/include/bits/types.h:100:#define __S32_TYPE int
在全系統(tǒng)中,進(jìn)程ID是唯一標(biāo)識,對于進(jìn)程的管理都是通過PID來實(shí)現(xiàn)的。每創(chuàng)建一個(gè)進(jìn)程,內(nèi)核去中就會創(chuàng)建一個(gè)結(jié)構(gòu)體來存儲該進(jìn)程的全部信息:
注:下述代碼來自 Linux內(nèi)核3.18.1
include/linux/sched.h:1235:struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
void *stack;
...
pid_t pid;
pid_t tgid;
...
};
每一個(gè)存儲進(jìn)程信息的節(jié)點(diǎn)也都保存著自己的PID。需要管理該進(jìn)程時(shí)就通過這個(gè)ID來實(shí)現(xiàn)(比如發(fā)送信號)。當(dāng)子進(jìn)程結(jié)束要回收時(shí)(子進(jìn)程調(diào)用exit()退出或代碼執(zhí)行完),需要通過wait()系統(tǒng)調(diào)用來進(jìn)行,未回收的消亡進(jìn)程會成為僵尸進(jìn)程,其進(jìn)程實(shí)體已經(jīng)不復(fù)存在,但會虛占PID資源,因此回收是有必要的。
線程的ID是一個(gè)long型變量:
/usr/include/bits/pthreadtypes.h:60:typedef unsigned long int pthread_t;
它的范圍大得多,管理方式也不一樣。線程ID一般在本進(jìn)程空間內(nèi)作用就可以了,當(dāng)然系統(tǒng)在管理線程時(shí)也需要記錄其信息。其方式是,在內(nèi)核創(chuàng)建一個(gè)內(nèi)核態(tài)線程與之對應(yīng),也就是說每一個(gè)用戶創(chuàng)建的線程都有一個(gè)內(nèi)核態(tài)線程對應(yīng)。但這種對應(yīng)關(guān)系不是一對一,而是多對一的關(guān)系,也就是一個(gè)內(nèi)核態(tài)線程可以對應(yīng)著多個(gè)用戶級線程。還是請讀者參看《Linux線程的實(shí)質(zhì)》普及相關(guān)概念。此處貼出blog地址:
http://my.oschina.net/cnyinlinux/blog/367910
對于線程而言,若要主動(dòng)終止需要調(diào)用pthread_exit() ,主線程需要調(diào)用pthread_join()來回收(前提是該線程沒有被detached,相關(guān)概念請查閱線程的“分離屬性”)。像線發(fā)送線程信號也是通過線程ID實(shí)現(xiàn)的。
6).資源管理方式的異同
進(jìn)程本身是資源分配的基本單位,因而它的資源都是獨(dú)立的,如果有多進(jìn)程間的共享資源,就要用到進(jìn)程間的通信方式了,比如共享內(nèi)存。共享數(shù)據(jù)就放在共享內(nèi)存去,大家都可以訪問,為保證數(shù)據(jù)寫入的安全,加上信號量一同使用。一般而言,共享內(nèi)存都是和信號量一起使用。消息隊(duì)列則不同,由于消息的收發(fā)是原子操作,因而自動(dòng)實(shí)現(xiàn)了互斥,單獨(dú)使用就是安全的。
線程間要使用共享資源不需要用共享內(nèi)存,直接使用全局變量即可,或者malloc()動(dòng)態(tài)申請內(nèi)存。顯得方便直接。而且互斥使用的是同一進(jìn)程空間內(nèi)的互斥量,所以效率上也有優(yōu)勢。
實(shí)際中,為了使程序內(nèi)資源充分規(guī)整,也都采用共享內(nèi)存來存儲核心數(shù)據(jù)。不管進(jìn)程還是線程,都采用這種方式。原因之一就是,共享內(nèi)存是脫離進(jìn)程的資源,如果進(jìn)程發(fā)生意外終止的話,共享內(nèi)存可以獨(dú)立存在不會被回收(是否回收由用戶編程實(shí)現(xiàn))。進(jìn)程的空間在進(jìn)程崩潰的那一刻也被系統(tǒng)回收了。雖然有coredump機(jī)制,但也只能是有限的彌補(bǔ)。共享內(nèi)存在進(jìn)程down之后還完整保存,這樣可以拿來分析程序的故障原因。同時(shí),運(yùn)行的寶貴數(shù)據(jù)沒有丟失,程序重啟之后還能繼續(xù)處理之前未完成的任務(wù),這也是采用共享內(nèi)存的又一大好處。
總結(jié)之,進(jìn)程間的通信方式都是脫離于進(jìn)程本身存在的,是全系統(tǒng)都可見的。這樣一來,進(jìn)程的單點(diǎn)故障并不會損毀數(shù)據(jù),當(dāng)然這不一定全是優(yōu)點(diǎn)。比如,進(jìn)程崩潰前對信號量加鎖,崩潰后重啟,然后再次進(jìn)入運(yùn)行狀態(tài),此時(shí)直接進(jìn)行加鎖,可能造成死鎖,程序再也無法繼續(xù)運(yùn)轉(zhuǎn)。再比如,共享內(nèi)存是全系統(tǒng)可見的,如果你的進(jìn)程資源被他人誤讀誤寫,后果肯定也是你不想要的。所以,各有利弊,關(guān)鍵在于程序設(shè)計(jì)時(shí)如何考量,技術(shù)上如何規(guī)避。這說起來又是編程技巧和經(jīng)驗(yàn)的事情了。
7).個(gè)體間輩分關(guān)系的迥異
進(jìn)程的備份關(guān)系森嚴(yán),在父進(jìn)程沒有結(jié)束前,所有的子進(jìn)程都尊從父子關(guān)系,也就是說A創(chuàng)建了B,則A與B是父子關(guān)系,B又創(chuàng)建了C,則B與C也是父子關(guān)系,A與C構(gòu)成爺孫關(guān)系,也就是說C是A的孫子進(jìn)程。在系統(tǒng)上使用pstree命令打印進(jìn)程樹,可以清晰看到備份關(guān)系。
多線程間的關(guān)系沒有那么嚴(yán)格,不管是父線程還是子線程創(chuàng)建了新的線程,都是共享父線程的資源,所以,都可以說是父線程的子線程,也就是只存在一個(gè)父線程,其余線程都是父線程的子線程。
8).進(jìn)程池與線程池的技術(shù)實(shí)現(xiàn)差別
我們都知道,進(jìn)程和線程的創(chuàng)建時(shí)需要時(shí)間的,并且系統(tǒng)所能承受的進(jìn)程和線程數(shù)也是有上限的,這樣一來,如果業(yè)務(wù)在運(yùn)行中需要?jiǎng)討B(tài)創(chuàng)建子進(jìn)程或線程時(shí),系統(tǒng)無法承受不能立即創(chuàng)建的話,必然影響業(yè)務(wù)。綜上,聰明的程序員發(fā)明了一種新方法——池。
在程序啟動(dòng)時(shí),就預(yù)先創(chuàng)建一些子進(jìn)程或線程,這樣在需要用時(shí)直接使喚。這就是老人口中的“多生孩子多種樹”。程序才開始運(yùn)行,沒有那么多的服務(wù)請求,必然大量的進(jìn)程或線程空閑,這時(shí)候一般讓他們“冬眠”,這樣不耗資源,要不然一大堆孩子的口食也是個(gè)負(fù)擔(dān)啊。對于進(jìn)程和線程而言,方式是不一樣的。另外,當(dāng)你有了任務(wù),要分配給那些孩子的時(shí)候,手段也不一樣。下面就分別來解說。
進(jìn)程池
首先創(chuàng)建了一批進(jìn)程,就得管理,也就是你得分開保存進(jìn)程ID,可以用數(shù)組,也可用鏈表。建議用數(shù)組,這樣可以實(shí)現(xiàn)常數(shù)內(nèi)找到某個(gè)線程,而且既然做了進(jìn)程池,就預(yù)先估計(jì)好了生產(chǎn)多少進(jìn)程合適,一般也不會再動(dòng)態(tài)延展。就算要?jiǎng)討B(tài)延展,也能預(yù)估范圍,提前做一個(gè)足夠大的數(shù)組。不為別的,就是為了快速響應(yīng)。本來錯(cuò)進(jìn)程池的目的也是為了效率。
接下來就要讓閑置進(jìn)程冬眠了,可以讓他們pause()掛起,也可用信號量掛起,還可以用IPC阻塞,方法很多,分析各自優(yōu)缺點(diǎn)根據(jù)實(shí)際情況采用就是了。
然后是分配任務(wù)了,當(dāng)你有任務(wù)的時(shí)候就要讓他干活了。喚醒了進(jìn)程,讓它從哪兒開始干呢?肯定得用到進(jìn)程間通信了,比如信號喚醒它,然后讓它在預(yù)先指定的地方去讀取任務(wù),可以用函數(shù)指針來實(shí)現(xiàn),要讓它干什么,就在約定的地方設(shè)置代碼段指針。這也只是告訴了它怎么干,還沒說干什么(數(shù)據(jù)條件),再通過共享內(nèi)存把要處理的數(shù)據(jù)設(shè)置好,這也子進(jìn)程就知道怎么做了。干完之后再來一次進(jìn)程間通信然后自己繼續(xù)冬眠,父進(jìn)程就知道孩子干完了,收割成果。
最后結(jié)束時(shí)回收子進(jìn)程,向各進(jìn)程發(fā)送信號喚醒,改變激活狀態(tài)讓其主動(dòng)結(jié)束,然后逐個(gè)wait()就可以了。
線程池
線程池的思想與上述類似,只是它更為輕量級,所以調(diào)度起來不用等待額外的資源。
要讓線程阻塞,用條件變量就是了,需要干活的時(shí)候父線程改變條件,子線程就被激活。
線程間通信方式就不用贅述了,不用繁瑣的通信就能達(dá)成,比起進(jìn)程間效率要高一些。
線程干完之后自己再改變條件,這樣父線程也就知道該收割成果了。
整個(gè)程序結(jié)束時(shí),逐個(gè)改變條件并改變激活狀態(tài)讓子線程結(jié)束,最后逐個(gè)回收即可。
到此,關(guān)于“Linux進(jìn)程與線程的區(qū)別”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
網(wǎng)站題目:Linux進(jìn)程與線程的區(qū)別
文章來源:http://jinyejixie.com/article40/podeeo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、全網(wǎng)營銷推廣、標(biāo)簽優(yōu)化、搜索引擎優(yōu)化、動(dòng)態(tài)網(wǎng)站、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)