日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux C :系统调用-fork,wait,subreaper

發(fā)布時(shí)間:2024/10/14 linux 81 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux C :系统调用-fork,wait,subreaper 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ?fork():創(chuàng)建子進(jìn)程,并返回進(jìn)程id。

? ? ?wait(&status):等待子進(jìn)程終止。如果成功則會(huì)返回僵尸子進(jìn)程的pid,status的值會(huì)是子進(jìn)程的exitcode。

? ? ?exit(value):進(jìn)程正常退出,并返回退出值value

? ? ?prctl(PR_SET_CHILD_SUBREAPER):設(shè)置當(dāng)前進(jìn)程為subreaper進(jìn)程。

零、示例代碼即可能的輸出結(jié)果

目錄

一、fork()

二、wait()

三、subreaper

四、解讀上述代碼和輸出結(jié)果


#include <stdio.h> #include <unistd.h> #include <wait.h> #include <sys/prctl.h> int main(){int pid ,r,status ;printf("mark process %d as a subreaper\n",getpid());r=prctl(PR_SET_CHILD_SUBREAPER);pid = fork();if(pid){//parent printf("subreaper %d child =%d\n",getpid(),pid);while(1){pid =wait(&status);if(pid >0){printf("subreaper %d wait a ZOMBIE=%d\n",getpid(),pid);}else{break;}}}else{//childprintf("child %d parent=%d\n",getpid(),(pid_t)getppid());pid=fork();if(pid){printf("child%d start : grandchild=%d\n",getpid(),pid);printf("child%d exit : grandchild=%d\n",getpid(),pid);}else{printf("grandchild%d start : myparent=%d\n",getpid(),getppid());printf("grandchild%d end : myparent=%d\n",getpid(),getppid());}}}

運(yùn)行結(jié)果:(每次運(yùn)行可能順序不一樣)

? ? ? 在Linux 中,每個(gè)用戶在同一時(shí)間只能有一定數(shù)量的進(jìn)程。用戶資源限制文件通常在/etc/security/limits.conf 文件中設(shè)置。進(jìn)程有兩種執(zhí)行狀態(tài),一種是內(nèi)核態(tài),一種是用戶態(tài)。每個(gè)進(jìn)程都在內(nèi)核中下產(chǎn)生并開(kāi)始執(zhí)行,想調(diào)用硬件設(shè)備例如操作CPU,鍵盤(pán),或者想執(zhí)行系統(tǒng)調(diào)用都是在內(nèi)核態(tài)下完成的。修改狀態(tài)寄存器的值就可以從內(nèi)核態(tài)轉(zhuǎn)化為用戶態(tài)。一旦轉(zhuǎn)為用戶態(tài),那么就無(wú)法直接訪問(wèn)硬件相關(guān)的設(shè)備,想要重新轉(zhuǎn)為內(nèi)核態(tài)只有3種方式:硬件中斷,異常,系統(tǒng)調(diào)用。 可以說(shuō),內(nèi)核是操作系統(tǒng)之下的部分,用戶是操作系統(tǒng)之上的部分。用戶只需關(guān)心操作系統(tǒng)為用戶提供了哪些可訪問(wèn)內(nèi)核的接口就行。

? ? ? 在內(nèi)核模式中,每個(gè)進(jìn)程都有完全相同的代碼段,數(shù)據(jù)段和堆,但是每個(gè)進(jìn)程都有只屬于自己的棧。

一、fork()

? ? ?創(chuàng)建子進(jìn)程并返回子進(jìn)程的pid , int pid = fork();? ?如果fork失敗則為-1。當(dāng)創(chuàng)建了子進(jìn)程后,子進(jìn)程和父進(jìn)程在用戶態(tài)的映像完全相同,但是在內(nèi)核態(tài)下的映像只有棧有區(qū)別,意味著子進(jìn)程和父進(jìn)程有相同的代碼和數(shù)據(jù)。因?yàn)閯?chuàng)建子進(jìn)程時(shí)用戶態(tài)的棧也是一樣的,意味著棧幀情況也是一樣的。創(chuàng)建完后子進(jìn)程和父進(jìn)程都從fork()后繼續(xù)執(zhí)行.fork()方法調(diào)用了內(nèi)核中kfork()函數(shù),它對(duì)創(chuàng)建出來(lái)的子進(jìn)程返回是0,父進(jìn)程返回值是子進(jìn)程的進(jìn)程號(hào);

int pid =fork(); if(pid=-1){//父進(jìn)程創(chuàng)建子進(jìn)程失敗的分支 }else if(pid ==0){//子進(jìn)程執(zhí)行的分支,因?yàn)樽舆M(jìn)程返回的pid是0 }else {//父進(jìn)程執(zhí)行的分支,pid是子進(jìn)程的id }

二、wait()

? ? ? ?等待僵尸子進(jìn)程。所謂的僵尸進(jìn)程,就是程序已經(jīng)結(jié)束但是資源未釋放的進(jìn)程。wait除了返回僵尸子進(jìn)程的id,獲取子進(jìn)程的退出狀態(tài),還會(huì)釋放僵尸子進(jìn)程。wait系統(tǒng)調(diào)用將調(diào)用內(nèi)核中的kwait函數(shù)

三、subreaper

進(jìn)程可以用系統(tǒng)調(diào)用定義自己為subreaper進(jìn)程:

prctl(PR_SET_CHILD_SUBREAPER);

? ? ? 如果子進(jìn)程的父進(jìn)程先死亡,那么該子進(jìn)程就會(huì)成為一個(gè)孤兒進(jìn)程。在Linux中,標(biāo)記為subreaper的祖先進(jìn)程會(huì)成為該孤兒的父進(jìn)程,否則將成為P1進(jìn)程子進(jìn)程。(P1進(jìn)程是操作系統(tǒng)初始化的進(jìn)程,除P0和P1進(jìn)程,其他所有進(jìn)程都是P1進(jìn)程的子孫進(jìn)程)。不過(guò)要注意的是,當(dāng)P1清理重定父級(jí)進(jìn)程時(shí),會(huì)丟失關(guān)于子進(jìn)程的所有信息。P1因?yàn)檫M(jìn)程等級(jí)高,當(dāng)P1作為孤兒進(jìn)程的父進(jìn)程時(shí)服務(wù)管理器不能再?gòu)姆?wù)守護(hù)進(jìn)程中接收SIGCHLD信號(hào),也不能等待任何僵尸子進(jìn)程。定義subreaper就可以很好的解決上述問(wèn)題,并且可以有效地減少P1進(jìn)程的工作量。

顯示當(dāng)前用戶的subreaper 進(jìn)程的PID 和信息:

? ? ?ps fxau | grep USERNAME | grep "/sbin/upstart"

四、解讀上述代碼和輸出結(jié)果

? 就運(yùn)行結(jié)果而言,

1)當(dāng)fork創(chuàng)建出來(lái)子進(jìn)程后,父進(jìn)程獲取到CPU使用權(quán)先執(zhí)行,并打印出了

? ? ??

? ? ? 然后進(jìn)入while循環(huán)等待子進(jìn)程執(zhí)行結(jié)束。

2)接下來(lái)子進(jìn)程執(zhí)行并打印出了,

? ? ??

? ? ?之后子進(jìn)程 fork 創(chuàng)建出了一個(gè)子進(jìn)程的子進(jìn)程即孫子進(jìn)程。

3)子進(jìn)程先執(zhí)行完畢,并打印出:

? ? ??

? ? ? 此時(shí),子進(jìn)程執(zhí)行完畢但是未釋放進(jìn)程資源,于是成為了僵尸進(jìn)程。

4)此時(shí)父進(jìn)程獲取到CPU使用權(quán),通過(guò)wait返回子進(jìn)程的pid,繼續(xù)執(zhí)行打印出了??

? ? ?

? ? ?wait釋放了子進(jìn)程的資源,使孫子進(jìn)程成為了孤兒進(jìn)程,但是由于之前父進(jìn)程(pid=3434)將自己設(shè)置成了PR_SET_CHILD_SUBREAPER? , 使 孫子進(jìn)程(pid=3436)的父親不再是已經(jīng)死亡的(pid=3435),而是父進(jìn)程(pid=3434)。

5)所以當(dāng)孫子執(zhí)行完自己的代碼后,打印出

? ? ?成為了僵尸進(jìn)程后,被父進(jìn)程 wait() 釋放出來(lái),打印出

? ? 后結(jié)束。

與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Linux C :系统调用-fork,wait,subreaper的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。