天天看点

10_26 当调用system函数时子进程与父进程对信号的处理,尤其是SIGCHLD

posix.1 标准规定,当在执行system函数时,应该阻止对父进程递送SIGCHLD信号。

因为如果不阻止,当system创建的子进程结束时,system调用者可能错误的认为,它自己的一个子进程结束了,从而调用一种wait函数以获得子进程退出状态,进而阻止了system函数里获得子进程的终止状态,并将其返回。

还因为system函数如果调用了交互式的应用,如本例的ed,其实父进程已经丧失了控制,应当等待该进程结束。

首先看直接调用标准的system函数时的运行结果。成功阻塞了对父进程信号(中断和退出)的传递。

源代码:

vim 10_26.c

#include "apue.h"

static void sig_int(int signo)

{

        printf("Caught SIGINT\n");

}

static void sig_child(int signo)

{

        printf("Caught SIGCHILD\n");

}

int main(void)

{

        if(signal(SIGINT,sig_int) == SIG_ERR)

                err_sys("signal SIGINT error");

        if (signal(SIGCHLD,sig_child) == SIG_ERR)

                err_sys("signal SIGCHLD error");

        if (system("/bin/ed") < 0)

                err_sys("system() error");

        exit(0);

}

~

~

~

~

~

~

~

~

~

~

~

~

~

~

~

~

~

~

"10_26.c" [New] 25L, 391C written

<bldc:/home/tingbinz/apue.3e/SBSCODE/10>R*_*G:gcc -Wall -ggdb3 error.c 10_23.c -o jump_out_while

error.c: In function `err_doit':

error.c:121: warning: implicit declaration of function `vsnprintf'

error.c:123: warning: implicit declaration of function `snprintf'

<bldc:/home/tingbinz/apue.3e/SBSCODE/10>R*_*G:gcc -Wall -ggdb3 error.c 10_26.c -o CHILD_Catch_signal

error.c: In function `err_doit':

error.c:121: warning: implicit declaration of function `vsnprintf'

error.c:123: warning: implicit declaration of function `snprintf'

运行结果。

<bldc:/home/tingbinz/apue.3e/SBSCODE/10>R*_*G:./CHILD_Catch_signal

a

hello,world

.

1,$p

hello,world

w temp.foo

12

^C

?

q

<bldc:/home/tingbinz/apue.3e/SBSCODE/10>R*_*G:

<bldc:/home/tingbinz/apue.3e/SBSCODE/10>R*_*G:

调用自己写的system函数,未阻塞信号,所以中断和退出信号都发送给了父进程和子进程。

自己system函数的源代码。

vim 8_22.c

#include "apue.h"

#include <errno.h>

#include <unistd.h>

int system(const char *cmdstring)

{

        pid_t pid;

        int status;

        if ((pid = fork()) < 0){

                status = -1;

        }else if (pid == 0){

                execl("/bin/sh","sh","-c",cmdstring, (char*) 0);

                err_sys("execl:%s error",cmdstring);

                _exit(127);

        }else{

                while (waitpid(pid,&status,0) < 0){

                        if (errno != EINTR){

                                status = -1;

                                break;

                        }

                }

        }

        return (status);

}

~

~

~

~

~

~

~

~

~

~

~

~

~

~

~

~

~

编译及运行结果:

:gcc -Wall -ggdb3 8_22.c error.c 10_26.c -o CHILD_Catch_signal

8_22.c: In function `system':

8_22.c:17: warning: implicit declaration of function `waitpid'

error.c: In function `err_doit':

error.c:121: warning: implicit declaration of function `vsnprintf'

error.c:123: warning: implicit declaration of function `snprintf'

./CHILD_Catch_signal

a

hello,world

.

1,$p

hello,world

w temp.foo

12

^C

?

Caught SIGINT

q

Caught SIGCHILD