C语言笔记 -- 处理僵尸进程

调用fork函数创建的子进程的终止方式:1)调用exit函数并使用exit函数传递参数 ;2)main函数中调用return语句并返回值。

fork函数创建的子进程虽然终止了,但是操作系统不会销毁子进程,这样的进程就是僵尸进程。

向exit函数传递的参数值和main函数中return语句的返回值都会传递给操作系统,只有这些值被传递给创建该子进程的父进程,这些终止的子进程才会被销毁。

如果父进程没有主动要求(通过函数调用)获得子进程的结束状态值,操作系统会一直保存,并让子进程长期处于僵尸进程的状态。

如果父进程终止,处于僵尸状态的子进程将同时被销毁。

 

销毁僵尸进程:

1)       pid_t wait(int *statloc);

wait函数将子进程终止时传递的参数值保存到statloc所指向的内存空间。然后通过宏WIFEXITED(status)确定子进程是否正常终止,通过宏WEXITSTATUS获得子进程的返回值。

wait函数的缺点:如果子进程没有终止,wait函数将阻塞直到子进程终止。

如下代码所示,子进程会休眠15s,在这段时间中父进程会阻塞在wait函数上直到子进程返回并终止。

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    pid_t pid = fork();
    if (pid == 0) {
        sleep(15);
        return 3;
    } else {
        int status;
        pid = wait(&status);
        printf("child process exited\n");
        if (WIFEXITED(status)) {
            printf("child process return : %d\n", WEXITSTATUS(status));
        }
    }
    return 0;
}

2)       pid_t waitpid(pid_t pid, int *status, int options);

waitpid(-1, &status, WNOHANG) 

其中,-1 表示可以等待任意子进程终止,WNOHANG表示子进程没有终止也不会进入阻塞状态,而是返回0并退出函数。

如下代码所示,子进程会休眠15s,而在这段时间中,父进程并没有阻塞在waitpid函数上,会不断运行while循环中的代码直到子进程终止后才退出循环。

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    pid_t pid = fork();
    if (pid == 0) {
        sleep(15);
        return 3;
    } else {
        int status;
        while (!waitpid(-1, &status, WNOHANG)) {
            printf("child process in running\n");
            printf("do someting\n");
        }
        printf("child process exited\n");
        if (WIFEXITED(status)) {
            printf("child process return : %d\n", WEXITSTATUS(status));
        }
    }
    return 0;
}

3)借助信号处理机制,当子进程终止后,会产生一个SIGCHLD信号,注册SIGCHLD信号的处理函数,在处理函数中调用wait/waitpid函数获取子进程的返回值,从而使操作系统销毁子进程。

signal/sigaction函数是信号注册函数。发生注册的信号时,操作系统将调用相应的信号处理函数。信号处理函数的参数应为int型,返回值类型为void 。操作系统调用信号处理函数时,传递给该函数的参数是信号值。 

当子进程终止时,操作系统会产生一个SIGCHLD信号。注册一个SIGCHLD信号的处理函数。处理函数调用wait/waitpid函数获取子进程的返回值来销毁子进程。

sigaction函数解决了signal的可移植问题。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值