fork进程控制

完整了解UNIX进程控制是十分重要的。


对我们而言,必须熟练掌握的几个函数:forkexec系列,_exitwaitwaitpid


waitpid可以等待一个特定进程的结束
wait相当于: waitpid( -1, &status, 0 );


关于fork:
如果子进程在父进程之前终止,父进程可以通过wait或者waitpid获得子进程的状态,内核为每个终止子进程保存了一定量的信息


一个已经终止,但是父进程没有做善后处理的进程被称为僵尸进程zombie,ps(1)打印的状态为Z。
如果编写一个长期运行的程序,它fork很多子进程,除非父进程等待取得子进程的终止状态,不然这些子进程终止后就会变成zombie


init (id为1,在自举过程结束时调用,绝不会终止)收养的进程,它结束时,init一定会调用一个wait函数取得终止状态
所谓“一个init的子进程”,指的可能是init直接产生的进程(比如getty);或者其父进程已经终止,由init收养的进程


子进程正常或者异常终止,内核向它的父进程发送异步SIGCHLD信号
对于SIGCHLD系统默认是忽略



小技巧

如果一个进程fork一个子进程,但不要它等待子进程终止,也不希望子进程处于僵尸状态直到父进程终止,可以fork两次

fork两次避免僵尸进程:

#include <apue.h>
#include <unistd.h>
#include <sys/wait.h>

#define handle_error(msg) \
    do { perror(msg); return EXIT_FAILURE; } while(0)

int main(void)
{
    pid_t pid;
    int status;

    if ((pid = fork()) < 0)
        handle_error("fork");
    else if (pid == 0) {            //first child
        if ((pid = fork()) < 0)
            handle_error("fork");
        else if (pid > 0)
            exit(0);        //parent from the second fork == first child

        /* fork twice 
         * out parent become init soon as real parent call exit()
         * */
        sleep(2);
        printf("second child, parent pid = %ld", (long) getpid());
        exit(0);
    } else {
        /* we are the original process 
         * not the parent of the second child
         * */
        if (waitpid(pid, &status, 0) != pid) 
            handle_error("waitpid");
    }
    return EXIT_SUCCESS;
}

第二个子进程调用sleep(3)保证打印父进程ID的时候第一个子进程已经终止。fork之后父进程和子进程都可以继续执行,并且我们无法预测哪一个先执行。fork之后如果不让第二个子进程休眠,那么它可能比其父进程先执行,于是它打印的父进程ID将是创建它的父进程的ID而不是init进程的1.。

当原来的进程(exec本程序的进程)终止时,shell打印其提示符,这在第二个子进程打印其父进程ID之前。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值