欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:運維 【Linux】進程控制

柚子快報邀請碼778899分享:運維 【Linux】進程控制

http://yzkb.51969.com/

??個人主頁:秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343??系列專欄:https://blog.csdn.net/qinjh_/category_12625432.html

目錄

fork函數(shù)初識

fork 函數(shù)返回值?

寫時拷貝

?fork調(diào)用失敗的原因

進程終止?

?進程退出場景

?進程常見退出方法

?進程等待

進程等待必要性

進程等待的方法

wait方法

?waitpid方法

?獲取子進程status

非阻塞等待

前言

????? hello! 各位鐵子們大家好哇。

? ? ? ? ? ? ?今日更新了Linux的進程控制的內(nèi)容 ????? 歡迎大家關(guān)注?點贊?收藏??留言?

fork函數(shù)初識

在linux中fork函數(shù)時非常重要的函數(shù),它從已存在進程中創(chuàng)建一個新進程。新進程為子進程,而原進程為父進程。

#include

pid_t fork(void);

//返回值:子進程中返回0,父進程返回子進程id,出錯返回-1

進程調(diào)用fork,當(dāng)控制轉(zhuǎn)移到內(nèi)核中的fork代碼后,內(nèi)核做:

分配新的內(nèi)存塊和內(nèi)核數(shù)據(jù)結(jié)構(gòu)給子進程將父進程部分數(shù)據(jù)結(jié)構(gòu)內(nèi)容拷貝至子進程添加子進程到系統(tǒng)進程列表當(dāng)中 fork返回,開始調(diào)度器調(diào)度

當(dāng)一個進程調(diào)用fork之后,就有兩個二進制代碼相同的進程。而且它們都運行到相同的地方。但每個進程都將可以 開始它們自己的旅程。?

fork 函數(shù)返回值?

子進程返回0,父進程返回的是子進程的pid。?

為什么父進程返回的是子進程的pid?

為了讓父進程方便對子進程進行標(biāo)識,進而進行管理。?

寫時拷貝

通常,父子代碼共享,父子不寫入時,數(shù)據(jù)也是共享的,當(dāng)任意一方試圖寫入,便以寫時拷貝的方式各自一份副本。?(進程的獨立性)

?fork調(diào)用失敗的原因

系統(tǒng)中有太多的進程實際用戶的進程數(shù)超過了限制?

進程終止?

進程終止做的事:

釋放曾經(jīng)的代碼和數(shù)據(jù)所占據(jù)的空間釋放內(nèi)核數(shù)據(jù)結(jié)構(gòu)

內(nèi)核數(shù)據(jù)結(jié)構(gòu)中,PCB會被延期處理,因為有一種狀態(tài)是僵尸狀態(tài)。

#include

2 #include

3

4 int main()

5 {

6 printf("I am process, pid:%d, ppid:%d\n",getpid(),getppid());

7 sleep(2);

8 return 100;

9 }

任何命令行啟動的進程,它的父進程都是bash,所以ppid都一樣。?

echo是內(nèi)建命令,打印的都是bash內(nèi)部的變量數(shù)據(jù)。?是一個變量名。

echo $?表示的是父進程獲取到的,最近一個子進程退出的退出碼。

main函數(shù)的返回值叫做進程的退出碼。

退出碼:

為0,標(biāo)識成功不為0,表示失敗

第一個echo $?返回./myprocess 的退出碼,第二個echo $?返回上一個echo $?的退出碼

雖然echo $?沒有創(chuàng)建子進程,但它是由父進程執(zhí)行的,所以他也會影響?的值。?

#include

2 #include

3 #include

4

5 int main()

6 {

7 for(int errcode=0;errcode<=255;errcode++)

8 {

9 printf("%d:%s\n",errcode,strerror(errcode));

10 }

11 printf("I am process, pid:%d, ppid:%d\n",getpid(),getppid());

12 sleep(2);

13 return 0;

14 }

退出碼不為0表示失敗。不同的非0值,一方面表示失敗,另一方面表示失敗的原因。

strerror函數(shù)會將錯誤碼轉(zhuǎn)成對應(yīng)的錯誤描述,如下圖;

父進程為什么要得到子進程的退出碼呢?

因為要知道子進程的退出情況。(成功還是失敗,失敗的原因是什么),然后展現(xiàn)給用戶看。

退出碼可以使用系統(tǒng)默認的,也可以自定義。?

?進程退出場景

?進程終止的3中情況:

代碼跑完,結(jié)果正確代碼跑完,結(jié)果不正確代碼異常終止

代碼跑完,結(jié)果不正確的原因可以通過退出碼確定。

一旦出現(xiàn)異常,退出碼就沒有意義了。

進程出異常,本質(zhì)是因為進程收到了OS發(fā)給進程的信號。

int main()

6 {

7 int *p=NULL;

8 while(1)

9 {

10 printf("I am a process,pid:%d\n",getpid());

11 sleep(1);

12 *p=100;//野指針

13 }

19 sleep(2);

20 return 0;

21 }

當(dāng)外面運行上面代碼后,會報段錯誤。?OS就會提前終止進程。

?我們把代碼里的野指針注釋掉,此時代碼正常運行,一直循環(huán)。此時我們給該進程發(fā)11號信號,該進程即使沒有錯誤,收到信號后,也會進行對應(yīng)的報錯。 所以說進程出異常,本質(zhì)是因為進程收到了OS發(fā)給進程的信號。

所以如果進程異常了,我們可以通過退出信號,就可以判斷進程為什么異常了,此時的退出碼是無意義的。

在用戶層面上,要確定進程是什么情況:

先確認是否異常如果不是異常,就一定是代碼跑完了,看退出碼即可。

衡量一個進程退出,只需要兩個數(shù)字:退出碼和退出信號。

?進程的PCB里面有退出信號和退出碼,當(dāng)進程退出時,會釋放代碼和數(shù)據(jù),但是PCB會保存一段時間,該進程變成Z(僵尸)狀態(tài)。父進程就可以從子進程的PCB中拿到退出信息。

?進程常見退出方法

正常終止:

main函數(shù)return,表示進程終止(非main函數(shù)的return,都只是表示函數(shù)結(jié)束)調(diào)用exit函數(shù)? 注意:在代碼的任意位置調(diào)用exit,都表示進程退出_exit (系統(tǒng)調(diào)用)

下面是exit的使用舉例:?

_exit和exit在使用上沒什么區(qū)別,只有一個細微的差別,如下例子:?

?上圖是帶\n的。結(jié)果打印并且換行了。

?

?上面是不帶\n的。結(jié)果打印了但沒換行。

?

上面是不帶\n的_exit的使用。結(jié)果什么也沒打印。?

?結(jié)論:exit會在進程退出的時候,沖刷緩沖區(qū),_exit不會。

exit在底層是調(diào)用_exit的。?由上面的結(jié)論可得,緩沖區(qū)在_exit之上,不然_exit也會沖刷緩沖區(qū)。

?進程等待

進程等待必要性

子進程退出,父進程如果不管不顧,就可能造成‘僵尸進程’的問題,進而造成內(nèi)存泄漏。進程一旦變成僵尸狀態(tài),那就刀槍不入,“殺人不眨眼”的kill -9 也無能為力,因為誰也沒有辦法 殺死一個已經(jīng)死去的進程。父進程派給子進程的任務(wù)完成的如何,我們需要知道。如,子進程運行完成,結(jié)果對還是不對, 或者是否正常退出。父進程通過進程等待的方式,回收子進程資源,獲取子進程退出信息

進程等待的方法

wait方法

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7

8 void ChildRun()

9 {

10 int cnt = 5;

11 while(cnt)

12 {

13 printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), get ppid(), cnt);

14 sleep(1);

15 cnt--;

16 }

17 }

18

19 int main()

20 {

21 printf("I am father, pid: %d, ppid:%d\n", getpid(), getppid());

22

23 pid_t id = fork();

24 if(id == 0)

25 {

26 // child

27 ChildRun();

28 printf("child quit ...\n");

29 exit(0);

30 }

31 // fahter

32 pid_t rid = wait(NULL);

33 if(rid > 0)

34 {

35 printf("wait success, rid: %d\n", rid);

36 }

37 }

作用:等待任何一個子進程退出

返回值:等待成功時,返回子進程的pid。失敗返回-1。?

參數(shù): 輸出型參數(shù),獲取子進程退出狀態(tài),不關(guān)心則可以設(shè)置成為NULL

運行上面的代碼,結(jié)果如下圖:

?上面代碼if后面不需要else就表示是父進程的代碼了。因為if里面即子進程里面用exit退出了,所以后面的都是父進程的。

?下面做出修改:

運行結(jié)果:

?修改后的代碼先讓父進程休眠十秒。子進程運行五秒后退出,此時由于父進程還在休眠無法回收,所以子進程就變成Z狀態(tài),再過五秒后,子進程就被父進程回收了。

?如果我們把sleep(10)注釋掉,此時父進程開始就馬上進入等待,等待期間父進程不會被調(diào)度。如果子進程沒有退出,父進程其實一直在阻塞等待。

?waitpid方法

pid_ t waitpid(pid_t pid, int *status, int options);

返回值:

當(dāng)正常返回的時候waitpid返回收集到的子進程的進程ID;如果設(shè)置了選項WNOHANG,而調(diào)用中waitpid發(fā)現(xiàn)沒有已退出的子進程可收集,則返回0;如果調(diào)用中出錯,則返回-1,這時errno會被設(shè)置成相應(yīng)的值以指示錯誤所在;

參數(shù):

pid:

Pid=-1,等待任一個子進程。與wait等效。Pid>0.等待其進程ID與pid相等的子進程。??status:

WIFEXITED(status): 若為正常終止子進程返回的狀態(tài),則為真。(查看進程是否是正常退出)WEXITSTATUS(status): 若WIFEXITED非零,提取子進程退出碼。(查看進程的退出碼)options:

WNOHANG: 若pid指定的子進程沒有結(jié)束,則waitpid()函數(shù)返回0,不予以等待。若正常結(jié)束,則返回該子進程的ID。?

waitpid有三個參數(shù),當(dāng)pid,即第一個參數(shù)為-1時,等待任意一個子進程,與wait等效。

當(dāng)?shù)谝粋€參數(shù)pid>0時,就會等待其進程ID與pid相等的子進程 。

如下圖,此時等待上方父進程的子進程。

?

等待失敗例子:

當(dāng)我們把pid給一個錯誤的,此時進程就是等待失敗。?

?獲取子進程status

?第二個參數(shù)status代表的是子進程的退出信息。

退出信息=退出碼+退出信號

wait和waitpid,都有一個status參數(shù),該參數(shù)是一個輸出型參數(shù)。如果傳遞NULL,表示不關(guān)心子進程的退出狀態(tài)信息。否則,操作系統(tǒng)會根據(jù)該參數(shù),將子進程的退出信息反饋給父進程。status不能簡單的當(dāng)作整形來看待,可以當(dāng)作位圖來看待(只研究status低16比特 位):

?最低7位表示終止信號,9到16位表示退出碼。所以退出碼的范圍是0~255。退出信號的范圍是0~125。這兩個范圍足以表示退出碼的退出信號的情況了。

19 int main()

20 {

21 printf("I am father, pid: %d, ppid:%d\n", getpid(), getppid());

22

23 pid_t id = fork();

24 if(id == 0)

25 {

26 // child

27 ChildRun();

28 printf("child quit ...\n");

29 exit(1);

30 }

31 sleep(7);

32 // fahter

33 // pid_t rid = wait(NULL);

34 int status=0;

35 pid_t rid=waitpid(id,&status,0);

36 if(rid > 0)

37 {

38 printf("wait success, rid: %d\n", rid);

39 }

40 else

41 {

42 printf("wait failed !\n");

43 }

44 sleep(3);

45 printf("father quit, status:%d, child quit code : %d,child quit signal: % d\n",status,(status>>8)&0xFF,status&0x7F);

46 }

上面是通過status退出信息來獲取退出碼和退出信號的代碼。

status右移8位,然后與0xFF即二進制的8個1進行按位與,獲取退出碼。

status按位與0x7F即二進制的7個1來獲取退出信號。

結(jié)果表明,前面所說都是正確的。

?實際上我們不使用位操作符處理status,而是使用兩個宏,WIFEXITED和WEXITSTATUS。

WIFEXITED(status): 若為正常終止子進程返回的狀態(tài),則為真。(查看進程是否是正常退出)WEXITSTATUS(status): 若WIFEXITED非零,提取子進程退出碼。(查看進程的退出碼)

非阻塞等待

?我們用的大部分接口都是阻塞等待接口,在阻塞等待時,父進程干不了別的事,一直在等待子進程退出。下面介紹非阻塞等待。

這里也需要用到一個宏:WNOHANG

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7

8 void ChildRun()

9 {

10 int cnt = 5;

11 while(cnt)

12 {

13 printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid (), cnt);

14 sleep(1);

15 cnt--;

16 }

17 }

18

19 int main()

20 {

21 printf("I am father, pid: %d, ppid:%d\n", getpid(), getppid());

22

23 pid_t id = fork();

24 if(id == 0)

25 {

26 // child

27 ChildRun();

28 printf("child quit ...\n");

29 exit(123);

30 }

31

32 //father

33 while(1)

34 {

35 int status=0;

36 pid_t rid=waitpid(id,&status,WNOHANG); //非阻塞等待

37 if(rid==0)

38 {

39 sleep(1);

40 printf("child is running, father check next time!\n");

41 //DoOtherThing();

42 }

43 else if(rid>0)

44 {

45 if(WIFEXITED(status))

46 {

47 printf("child quit success, child exit code:%d\n",WEXITSTATUS(status));

48 }

49 else

50 {

51 printf("child quit unnormal!\n");

52 }

53 break;

54 }

55 else

56 {

57 printf("waitpid failed!\n");

58 break;

59 }

60 }

使用WNOHANG的時候,需要使用循環(huán)結(jié)構(gòu)。因為WNOHANG只會查看一次子進程是否結(jié)束,使用循環(huán)結(jié)構(gòu)就可以到最后判斷子進程是什么情況了。即非阻塞等待的時候+循環(huán)=非阻塞輪詢。

在非阻塞等待時,父進程可以在每次查看子進程的間隙做其他事情。

pid_ t waitpid(pid_t pid, int *status, int options);

pid_t >0 :等待成功,子進程退出了,并且父進程回收成功

pid_t <0 :等待失敗了

pid_t =0 :檢測是成功的,只不過子進程還沒退出,需要下一次進行重復(fù)等待。

柚子快報邀請碼778899分享:運維 【Linux】進程控制

http://yzkb.51969.com/

好文鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19517198.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄