多進(jìn)程&多線程

多進(jìn)程

進(jìn)程是資源(CPU、內(nèi)存等)分配的基本單位,它是程序執(zhí)行時的一個實例。程序運行時系統(tǒng)就會創(chuàng)建一個進(jìn)程,并為它分配資源,然后把該進(jìn)程放入進(jìn)程就緒隊列,進(jìn)程調(diào)度器選中它的時候就會為它分配CPU時間,程序開始真正運行。

Linux系統(tǒng)函數(shù)fork()可以在父進(jìn)程中創(chuàng)建一個子進(jìn)程,這樣的話,在一個進(jìn)程接到來自客戶端新的請求時就可以復(fù)制出一個子進(jìn)程讓其來處理,父進(jìn)程只需負(fù)責(zé)監(jiān)控請求的到來,然后創(chuàng)建子進(jìn)程讓其去處理,這樣就能做到并發(fā)處理。
[注]
fork和exec函數(shù)是兩個重要的系統(tǒng)調(diào)用函數(shù)

  • fork的作用是根據(jù)一個現(xiàn)有的進(jìn)程復(fù)制出一個新進(jìn)程,原有的進(jìn)程稱為父進(jìn)程(Parent Process),新進(jìn)程稱為子進(jìn)程(Child Process)
#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

fork調(diào)用失敗返回-1;
調(diào)用成功:fork函數(shù)會返回兩次結(jié)果,因為操作系統(tǒng)會把當(dāng)前進(jìn)程的數(shù)據(jù)復(fù)制一遍,然后程序就分兩個進(jìn)程繼續(xù)運行后面的代碼,fork分別在父進(jìn)程和子進(jìn)程中返回,在子進(jìn)程返回的值pid永遠(yuǎn)是0,在父進(jìn)程返回的是子進(jìn)程的進(jìn)程id。
fork的特點簡單概括起來就是:"調(diào)用一次,返回兩次",在父進(jìn)程中調(diào)用一次,在父進(jìn)程和子進(jìn)程中各返回一次
gdb調(diào)試子進(jìn)程:set follow-fork-mode child 設(shè)置跟蹤子進(jìn)程

  • exec函數(shù)
    用fork創(chuàng)建子進(jìn)程后執(zhí)行的是和父進(jìn)程相同的程序(但有可能執(zhí)行不同的代碼分支),子進(jìn)程往往調(diào)用exec函數(shù)以執(zhí)行另一個程序。當(dāng)進(jìn)程調(diào)用exec函數(shù)時,該進(jìn)程的用戶空間代碼和數(shù)據(jù)完全被新程序替換,從新程序的啟動例程開始執(zhí)行,調(diào)用exec函數(shù)并不創(chuàng)建新進(jìn)程,所以調(diào)用exec前后該進(jìn)程的id并未改變
    exec的作用簡單概括起來就是使調(diào)用其的進(jìn)程(一般為子進(jìn)程)執(zhí)行自己對應(yīng)的處理業(yè)務(wù)
    有6種以exec開頭的函數(shù),統(tǒng)稱exec函數(shù)
#include <unistd.h>

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ... , char *const envp[ ]);
int execv(const char *path,  char *const argv[ ]);
int execvp(const char *file,  char *const argv[ ]);
int execve(const char *path,  char *const argv[ ], char *const envp[ ]);

這些函數(shù)如果調(diào)用成功則加載新的程序從啟動代碼開始執(zhí)行,不再返回,如果調(diào)用出錯則返回-1,所以exec函數(shù)只有出錯的返回值而沒有成功的返回值。

這些函數(shù)原型看起來很容易混淆,掌握規(guī)律則很好記

  • 不帶字母p(表示path)的exec函數(shù)第一個參數(shù)必須是程序的相對路徑或絕對路徑,例如:"/bin/ls"或./a.out
  • 帶字母p的函數(shù)
  • 帶有字母l(表示list)
  • e結(jié)尾的exec函數(shù),環(huán)境變量
不知道的話記得萬能的 Man

wait/waitpid:會徹底清除掉這個進(jìn)程,

如果一個進(jìn)程已經(jīng)終止,但是他的父進(jìn)程尚未調(diào)用wait或waitpid對他進(jìn)行清理,這是的進(jìn)程狀態(tài)稱為僵尸(Zombie)進(jìn)程,任何進(jìn)程在剛終止時都是僵尸進(jìn)程,正常情況下,僵尸進(jìn)程都立即被父進(jìn)程清理了。

wait和waitpid都可以獲取子進(jìn)程的終止信息
兩者的區(qū)別:

補充


多線程

線程是程序執(zhí)行時的最小單位,它是進(jìn)程的一個執(zhí)行流,是CPU調(diào)度和分派的基本單位,一個進(jìn)程可以由很多個線程組成,線程間共享進(jìn)程的所有資源,每個線程有自己的堆棧和局部變量。線程由CPU獨立調(diào)度執(zhí)行,在多CPU環(huán)境下就允許多個線程同時運行。同樣多線程也可以實現(xiàn)并發(fā)操作,每個請求分配一個線程來處理。

創(chuàng)建:pthread_create()
掛起:pthread_join()
終止(3種):
return
pthread_cancel()
pthread_exit()

線程和進(jìn)程各自有什么區(qū)別和優(yōu)劣呢?

  • 進(jìn)程是資源分配的最小單位,線程是程序執(zhí)行的最小單位。
  • 進(jìn)程有自己的獨立地址空間,每啟動一個進(jìn)程,系統(tǒng)就會為它分配地址空間,建立數(shù)據(jù)表來維護(hù)代碼段、堆棧段和數(shù)據(jù)段,這種操作非常昂貴。而線程是共享進(jìn)程中的數(shù)據(jù)的,使用相同的地址空間,因此CPU切換一個線程的花費遠(yuǎn)比進(jìn)程要小很多,同時創(chuàng)建一個線程的開銷也比進(jìn)程要小很多。
  • 線程之間的通信更方便,同一進(jìn)程下的線程共享全局變量、靜態(tài)變量等數(shù)據(jù),而進(jìn)程之間的通信需要以通信的方式(IPC)進(jìn)行。不過如何處理好同步與互斥是編寫多線程程序的難點。
  • 但是多進(jìn)程程序更健壯,多線程程序只要有一個線程死掉,整個進(jìn)程也死掉了,而一個進(jìn)程死掉并不會對另外一個進(jìn)程造成影響,因為進(jìn)程有自己獨立的地址空間。
From《Unix網(wǎng)絡(luò)編程》
  • fork is expensive. Memory is copied from the parent to the child, all descriptors are duplicated in the child, and so on. Current implementations use a technique called copy-on-write, which avoids a copy of the parent’s data space to the child until the child needs its own copy. But, regardless of this optimization, fork is expensive.
  • IPC is required to pass information between the parent and child after the fork. Passing information from the parent to the child before the fork is easy, since the child starts with a copy of the parent’s data space and with a copy of all the parent’s descriptors. But, returning information from the child to the parent takes more work.
  • Threads help with both problems. Threads are sometimes called lightweight processes since a thread is “l(fā)ighter weight” than a process. That is, thread creation can be 10–100 times faster than process creation.
  • All threads within a process share the same global memory. This makes the sharing of information easy between the threads, but along with this simplicity comes the problem
參考引用:

米羅西的博文
多進(jìn)程與多線程 From yuan先生 [寫的是真滴好!代碼實例Python]
多線程還是多進(jìn)程的選擇及區(qū)別 [代碼實例C/C++]
實例

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.內(nèi)存的頁面置換算法 (1)最佳置換算法(OPT)(理想置換算法):從主存中移出永遠(yuǎn)不再需要的頁面;如無這樣的...
    杰倫哎呦哎呦閱讀 3,595評論 1 9
  • 又來到了一個老生常談的問題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢? 今天就這個問題開始,來談?wù)劜?..
    tangsl閱讀 4,322評論 0 23
  • 一、多進(jìn)程 1、子進(jìn)程(subprocess包) 在python中,通過subprocess包,fork一個子進(jìn)程...
    meetliuxin閱讀 561評論 0 1
  • 曾經(jīng)的信誓旦旦,豪情萬丈,總以為自己無所不能,在現(xiàn)實的一次次響亮的耳光之后,告訴自己,自己還是不行,一次次被否定,...
    Cthinker閱讀 349評論 0 0
  • 孔子說:“七十而從心所欲,不逾矩。”我忘了后面一句“不逾矩”,理解成孔子到了老年,看透一切,也超脫自我,尋求自由,...
    卿瑩閱讀 273評論 0 0

友情鏈接更多精彩內(nèi)容