考虑以下伪C代码:
static int G = 0;
void alrm_handler(int signo) {
G = 1;
}
void son() {
struct sched_param param;
param.sched_priority = 50;
sched_setscheduler(getpid(),SCHED_FIFO, ¶m);
kill(getppid(), SIG_ALRM);
sched_yield();
printf("An");
while(1);
exit(0);
}
int main() {
signal(SIG_ALRM, alrm_handler);
int son_pid = fork();
if(son_pid==0)
son();
waitpid(son_pid);
printf("Bn");
return 0;
}
它来自操作系统的一次考试。问题如下:
In multi cores CPU what would be printed?
答案是我们不能知道,因为它可能是A
然后是B
,或者B
然后是A
。我不明白为什么。如果父级正在用waitpid
等待子级,并且子级发送信号SIG_ALRM
,为父级调用alrm_handler
函数,则父级将完成该函数的执行,然后返回等待子级直到其完成运行,否?所以它应该是A
,然后是B
。
根据POSIX,在调用signal
设置的信号处理程序后,是否重新启动系统调用是未定义的。
- System V和Linux
signal
系统调用不会重新启动系统调用 - BSD和默认的GLibc会重新启动系统调用
如果使用System Vsignal
,则waitpid
可以在发送信号后立即返回,从而允许按任何顺序打印字母。如果标准输出是管道或常规文件,则只有B
将被输出,因为子级处于无限循环中
在BSDsignal
中,由于子级中的无限循环,waitpid
不会返回,因此只打印A
。如果标准输出是管道或常规文件,则不会输出任何内容。