C问题:求教:R.Stevens 中的一个问题(kingofark)
[问题名称]:
Kingofark求教:R.Stevens<UNIX环境高级编程>中的一个问题(kingofark)
[问题的环境]:
我的机子:Red Hat Linux 7.1 (Kernel 2.4.2-2)
[问题的地点]:
机械工业出版社:Richard Stevens《UNIX环境高级编程》第10章 信号
第229页至第230页:程序10-15 保护临界区不被信号中断
[问题的提出]:
书中说到,
“运行程序10-15得到下面的输出:
$ a.out
in critical region: SIGINT
^? 键入自定义的中断字符
in sig_int: SIGINT
after return from sigsuspend: SIGINT”
本程序演示了如何在临界区(即代码中的 critical region 那个位置)屏蔽掉一些中断信号。但是,我阅读到这里的时候,对书中所显示的输出结果很不满意,因为三条输出竟然都是SIGINT。
按照程序的本意,结果中的第一条(即“in critical region:”)的输出应该是和第三条(即“after return from sigsuspend:”)的输出是一样的(这两条显示的都是临界区中被屏蔽的中断信号),而它们并不一定与第二条(即“in sig_int:”)的输出相同。
然而在书中,却恰好是一个三条输出结果都相同的例子。我觉得对于我这样一个初学者来说,即使没有看不懂,至少也是令人觉得很不爽——这样的输出结果,非要让人来一个完全不必要的阿Q式“凡事须得研究才能明白”的研究才能消除对其的迷惑。
于是,我对程序10-15作了一点小的修改。只要让临界区多屏蔽一个中断信号,那么第一、三条的输出结果就会与第二条的输出结果不同,从而使得整个程序示例的输出结果清晰明了,明白无误。具体改动:只要在一开始设置newmask信号集的地方(即代码中sigaddset(&newmask,SIGINT);这一句的地方,)再加上一句sigaddset(&newmask,其它中断信号);就可以了。我加上了一句sigaddset(&newmask,SIGUSR1);,得到如下的输出结果:
$ a.out
in critical region: SIGINT SIGUSR1
^? 键入自定义的中断字符
in sig_int: SIGINT
after return from sigsuspend: SIGINT SIGUSR1
这样多好!
[问题的解答]:
毕竟上面的讨论问题是我自己琢磨的,所以也不敢保证是对的,特此希望各位有兴趣的同胞也看看,有什么问题和想法或者异议,跟我说说,也好让我学习学习。
谢谢!
附:书中的程序10-15代码及相关的代码程序10-10
// -- 程序10-15 ----------------------------------
#include <signal.h>
#include "ourhdr.h"
static void sig_int(int);
int
main(void)
{
sigset_t newmask, oldmask, zeromask;
if (signal(SIGINT, sig_int) == SIG_ERR)
err_sys("signal(SIGINT) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
/* block SIGINT and save current signal mask */
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
/* critical region of code */
pr_mask("in critical region: ");
/* allow all signals and pause */
if (sigsuspend(&zeromask) != -1)
err_sys("sigsuspend error");
pr_mask("after return from sigsuspend: ");
/* reset signal mask which unblocks SIGINT */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
/* and continue processing ... */
exit(0);
}
static void
sig_int(int signo)
{
pr_mask("\nin sig_int: ");
return;
}
//-- 程序10-10 ---------------------------------------
#include <errno.h>
#include <signal.h>
#include "ourhdr.h"
void
pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
err_sys("sigprocmask error");
printf("%s", str);
if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
/* remaining signals can go here */
printf("\n");
errno = errno_save;
}