Linux使用waitpid回收多個子進程的方法小結(jié)
什么是waitpid
waitpid是Unix/Linux系統(tǒng)提供的一個系統(tǒng)調(diào)用,用于等待子進程的狀態(tài)改變并回收其資源。相比于wait函數(shù),waitpid提供了更靈活的控制選項,可以指定等待哪個特定的子進程,以及是否阻塞等待【1†source】。
#include <sys/wait.h> pid_t waitpid(pid_t pid, int *status, int options);
參數(shù)說明:
pid: 要等待的子進程ID。特殊值包括:
- -1: 等待任意子進程
- 0: 等待與調(diào)用進程同組的任意子進程
0: 等待指定PID的子進程
- status: 用于存儲子進程退出狀態(tài)的指針
- options: 控制選項,最常用的是WNOHANG,表示非阻塞模式
回收多個子進程的方法
方法一:循環(huán)調(diào)用waitpid
最簡單的方法是在父進程中循環(huán)調(diào)用waitpid,直到所有子進程都被回收:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main() {
pid_t pids[5];
int i;
// 創(chuàng)建5個子進程
for (i = 0; i < 5; i++) {
pids[i] = fork();
if (pids[i] == 0) {
// 子進程代碼
printf("Child process %d started\n", getpid());
sleep(1 + rand() % 3); // 隨機休眠1-3秒
printf("Child process %d exiting\n", getpid());
exit(0);
}
}
// 父進程回收子進程
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;
}
方法二:非阻塞方式回收子進程
使用WNOHANG選項,父進程可以在不阻塞的情況下檢查子進程狀態(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個子進程
for (i = 0; i < 5; i++) {
pids[i] = fork();
if (pids[i] == 0) {
// 子進程代碼
printf("Child process %d started\n", getpid());
sleep(1 + rand() % 3); // 隨機休眠1-3秒
printf("Child process %d exiting\n", getpid());
exit(0);
}
}
// 父進程非阻塞方式回收子進程
int status;
pid_t pid;
int children_left = 5;
while (children_left > 0) {
pid = waitpid(-1, &status, WNOHANG);
if (pid > 0) {
// 成功回收一個子進程
printf("Parent reaped child %d\n", pid);
children_left--;
} else if (pid == 0) {
// 有子進程仍在運行
printf("Waiting for children to finish...\n");
sleep(1);
} else {
// 出錯
perror("waitpid");
exit(1);
}
}
printf("All children have been reaped\n");
return 0;
}
方法三:信號處理方式回收子進程
可以通過SIGCHLD信號來通知父進程子進程已經(jīng)終止,然后在信號處理函數(shù)中回收子進程:
#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;
// 回收所有已終止的子進程
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個子進程
for (i = 0; i < 5; i++) {
pids[i] = fork();
if (pids[i] == 0) {
// 子進程代碼
printf("Child process %d started\n", getpid());
sleep(1 + rand() % 3); // 隨機休眠1-3秒
printf("Child process %d exiting\n", getpid());
exit(0);
}
}
// 父進程繼續(xù)執(zhí)行其他任務(wù)
printf("Parent doing other work...\n");
sleep(5);
printf("Parent finished\n");
return 0;
}
最佳實踐和注意事項
- 及時回收子進程:父進程應(yīng)該及時回收子進程,避免僵尸進程的產(chǎn)生【2†source】。
- 處理異常情況:在調(diào)用waitpid時,應(yīng)該檢查返回值,處理可能的錯誤情況。
- 信號處理注意事項:使用信號處理方式回收子進程時,需要注意信號處理函數(shù)的可重入性和安全性。
- 避免競爭條件:在多線程環(huán)境中使用waitpid時,需要注意同步問題,避免競爭條件。
- 使用WNOHANG:對于需要同時處理多個任務(wù)的父進程,使用WNOHANG選項可以避免阻塞,提高程序的響應(yīng)性【3†source】。
總結(jié)
waitpid是Unix/Linux系統(tǒng)中回收子進程的強大工具,通過合理使用waitpid及其選項,父進程可以有效地管理多個子進程。本文介紹了三種常見的回收多個子進程的方法,包括循環(huán)調(diào)用、非阻塞方式和信號處理方式,并提供了相應(yīng)的代碼示例。根據(jù)具體的應(yīng)用場景和需求,選擇最適合的方法來管理子進程,可以提高程序的健壯性和效率。
在實際開發(fā)中,還需要考慮程序的錯誤處理、資源釋放和信號安全等問題,確保程序在各種情況下都能正確運行。
以上就是Linux使用waitpid回收多個子進程的方法小結(jié)的詳細內(nèi)容,更多關(guān)于Linux waitpid回收多個子進程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在linunx系統(tǒng)中搭建靜態(tài)文件服務(wù)的流程步驟
在服務(wù)器上有一些文件,想共享給其他用戶下載,同時因為ftp和sftp被禁用,且使用起來不太方便,需要找一種搭建成本低,安全高效的方式來完成此功能,因此linux上的httpd服務(wù)是一個很好的選擇,所以本文給大家介紹了在linux系統(tǒng)中搭建靜態(tài)文件服務(wù)的流程步驟2024-02-02
使用Apache commons-cli包進行命令行參數(shù)解析的示例代碼
Apache的commons-cli包是專門用于解析命令行參數(shù)格式的包。這篇文章給大家介紹使用Apache commons-cli包進行命令行參數(shù)解析的示例代碼,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05

