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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

进程之父子进程的关系

發(fā)布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程之父子进程的关系 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)載:https://blog.csdn.net/qq_28840229/article/details/79844763

fork之后:

父子相同處: 全局變量、.data、.text、棧、堆、環(huán)境變量、用戶ID、宿主目錄、進(jìn)程工作目錄、信號處理方式...

父子不同處: 1.進(jìn)程ID ??2.fork返回值 ??3.父進(jìn)程ID ???4.進(jìn)程運(yùn)行時間 ???5.鬧鐘(定時器) ??6.未決信號集

似乎,子進(jìn)程復(fù)制了父進(jìn)程0-3G用戶空間內(nèi)容,以及父進(jìn)程的PCB,但pid不同。真的每fork一個子進(jìn)程都要將父進(jìn)程的0-3G地址空間完全拷貝一份,然后在映射至物理內(nèi)存嗎?

當(dāng)然不是!父子進(jìn)程間遵循讀時共享寫時復(fù)制的原則。這樣設(shè)計(jì),無論子進(jìn)程執(zhí)行父進(jìn)程的邏輯還是執(zhí)行自己的邏輯都能節(jié)省內(nèi)存開銷。

1、fork函數(shù)時調(diào)用一次,返回兩次。在父進(jìn)程和子進(jìn)程中各調(diào)用一次。子進(jìn)程中返回值為0,父進(jìn)程中返回值為子進(jìn)程的PID。程序員可以根據(jù)返回值的不同讓父進(jìn)程和子進(jìn)程執(zhí)行不同的代碼。子進(jìn)程是父進(jìn)程的副本,獲得了父進(jìn)程數(shù)據(jù)空間、堆和棧的副本;父子進(jìn)程并不共享這些存儲空間,共享正文段(即代碼段);因此子進(jìn)程對變量的所做的改變并不會影響父進(jìn)程。一般來說,fork之后父、子進(jìn)程執(zhí)行順序是不確定的,這取決于內(nèi)核調(diào)度算法。進(jìn)程之間實(shí)現(xiàn)同步需要進(jìn)行進(jìn)程通信。

子進(jìn)程對數(shù)據(jù)進(jìn)行減一操作,父進(jìn)程做加一操作:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
?
int main()
{
?pid_t pid;
?char *message;
?int n = 0;
?pid = fork();
?while(1){
?if(pid < 0){
?perror("fork failed\n");
?exit(1);
?}
?else if(pid == 0){
?n--;
?printf("child's n is:%d\n",n);
?}
?else{
?n++;
?printf("parent's n is:%d\n",n);
?}
?sleep(1);
?}
?exit(0);
}


2、進(jìn)程等待

孤兒進(jìn)程:?父進(jìn)程生成子進(jìn)程,但是父進(jìn)程比子進(jìn)程先結(jié)束;子進(jìn)程會變成孤兒進(jìn)程,由系統(tǒng)1號init 進(jìn)程進(jìn)行接管。init 進(jìn)程接管后,在該孤兒進(jìn)程結(jié)束的時候,負(fù)責(zé)“收尸”,回收系統(tǒng)資源及進(jìn)程信息。

僵尸進(jìn)程:子進(jìn)程已經(jīng)退出,但是沒有父進(jìn)程回收它的資源(父進(jìn)程生成的子進(jìn)程,但是子進(jìn)程比父進(jìn)程先掛掉,如果父進(jìn)程沒有收回它的資源時,那么子進(jìn)程掛掉后就變成了僵尸進(jìn)程;應(yīng)該盡量避免產(chǎn)生僵尸進(jìn)程,可以在父進(jìn)程調(diào)用wait 或者waitpid 進(jìn)程回收)。

進(jìn)程一旦調(diào)用了wait,就立即阻塞自己,由wait 自動分析是否當(dāng)前進(jìn)程的某個子進(jìn)程已經(jīng)退出。如果讓它找到了這樣一個已經(jīng)變成僵尸的子進(jìn)程,wait 就會收集這個子進(jìn)程的信息,并把它徹底銷毀后返回;如果沒有找到這樣一個子進(jìn)程,wait 就會一直阻塞在這里,直到有一個出現(xiàn)為止。

補(bǔ)充:


進(jìn)程0

內(nèi)核是一個大的程序,可以控制硬件,也可以創(chuàng)建、運(yùn)行、終止、控制所有的進(jìn)程。當(dāng)內(nèi)核被加載到內(nèi)存后,首先就會有完成內(nèi)核初始化的函數(shù)start_kernel()從無到有的創(chuàng)建一個內(nèi)核線程swap,并設(shè)置其PID為0,即進(jìn)程0;它也叫閑逛進(jìn)程;進(jìn)程0執(zhí)行的是cpu_idle()函數(shù),該函數(shù)僅有一條hlt匯編指令,就是在系統(tǒng)閑置時用來降低電力的使用和減少熱的產(chǎn)生。同時進(jìn)程0的PCB叫做init_task,在很多鏈表中起了表頭的作用。

當(dāng)就緒隊(duì)列中再沒有其他進(jìn)程時,閑逛進(jìn)程就會被調(diào)度程序選中,以此來省電,減少熱量的產(chǎn)生。

進(jìn)程1

即init進(jìn)程。首先內(nèi)核線程kernel_init執(zhí)行內(nèi)核的一些初始化函數(shù),以將內(nèi)核初始化。那么此內(nèi)核態(tài)的線程又是怎樣變?yōu)橐粋€用戶進(jìn)程的?實(shí)際上,kernel_int()內(nèi)核函數(shù)中調(diào)用了execve()系統(tǒng)調(diào)用,該系統(tǒng)調(diào)用裝入用戶態(tài)下的一個可執(zhí)行程序init,從而啟動用戶進(jìn)程init進(jìn)程。注意,內(nèi)核函數(shù)kernel_init()與用戶態(tài)下的可執(zhí)行文件init是不同的,位置不同,運(yùn)行狀態(tài)不同,代碼也不同。init進(jìn)程只是內(nèi)核線程kernel_init啟動起來的一個普通的用戶進(jìn)程,當(dāng)然也是用戶態(tài)下的第一個進(jìn)程,并且init進(jìn)程從不終止,用來創(chuàng)建和監(jiān)控操作系統(tǒng)外層的所有進(jìn)程的活動。


3、父進(jìn)程創(chuàng)建多個子進(jìn)程問題

void createsubprocess(int num) ?
{ ?
? ? pid_t pid; ?
? ? int i; ?
? ? for(i=0;i<num;i++) ?
? ? { ?
? ? ? ? pid=fork(); ?
? ? ? ? if(pid==0||pid==-1) ?//子進(jìn)程或創(chuàng)建進(jìn)程失敗均退出,這里是關(guān)鍵所在,子進(jìn)程中跳出循環(huán)。
? ? ? ? { ?
? ? ? ? ? ? break; ?
? ? ? ? } ?
? ? } ?
? ? if(pid==-1) ?
? ? { ?
? ? ? ? perror("fail to fork!\n"); ?
? ? ? ? exit(1); ?
? ? } ?
? ? else if(pid==0) ?
? ? { ?
? ? ? ? printf("子進(jìn)程id=%d,其對應(yīng)的父進(jìn)程id=%d\n",getpid(),getppid()); ?
? ? ? ? exit(0); ?
? ? } ?
? ? else?
? ? { ?
? ? ? ? printf("父進(jìn)程id=%d\n",getpid()); ?
? ? ? ? exit(0); ?
? ? } ?
}

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的进程之父子进程的关系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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