进程等待

通过调用fork创建了一个子进程,通过返回值来判断,但始终无法并不知道结束顺序,比如下面在两个进程中,最后都分别执行message内容,并sleep 1秒钟,不过子进程执行了3次,而父进程仅仅执行一次,就会出现奇怪的现象~!

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(){
    pid_t pid;
    char *message;
    int n;

    if ((pid = fork()) < 0) {
        printf("fork failed...\n");
        exit(1);
    } else if (pid == 0){
        message = "child now...";
        n = 3;
    } else {
        message = "parent now...";
        n = 1;
    }

    for(; n > 0; n--){
        puts(message);
        sleep(1);
    }
    return 0;
}

编译执行结果如下:

lihui@2015 ~
$ ./a.exe
child now...
parent now...
child now...

lihui@2015 ~
$ child now...

很莫名其妙的,第一次打印了1次父进程和2次子进程,这时候结束了,可立马在什么都没做的情况下,shell命令行又跳出来了一行子进程的打印信息

也就是说这里运行的时候,子进程并没有执行完毕,而父进程已经结束了,具体说是在子进程打印完它的所有消息之前就结束了,所以就显得有些乱

有时候我们希望知道子进程何时结束,并且能够通过父进程等待子进程的结束,可以调用wait函数:

#include <sys/wait.h>

pid_t wait(int *status);

wait系统调用会暂停父进程直到它的子进程结束为止,这个系统调用返回的是子进程的pid,此时应该是已经结束运行的子进程的pid,而且允许父进程了解子进程的退出状态,也就是子进程main函数返回的值或者是子进程exit函数的退出码,如果status不是空指针,状态信息也会被写入它所指向的位置;通过sys/wait.h里定义的宏解释状态信息:

WIFEXITED(status)       如果子进程正常结束,它返回一个非零值
WEXITSTATUS(status)     如果WIFEXITED非零,它返回子进程的退出码
WIFSIGNALED(status)     如果子进程因为一个未捕获的信号而终止,它返回一个非零值
WTERMSIG(status)        如果WIFSIGNALED非零,它返回一个信号代码
WIFSTOPPED(status)      如果子进程意外终止,它返回一个非零值
WSTOPSIG(status)        如果WIFSTOPPED非零,它返回一个信号代码

如此一来,想要父进程在执行完之后,等待子进程先执行完,自己再结束,可以加入最后一段主进程的等待过程:

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

int main(){
    pid_t pid;
    char *message;
    int n;

    if ((pid = fork()) < 0) {
        printf("fork failed...\n");
        exit(1);
    } else if (pid == 0){
        message = "child now...";
        n = 3;
    } else {
        message = "parent now...";
        n = 1;
    }

    for(; n > 0; n--){
        puts(message);
        sleep(1);
    }
    if (pid != 0){
        int status;
        pid_t child_pid;
        child_pid = wait(&status);
        printf("child %d finished...\n", child_pid);
        if (WIFEXITED(status))
            printf("child exited with code %d\n", WEXITSTATUS(status));
        else
            printf("child abnormally...\n");
    }
    return 0;
}

如此一来,编译,执行,就再也不会出现主进程结束了,子进程还冒出来打印信息的现象:

lihui@2015 ~
$ ./a.exe
child now...
parent now...
child now...
child now...
child 5964 finished...
child exited with code 0

发表评论