为什么在 SIGUSR1 循环的处理程序中调用 kill(getpid(), SIGUSR1)?
Why does calling kill(getpid(), SIGUSR1) inside handler for SIGUSR1 loop?
我试图通过这段代码了解幕后发生的事情。这是我正在参加的 OS 课程介绍的期末考试中提出的问题。据我了解,当从内核模式返回到用户模式时,系统会检查是否有任何未决信号(通过检查信号向量)并倾向于处理它们。因此,当来自 kill 系统调用的程序 returns 时,OS 发现 SIGUSR1 处于挂起状态并调用处理程序。按照这个逻辑,处理程序应该在无限循环中打印“stack”,但是当 运行 这段代码实际上在无限循环中打印“Whosebug”。为什么会这样?
提前致谢。
void handler(int signo) {
printf("stack");
kill(getpid(), SIGUSR1);
printf("overflow\n");
}
int main() {
struct sigaction act;
act.sa_handler = &handler;
sigaction(SIGUSR1, &act, NULL);
kill(getpid(), SIGUSR1);
return 0;
}
您实际上在这里有未定义的行为,因为您使用未完全初始化的 struct sigaction
对象调用 sigaction
。因此,根据 sa_flags
和 sa_mask
字段中的值,可能会发生各种不同的事情。
其中一些不会在信号处理程序 运行ning 时阻塞 SIGUSR1,这意味着新的信号处理程序将 运行 在第一次调用 kill 时立即(在第一个处理程序之前) returns 并弹出其栈帧)。所以你最终会在堆栈上得到许多递归 handler
堆栈帧(以及 'stack' 的输出)直到它溢出。
其他组合会阻止信号,因此它不会立即触发第二个信号处理程序。相反,信号将“挂起”,直到第一个信号处理程序 returns.
我试图通过这段代码了解幕后发生的事情。这是我正在参加的 OS 课程介绍的期末考试中提出的问题。据我了解,当从内核模式返回到用户模式时,系统会检查是否有任何未决信号(通过检查信号向量)并倾向于处理它们。因此,当来自 kill 系统调用的程序 returns 时,OS 发现 SIGUSR1 处于挂起状态并调用处理程序。按照这个逻辑,处理程序应该在无限循环中打印“stack”,但是当 运行 这段代码实际上在无限循环中打印“Whosebug”。为什么会这样? 提前致谢。
void handler(int signo) {
printf("stack");
kill(getpid(), SIGUSR1);
printf("overflow\n");
}
int main() {
struct sigaction act;
act.sa_handler = &handler;
sigaction(SIGUSR1, &act, NULL);
kill(getpid(), SIGUSR1);
return 0;
}
您实际上在这里有未定义的行为,因为您使用未完全初始化的 struct sigaction
对象调用 sigaction
。因此,根据 sa_flags
和 sa_mask
字段中的值,可能会发生各种不同的事情。
其中一些不会在信号处理程序 运行ning 时阻塞 SIGUSR1,这意味着新的信号处理程序将 运行 在第一次调用 kill 时立即(在第一个处理程序之前) returns 并弹出其栈帧)。所以你最终会在堆栈上得到许多递归 handler
堆栈帧(以及 'stack' 的输出)直到它溢出。
其他组合会阻止信号,因此它不会立即触发第二个信号处理程序。相反,信号将“挂起”,直到第一个信号处理程序 returns.