//
// Created by hsj on 2024-1-9.
// 杀死僵尸进程
// ****************************************************僵尸进程定义***************************************************
// “应该向创建子进程的父进程传递子进程的exit参数值或return语句的返回值。”
// 如何向父进程传递这些值呢?操作系统不会主动把这些值传递给父进程。
// 只有父进程主动发起请求(函数调用)时,操作系统才会传递该值。
// 换言之,如果父进程未主动要求获得子进程的结束状态值,操作系统将-直保存, 并让子进程长时间处于僵尸进程状态。
// 也就是说,父母要负责收回自己生的孩子(也许这种描述有些不妥)。
// ****************************************************僵尸进程定义[结束]***************************************************
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
//防止僵尸进程,
void read_childproc(int sig);
int main(void)
{
int i = 0;
printf("i son/pa ppid pid fpid\n");
/**
* struct sigaction
{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
}
此结构体的sa_handler成 员保存信号处理函数的指针值(地址值)。
sa_mask和sa_flags的所有位均初始化为0即可。这2个成员用于指定信号相关的选项和特性,而我们的目的主要是防止产生僵尸进程,故省略。
*/
struct sigaction act;
act.sa_handler=read_childproc;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
//注册子进程结束事件
sigaction(SIGCHLD,&act, 0);
//ppid指当前进程的父进程pid
//pid指当前进程的pid,
//fpid指fork返回给当前进程的值
for (i = 0; i < 2; i++)
{
pid_t fpid = fork();
if (fpid == 0)
{
printf("%d child %4d %4d %4d\n", i, getppid(), getpid(), fpid);
return 0;
}
else
{
printf("%d parent %4d %4d %4d\n", i, getppid(), getpid(), fpid);
}
// sleep(3); //3 sec
}
return 0;
}
void read_childproc(int sig){
pid_t pid;
int status;
//非阻塞式退出进程
//waitpid第一个参数:等待终止的目标子进程的ID,若传递-1,则与wait函数相同,可以等待任意子进程终止。
pid=waitpid(-1, &status, WNOHANG);
if(WIFEXITED(status)){//检测退出了吗
//printf("signal: Removed Child proc id: %d \n", pid);
//printf("signal: Child proc return/back value: %d \n", WEXITSTATUS(status));//获取退出的子进程的退出码/返回值
}
}