一个关于apue里的问题
最近在看unix编程,看到了信号这一章,好迷惑。。。。很多都不能理解。比如在下面这段代码中TELL_WAIT()为什么要Block SIGUSR1 and SIGUSR2 呢?如果没有阻塞这两个信号有什么后果呢?望各位路过大神可以解答一下我的疑惑。万分感激
#include "apue.h"
static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t newmask, oldmask, zeromask;
static void
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
{
sigflag = 1;
}
void
TELL_WAIT(void)
{
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR2) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);
/*
* Block SIGUSR1 and SIGUSR2, and save current signal mask.
*/
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
}
void
TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2); /* tell parent we're done */
}
void
WAIT_PARENT(void)
{
while (sigflag == 0)
sigsuspend(&zeromask); /* and wait for parent */
sigflag = 0;
/*
* Reset signal mask to original value.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
void
TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1); /* tell child we're done */
}
void
WAIT_CHILD(void)
{
while (sigflag == 0)
sigsuspend(&zeromask); /* and wait for child */
sigflag = 0;
/*
* Reset signal mask to original value.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
linux?? apue
[解决办法]
你这个没有main函数没法说具体会出现什么结果。
阻塞信号是因为并发。比如说,多进程并发,三个信号同时响应,都打开一个文件将里面的数字加1,第一个信号打开取数+1还没有存回去,可能第二个进程就取数了,也取到了1,这样都是把2存回去了,加了两次按理说本来应该是三。这就是多个进程竞争冲突,所以一个信号操作的时候一般把别的信号block住,让此时只能响应一个信号
[解决办法]
正好手头有这本书,谈一谈我当初看的时候对这个问题的理解。
1.这段代码要参考程序清单8-7来看,(可能出版社不同具体标识也不同)
2.再请lz注意一下10.4节中的一句话:信号有可能丢失,一个信号发生了,进程却不知道这一点。有时用户希望通知内核阻塞一个信号,不要忽略该信号,在其发生时记住它,然后在进程做好准备时再通知他
好了,有了以上两点,我们分析一下这个例程,
假设fork之后(8-7程序)父进程先执行,那么它会TELL_CHILD,也就是把SIGUSR1发送给子进程,但是这个时候子进程根本就没有运行,也就是说子进程根本就没有准备好(参考上述第2点),可能会弄丢这个信号,所以需要阻塞这个SIGUSR1,等到子进程真正准备好了的时候(我的理解就是子进程运行起来的时候)在把这个阻塞的信号传递给它,所以子进程就能从sigsuspend中返回并继续执行
呵呵,个人理解,欢迎楼主批评指正