Linux使用waitpid回收多個(gè)子進(jìn)程的方法小結(jié)
什么是waitpid
waitpid是Unix/Linux系統(tǒng)提供的一個(gè)系統(tǒng)調(diào)用,用于等待子進(jìn)程的狀態(tài)改變并回收其資源。相比于wait函數(shù),waitpid提供了更靈活的控制選項(xiàng),可以指定等待哪個(gè)特定的子進(jìn)程,以及是否阻塞等待【1†source】。
#include <sys/wait.h> pid_t waitpid(pid_t pid, int *status, int options);
參數(shù)說明:
pid: 要等待的子進(jìn)程ID。特殊值包括:
- -1: 等待任意子進(jìn)程
- 0: 等待與調(diào)用進(jìn)程同組的任意子進(jìn)程
0: 等待指定PID的子進(jìn)程
- status: 用于存儲(chǔ)子進(jìn)程退出狀態(tài)的指針
- options: 控制選項(xiàng),最常用的是WNOHANG,表示非阻塞模式
回收多個(gè)子進(jìn)程的方法
方法一:循環(huán)調(diào)用waitpid
最簡(jiǎn)單的方法是在父進(jìn)程中循環(huán)調(diào)用waitpid,直到所有子進(jìn)程都被回收:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main() {
pid_t pids[5];
int i;
// 創(chuàng)建5個(gè)子進(jìn)程
for (i = 0; i < 5; i++) {
pids[i] = fork();
if (pids[i] == 0) {
// 子進(jìn)程代碼
printf("Child process %d started\n", getpid());
sleep(1 + rand() % 3); // 隨機(jī)休眠1-3秒
printf("Child process %d exiting\n", getpid());
exit(0);
}
}
// 父進(jìn)程回收子進(jìn)程
int status;
pid_t pid;
for (i = 0; i < 5; i++) {
pid = waitpid(pids[i], &status, 0);
if (pid == -1) {
perror("waitpid");
exit(1);
}
printf("Parent reaped child %d\n", pid);
}
return 0;
}
方法二:非阻塞方式回收子進(jìn)程
使用WNOHANG選項(xiàng),父進(jìn)程可以在不阻塞的情況下檢查子進(jìn)程狀態(tài):
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main() {
pid_t pids[5];
int i;
// 創(chuàng)建5個(gè)子進(jìn)程
for (i = 0; i < 5; i++) {
pids[i] = fork();
if (pids[i] == 0) {
// 子進(jìn)程代碼
printf("Child process %d started\n", getpid());
sleep(1 + rand() % 3); // 隨機(jī)休眠1-3秒
printf("Child process %d exiting\n", getpid());
exit(0);
}
}
// 父進(jìn)程非阻塞方式回收子進(jìn)程
int status;
pid_t pid;
int children_left = 5;
while (children_left > 0) {
pid = waitpid(-1, &status, WNOHANG);
if (pid > 0) {
// 成功回收一個(gè)子進(jìn)程
printf("Parent reaped child %d\n", pid);
children_left--;
} else if (pid == 0) {
// 有子進(jìn)程仍在運(yùn)行
printf("Waiting for children to finish...\n");
sleep(1);
} else {
// 出錯(cuò)
perror("waitpid");
exit(1);
}
}
printf("All children have been reaped\n");
return 0;
}
方法三:信號(hào)處理方式回收子進(jìn)程
可以通過SIGCHLD信號(hào)來(lái)通知父進(jìn)程子進(jìn)程已經(jīng)終止,然后在信號(hào)處理函數(shù)中回收子進(jìn)程:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>
void sigchld_handler(int sig) {
int status;
pid_t pid;
// 回收所有已終止的子進(jìn)程
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
printf("Parent reaped child %d\n", pid);
}
}
int main() {
pid_t pids[5];
int i;
// 設(shè)置SIGCHLD信號(hào)處理
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
// 創(chuàng)建5個(gè)子進(jìn)程
for (i = 0; i < 5; i++) {
pids[i] = fork();
if (pids[i] == 0) {
// 子進(jìn)程代碼
printf("Child process %d started\n", getpid());
sleep(1 + rand() % 3); // 隨機(jī)休眠1-3秒
printf("Child process %d exiting\n", getpid());
exit(0);
}
}
// 父進(jìn)程繼續(xù)執(zhí)行其他任務(wù)
printf("Parent doing other work...\n");
sleep(5);
printf("Parent finished\n");
return 0;
}
最佳實(shí)踐和注意事項(xiàng)
- 及時(shí)回收子進(jìn)程:父進(jìn)程應(yīng)該及時(shí)回收子進(jìn)程,避免僵尸進(jìn)程的產(chǎn)生【2†source】。
- 處理異常情況:在調(diào)用waitpid時(shí),應(yīng)該檢查返回值,處理可能的錯(cuò)誤情況。
- 信號(hào)處理注意事項(xiàng):使用信號(hào)處理方式回收子進(jìn)程時(shí),需要注意信號(hào)處理函數(shù)的可重入性和安全性。
- 避免競(jìng)爭(zhēng)條件:在多線程環(huán)境中使用waitpid時(shí),需要注意同步問題,避免競(jìng)爭(zhēng)條件。
- 使用WNOHANG:對(duì)于需要同時(shí)處理多個(gè)任務(wù)的父進(jìn)程,使用WNOHANG選項(xiàng)可以避免阻塞,提高程序的響應(yīng)性【3†source】。
總結(jié)
waitpid是Unix/Linux系統(tǒng)中回收子進(jìn)程的強(qiáng)大工具,通過合理使用waitpid及其選項(xiàng),父進(jìn)程可以有效地管理多個(gè)子進(jìn)程。本文介紹了三種常見的回收多個(gè)子進(jìn)程的方法,包括循環(huán)調(diào)用、非阻塞方式和信號(hào)處理方式,并提供了相應(yīng)的代碼示例。根據(jù)具體的應(yīng)用場(chǎng)景和需求,選擇最適合的方法來(lái)管理子進(jìn)程,可以提高程序的健壯性和效率。
在實(shí)際開發(fā)中,還需要考慮程序的錯(cuò)誤處理、資源釋放和信號(hào)安全等問題,確保程序在各種情況下都能正確運(yùn)行。
以上就是Linux使用waitpid回收多個(gè)子進(jìn)程的方法小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Linux waitpid回收多個(gè)子進(jìn)程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Linux文件編輯命令vi詳細(xì)整理(總結(jié))
本篇文章主要介紹了Linux文件編輯命令詳細(xì)整理(總結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-07-07
Apache中配置SSLCache實(shí)現(xiàn)分布式環(huán)境下的會(huì)話共享
本文主要介紹了Apache中配置SSLCache實(shí)現(xiàn)分布式環(huán)境下的會(huì)話共享,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-04-04
關(guān)于Read-only file system問題的解決
這篇文章主要介紹了關(guān)于Read-only file system問題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
詳解Win10 Bash/WSL調(diào)試Linux環(huán)境下的.NET Core應(yīng)用程序
本篇文章主要介紹了詳解Win10 Bash/WSL調(diào)試Linux環(huán)境下的.NET Core應(yīng)用程序 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
rsync中文手冊(cè)之使用rsync實(shí)現(xiàn)網(wǎng)站鏡像和備份linux
用rsync實(shí)現(xiàn)網(wǎng)站鏡像和備份 雖然是linux下的操作,但原理和windows下類似2008-09-09
服務(wù)器安裝寶塔面板無(wú)法遠(yuǎn)程連接數(shù)據(jù)庫(kù)的解決方法
這篇文章主要介紹了服務(wù)器安裝寶塔面板無(wú)法遠(yuǎn)程連接數(shù)據(jù)庫(kù)的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Git開發(fā)分支合并到develop分支實(shí)現(xiàn)方式
文章詳細(xì)介紹了如何在Git中將本地開發(fā)分支合并到develop分支,包括創(chuàng)建分支、開發(fā)、提交、切換分支、合并分支、解決沖突以及版本回退等步驟,同時(shí),還提到了一些常用的Git命令和操作,如git reset、git log和git push等2026-01-01

