C語(yǔ)言多進(jìn)程創(chuàng)建和回收的實(shí)現(xiàn)實(shí)例
一、多進(jìn)程創(chuàng)建和回收
- 孤兒進(jìn)程:父進(jìn)程先退出了,子進(jìn)程沒有退出,成為孤兒進(jìn)程,父進(jìn)程變成1號(hào)進(jìn)程。
- 僵尸進(jìn)程:父進(jìn)程沒有退出,子進(jìn)程退出了,但是父進(jìn)程沒有回收子進(jìn)程資源,導(dǎo)致子進(jìn)程變成僵尸進(jìn)程。
1. fork()
創(chuàng)建子進(jìn)程函數(shù),一個(gè)進(jìn)程可以創(chuàng)建多個(gè)子進(jìn)程。
pid_t fork(void)
返回值
小于0 創(chuàng)建失敗
等于0 是子進(jìn)程
大于0 是父進(jìn)程示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
pid_t ret = fork();
if (ret < 0)
{
perror("fork error");
return -1;
}
else if (ret > 0)
{
printf("here is father,pid is [%d], child pid is [%d]\n", getpid(), ret);
sleep(1);
}
else if (ret == 0)
{
printf("here is child pid is [%d],father is [%d]\n", getpid(), getppid());
}
return 0;
}2. wait()
父進(jìn)程回收子進(jìn)程,其中分為wait()和waitpid()函數(shù)
pid_t wait(int *status);
返回值
大于0 返回值為回收的進(jìn)程id
返回-1 回收失敗
參數(shù) status 進(jìn)程回收狀態(tài)
可以使用下面的宏來(lái)說(shuō)明當(dāng)前的回收狀態(tài)
WIFEXITED(wstatus) 如果正常返回,返回true
WEXITSTATUS(wstatus) 用于輸出正常返回的狀態(tài) 用 %d 格式化輸出
WIFSIGNALED(wstatus) 如果被信號(hào)殺死,返回true
WTERMSIG(wstatus) 用于輸出被哪個(gè)信號(hào)殺死 用 %d 格式化輸出
WIFSTOPPED(wstatus) 如果子進(jìn)程停止了,返回true
WSTOPSIG(wstatus) 用于輸出進(jìn)程停止是由于哪個(gè)信號(hào)
WIFCONTINUED(wstatus) 如果進(jìn)程被信號(hào)SIGCONT重啟,返回true
WCOREDUMP(wstatus) 如果子進(jìn)程發(fā)生核心轉(zhuǎn)儲(chǔ),返回true
示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// pid_t wait(int *status);
int main()
{
pid_t ret = fork();
if (ret < 0)
{
perror("fork error");
return -1;
}
else if (ret > 0)
{
int waitstatus;
printf("here is father,pid is [%d], child pid is [%d]\n", getpid(), ret);
pid_t waitid = wait(&waitstatus);
if (waitid == -1)
{
perror("wait error");
return -1;
}
else if (waitid > 0)
{
printf("child pid [%d] is over\n", waitid);
}
if (WIFEXITED(waitstatus))
{
printf("exited, status=%d\n", WEXITSTATUS(waitstatus));
}
else if (WIFSIGNALED(waitstatus))
{
printf("killed by signal %d\n", WTERMSIG(waitstatus));
}
else if (WIFSTOPPED(waitstatus))
{
printf("stopped by signal %d\n", WSTOPSIG(waitstatus));
}
else if (WIFCONTINUED(waitstatus))
{
printf("continued\n");
}
}
else if (ret == 0)
{
printf("here is child pid is [%d],father is [%d]\n", getpid(), getppid());
}
return 0;
}
//輸出
here is father,pid is [24290], child pid is [24291]
here is child pid is [24291],father is [24290]
child pid [24291] is over
exited, status=03. waitpid()
waitpid中的第三個(gè)參數(shù)可以讓回收進(jìn)程變成非阻塞的。
pid_t waitpid(pid_t pid, int *status, int options);
返回值
大于0 成功,返回的是回收的進(jìn)程id
等于0 返回0是因?yàn)榈谌齻€(gè)參數(shù)設(shè)置為了 WNOHANG ,等待是非阻塞的,并且這個(gè)時(shí)候沒有子進(jìn)程需要被回收
小于0 回收失敗
參數(shù) pid 進(jìn)程id
小于-1 :等待該數(shù)字絕對(duì)值的所在組所有子進(jìn)程,例如-21328,則等待21328組內(nèi)所有子進(jìn)程
-1 :等待所有子進(jìn)程
0 :等待組ID等于調(diào)用進(jìn)程的組ID的子進(jìn)程
大于0 :等待某個(gè)子進(jìn)程
參數(shù) status 進(jìn)程回收狀態(tài)
同wait函數(shù)的
參數(shù) options 回收選項(xiàng)
0 :不添加選項(xiàng)
WNOHANG :如果沒有子進(jìn)程需要被回收,就立即返回
WUNTRACED :如果一個(gè)子進(jìn)程被停止了,就返回
WCONTINUED :如果一個(gè)子進(jìn)程被SIGCONT從停止轉(zhuǎn)變?yōu)檫\(yùn)行,就返回
示例:
創(chuàng)建多個(gè)子進(jìn)程并回收它們
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// pid_t waitpid(pid_t pid, int *status, int options);
int main()
{
int i = 0;
for (i = 0; i < 3; i++)
{
pid_t ret = fork();
if (ret < 0)
{
perror("fork error");
return -1;
}
else if (ret > 0)
{
printf("here is father,pid is [%d], child pid is [%d]\n", getpid(), ret);
// pid_t waitid = wait(&waitstatus);
}
else if (ret == 0)
{
sleep(3);
printf("here is child [%d] pid is [%d],father is [%d]\n", i, getpid(), getppid());
break;
}
}
if (i == 3)
{
int waitstatus;
int num = 0;
do
{
pid_t waitid = waitpid(-1, &waitstatus, WNOHANG);
if (waitid == -1)
{
perror("wait error");
return -1;
}
else if (waitid > 0)
{
printf("child pid [%d] is over\n", waitid);
num++;
}
else if (waitid == 0)
{
// 沒有進(jìn)程被回收,可以做其他事情
sleep(1);
continue;
}
if (WIFEXITED(waitstatus))
{
printf("[%d] exited, status=%d\n", waitid, WEXITSTATUS(waitstatus));
}
else if (WIFSIGNALED(waitstatus))
{
printf("[%d] killed by signal %d\n", waitid, WTERMSIG(waitstatus));
}
else if (WIFSTOPPED(waitstatus))
{
printf("[%d] stopped by signal %d\n", waitid, WSTOPSIG(waitstatus));
}
else if (WIFCONTINUED(waitstatus))
{
printf("[%d] continued\n", waitid);
}
if (num == i)
{
break;
}
} while (1);
}
return 0;
}
//輸出
here is father,pid is [24553], child pid is [24554]
here is father,pid is [24553], child pid is [24555]
here is father,pid is [24553], child pid is [24556]
here is child [0] pid is [24554],father is [24553]
here is child [2] pid is [24556],father is [24553]
here is child [1] pid is [24555],father is [24553]
child pid [24554] is over
[24554] exited, status=0
child pid [24555] is over
[24555] exited, status=0
child pid [24556] is over
[24556] exited, status=0到此這篇關(guān)于C語(yǔ)言多進(jìn)程創(chuàng)建和回收的實(shí)現(xiàn)實(shí)例的文章就介紹到這了,更多相關(guān)C語(yǔ)言多進(jìn)程創(chuàng)建回收內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++分析構(gòu)造函數(shù)與析造函數(shù)的特點(diǎn)梳理
本文對(duì)類的構(gòu)造函數(shù)和析構(gòu)函數(shù)進(jìn)行總結(jié),主要包括了構(gòu)造函數(shù)的初始化、重載、使用參數(shù)和默認(rèn)參數(shù),拷貝構(gòu)造函數(shù)和析構(gòu)函數(shù),希望能幫助讀者在程序開發(fā)中更好的理解類,屬于C/C++基礎(chǔ)2022-05-05
c++中cin/cout與scanf/printf的區(qū)別比較
這篇文章主要介紹了c++中cin/cout與scanf/printf的區(qū)別比較,需要的朋友可以參考下2017-06-06
C語(yǔ)言用棧實(shí)現(xiàn)十進(jìn)制轉(zhuǎn)換為二進(jìn)制的方法示例
這篇文章主要介紹了C語(yǔ)言用棧實(shí)現(xiàn)十進(jìn)制轉(zhuǎn)換為二進(jìn)制的方法,結(jié)合實(shí)例形式分析了C語(yǔ)言棧的定義及進(jìn)制轉(zhuǎn)換使用技巧,需要的朋友可以參考下2017-06-06
C++實(shí)現(xiàn)神經(jīng)BP神經(jīng)網(wǎng)絡(luò)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)神經(jīng)BP神經(jīng)網(wǎng)絡(luò),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05
關(guān)于C語(yǔ)言中弱符號(hào)與弱引用的實(shí)際應(yīng)用問題
在編碼過程中,我們經(jīng)常遇到符號(hào)重定義的錯(cuò)誤問題,本文通過實(shí)例代碼展示給大家介紹了C語(yǔ)言弱符號(hào)與弱引用的實(shí)際應(yīng)用問題,一起看看吧2021-09-09

