CSAPP第3版练习题8.8,使用信号处理程序

问题描述

以下代码摘自 CS:APP3e 第 809 页的练习题 8.8

volatile long counter = 2;

void handler1(int sig) 
{
    sigset_t mask,prev_mask;

    Sigfillset(&mask);
    Sigprocmask(SIG_BLOCK,&mask,&prev_mask);  /* Block sigs */
    Sio_putl(--counter);
    Sigprocmask(SIG_SETMASK,&prev_mask,NULL); /* Restore sigs */

    _exit(0);
}

int main() 
{
    pid_t pid;
    sigset_t mask,prev_mask;

    printf("%ld",counter);
    fflush(stdout);

    signal(SIGUSR1,handler1);
    if ((pid = fork()) == 0) {
        while(1) {};
    }
    Kill(pid,SIGUSR1); 
    Waitpid(-1,NULL,0);

    Sigfillset(&mask);
    Sigprocmask(SIG_BLOCK,&prev_mask);  /* Block sigs */
    printf("%ld",++counter);
    Sigprocmask(SIG_SETMASK,NULL); /* Restore sigs */

    exit(0);
}

任务是找到这个程序的打印输出。根据教科书,答案应该是“213”。给出的解释如下:

父进程首先打印“2”,然后派生子进程,子进程无限循环。然后父节点向子节点发送信号并等待它终止。孩子捕获信号(中断无限循环),递减计数器(从初始值 2),打印“1”,然后终止。父节点收割子节点后,它会增加计数器(从初始值 2 开始),打印“3”,然后终止。

我不明白对 printf 的最后一次调用如何将 counter 的初始值设为 2。在孩子捕获 SIGUSR1 信号并将控制权传递给 handler1,它将全局变量递减为 1,并因 _exit(0) 系统调用而终止。父进程收割终止的子进程后,调用 printf("%ld",++counter); 应该使用 counter 的值作为 1 并打印“2”。因此,打印输出应该是“212”。谁能解释为什么打印“213”?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)