/*
* main.c
* 子進程狀態改變會發送SIGCHLD信號給父進程
* 此處實現父進程創建並回收多個子進程
* Created on: 2020年3月3日
* Author: LuYonglei
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#define MY_PROCESS_COUNT 10
void child_catch(int signalNumber) {
//子進程狀態發生改變時,內核對信號作處理的回調函數
int w_status;
pid_t w_pid;
while ((w_pid = waitpid(-1, &w_status, WNOHANG)) != -1 && w_pid != 0) {
if (WIFEXITED(w_status)) //判斷子進程是否正常退出
printf("---catch pid %d,return value %d\n", w_pid, WEXITSTATUS(w_status)); //打印子進程PID和子進程返回值
}
}
int main(int argc, char **argv) {
pid_t pid;
int i;
//在此處阻塞SIGCHLD信號,防止信號處理函數尚未注冊成功就有子進程結束
sigset_t child_sigset;
sigemptyset(&child_sigset); //將child_sigset每一位都設置為0
sigaddset(&child_sigset, SIGCHLD); //添加SIGCHLD位
sigprocmask(SIG_BLOCK, &child_sigset, NULL); //完成父進程阻塞SIGCHLD的設置
for (i = 0; i < MY_PROCESS_COUNT; i++) {
//創建子進程,創建成功就跳出循環
if ((pid = fork()) == 0)
break;
}
if (MY_PROCESS_COUNT == i) { //括號內為父進程代碼
struct sigaction act; //信號回調函數使用的結構體
act.sa_handler = child_catch;
sigemptyset(&(act.sa_mask)); //設置執行信號回調函數時父進程的的信號屏蔽字
act.sa_flags = 0;
sigaction(SIGCHLD, &act, NULL); //給SIGCHLD注冊信號處理函數
//解除SIGCHLD信號的阻塞
sigprocmask(SIG_UNBLOCK, &child_sigset, NULL);
printf("im PARENT ,my pid is %d\n", getpid());
while (1); //父進程堵塞,回收子進程
} else {
//子進程執行代碼
printf("im CHILD ,my pid is %d\n", getpid());
return i;
}
}