2

大家好,在使用 fork 和 signal 进行一些实验时,我遇到了一个表现出非常有趣的行为的程序,但经过几个小时的努力,我无法弄清楚发生了什么。

我想做的是我在主体内创建一个子进程,然后打印“hello world”,然后调用exit。在此之后,它的信号处理程序将被调用,并且被等待系统调用阻塞的父进程也将被调用。现在我在信号处理程序中创建另一个进程,但从那里开始,输出变为无限。

输出如下: Hello world Come to Linux Come to UNIX Come to Linux Come to UNIX Come to Linux Come to UNIX ...

又何必来Linux一再印。

另外请告诉我什么时候调用 fork,我知道重复的地址空间是由父级组成的,但是信号处理程序呢。他们是否也会重复。在我的情况下,当孩子调用退出时。然后被调用的信号处理程序是子级或父级的。

请帮忙。谢谢。

void sig_handler(int signo)
{
if(fork() == 0){

}
else{
    int pid = 0;
    wait(&pid);
    printf("Come to unix");
    fflush(stdout);
}
 }


int main()
{
if (signal(SIGCHLD, sig_handler) == SIG_ERR){
}

int child_pid;
int i;

child_pid = fork();
switch (child_pid) {
    case -1:         
        perror("fork");
        exit(1);
    case 0:          
        printf("hello world\n");fflush(stdout);        
        exit(0);
    default:
        wait(&i);
        printf("Come to linux");
        exit(0);
        //break;
}

return 0;
}
4

2 回答 2

1

它会进入无限循环不是很明显吗?您已经创建了一个 SIGCHLD 处理程序,然后在该处理程序中再次分叉并等待子进程退出。基本上,当该处理程序中的子级退出时,父级再次进入处理程序。下面的代码应该避免它。在信号处理程序开始时,通过将其设置为默认值来避免该信号。

void sig_handler(int signo) {
     signal (SIGCHLD, SIG_IGN);
    if(fork() == 0){ 

    }   
    else{
        int pid = 0;
        wait(&pid);
        printf("Come to unix");
        fflush(stdout);
    }    
}

此外,您只能在信号处理程序中调用异步信号安全例程以避免未定义的行为。我不确定 printf 和 fflush 是否同步安全。即使进行上述更改避免了循环,程序仍然可能具有未定义的行为。我猜 fork 是异步安全的

请参阅下面可能有帮助的讨论:http: //sourceware.org/bugzilla/show_bug.cgi ?id=4737

于 2013-03-23T13:21:24.643 回答
0

根据 POSIX 标准,调用fork(2)信号处理程序具有未定义的行为,所以不要这样做:)

请参阅: http: //pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

于 2013-03-23T12:33:49.150 回答