Linux使用waitpid回收多個子進(jìn)程的方法小結(jié)
什么是waitpid
waitpid是Unix/Linux系統(tǒng)提供的一個系統(tǒng)調(diào)用,用于等待子進(jìn)程的狀態(tài)改變并回收其資源。相比于wait函數(shù),waitpid提供了更靈活的控制選項(xiàng),可以指定等待哪個特定的子進(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: 用于存儲子進(jìn)程退出狀態(tài)的指針
- options: 控制選項(xiàng),最常用的是WNOHANG,表示非阻塞模式
回收多個子進(jìn)程的方法
方法一:循環(huán)調(diào)用waitpid
最簡單的方法是在父進(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個子進(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個子進(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) {
// 成功回收一個子進(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 {
// 出錯
perror("waitpid");
exit(1);
}
}
printf("All children have been reaped\n");
return 0;
}
方法三:信號處理方式回收子進(jìn)程
可以通過SIGCHLD信號來通知父進(jìn)程子進(jìn)程已經(jīng)終止,然后在信號處理函數(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信號處理
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個子進(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)
- 及時回收子進(jìn)程:父進(jìn)程應(yīng)該及時回收子進(jìn)程,避免僵尸進(jìn)程的產(chǎn)生【2†source】。
- 處理異常情況:在調(diào)用waitpid時,應(yīng)該檢查返回值,處理可能的錯誤情況。
- 信號處理注意事項(xiàng):使用信號處理方式回收子進(jìn)程時,需要注意信號處理函數(shù)的可重入性和安全性。
- 避免競爭條件:在多線程環(huán)境中使用waitpid時,需要注意同步問題,避免競爭條件。
- 使用WNOHANG:對于需要同時處理多個任務(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)程可以有效地管理多個子進(jìn)程。本文介紹了三種常見的回收多個子進(jìn)程的方法,包括循環(huán)調(diào)用、非阻塞方式和信號處理方式,并提供了相應(yīng)的代碼示例。根據(jù)具體的應(yīng)用場景和需求,選擇最適合的方法來管理子進(jìn)程,可以提高程序的健壯性和效率。
在實(shí)際開發(fā)中,還需要考慮程序的錯誤處理、資源釋放和信號安全等問題,確保程序在各種情況下都能正確運(yùn)行。
以上就是Linux使用waitpid回收多個子進(jìn)程的方法小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Linux waitpid回收多個子進(jìn)程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在linunx系統(tǒng)中搭建靜態(tài)文件服務(wù)的流程步驟
在服務(wù)器上有一些文件,想共享給其他用戶下載,同時因?yàn)閒tp和sftp被禁用,且使用起來不太方便,需要找一種搭建成本低,安全高效的方式來完成此功能,因此linux上的httpd服務(wù)是一個很好的選擇,所以本文給大家介紹了在linux系統(tǒng)中搭建靜態(tài)文件服務(wù)的流程步驟2024-02-02
Linux實(shí)現(xiàn)搭建ssh并允許使用root遠(yuǎn)程
這篇文章主要介紹了Linux實(shí)現(xiàn)搭建ssh并允許使用root遠(yuǎn)程方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02
在Linux中使用MD5實(shí)現(xiàn)用戶驗(yàn)證的解決方法
本篇文章小編為大家介紹,在Linux中使用MD5實(shí)現(xiàn)用戶驗(yàn)證的解決方法。需要的朋友參考下2013-04-04
apache的commons-pool2原理與使用實(shí)踐記錄
Apache?Commons?Pool2是一個高效的對象池化框架,通過復(fù)用昂貴資源(如數(shù)據(jù)庫連接、線程、網(wǎng)絡(luò)連接)優(yōu)化系統(tǒng)性能,這篇文章主要介紹了apache的commons-pool2原理與使用詳解,需要的朋友可以參考下2025-05-05
使用Apache commons-cli包進(jìn)行命令行參數(shù)解析的示例代碼
Apache的commons-cli包是專門用于解析命令行參數(shù)格式的包。這篇文章給大家介紹使用Apache commons-cli包進(jìn)行命令行參數(shù)解析的示例代碼,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05

