gpt4 book ai didi

c - 在 C 中处理 SIGTSTP 信号

转载 作者:行者123 更新时间:2023-12-03 14:42:41 29 4
gpt4 key购买 nike

我在学习中遇到了这个示例代码:

#include <signal.h>
#include <stdio.h>
#include <string.h>

char* nums[5] = {"One", "Two", "Three", "Four", "Five"};
char number[6];

void handler(int n) {
printf(" %s\n", number);
}

int main() {
signal(SIGTSTP, handler); // ^Z
for(int n = 0; ; n++) {
strcpy(number, nums[n % 5]);
}
}

显然,这段代码在编译和运行时有问题。尝试使用 Ctrl+Z 生成 SIGTSTP,而不是打印出“nums”中的一个单词然后退出,而是按预期打印出数字,但随后继续运行。它需要来自键盘的另一个 SIGTSTP 信号来真正让程序退出。

这是为什么?

最佳答案

为了回答您提出的两个实际问题,程序会继续运行,因为您的信号处理程序已返回,并且您在信号处理程序中编写的任何内容都不会导致程序终止,因此您的程序将继续正常运行。如果您希望程序终止,您需要从中调用 _exit()_Exit()

第二个 SIGTSTP 导致您的程序终止的原因是因为 signal() 是一个过时且不可靠的接口(interface),在类 Unix 平台上也不是标准接口(interface)。原始行为是,在使用 signal() 注册信号处理程序后,当实际传送该信号时,首先将该信号的配置重置为 SIG_DFL,然后 然后 您的信号处理程序运行。因此,在第一次传递该信号后,您的信号处理程序不再注册,除非您再次调用 signal()。因此,当信号第二次传递给您的程序时,不会调用您的信号处理程序,而是采取默认操作,在本例中是停止进程。此行为在 BSD 派生系统上有所不同,其中信号处理程序保持注册状态。所以实际上,您可以使用 signal() 做的唯一可靠的事情是将处置设置为 SIG_IGNSIG_DFL。对于其他任何事情,您应该使用带有 sigaction() 的现代可靠信号接口(interface)。

您的程序还有一些其他问题。首先,printf() 以及大多数标准库函数从信号处理程序调用是不安全的。 POSIX 定义 a complete list of asynchronous-signal-safe functions可以从信号处理程序中安全地调用它。相反,在这种情况下,您应该设置一个类型为 volatile sig_atomic_t 的标志,并将其设置在您的处理程序中。

其次,您在这里使用 strcpy() 的方式特别危险。假设 number 当前包含 “Two”。然后,在循环的下一次迭代中,它复制 'T''h''r' 'e',覆盖现有终止空字符的最后一个字符。 然后 发送信号并将此字符串传递给 printf()。即使没有从信号处理程序调用 printf() 的问题,您也向它发送一个 char 数组,该数组不以空字符结尾,您将招致未定义的行为和可能的段错误。

这是您的示例的一个更好的版本,使用 sigaction() 接口(interface),而不是从信号处理程序调用不安全的函数:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

char * nums[] = {"One", "Two", "Three", "Four", "Five"};
volatile sig_atomic_t stop;

void handler(int n)
{
stop = 1;
}

int main(void)
{
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);

if ( sigaction(SIGTSTP, &sa, NULL) == -1 ) {
perror("Couldn't set SIGTSTP handler");
exit(EXIT_FAILURE);
}

int n = 0;
while ( !stop ) {
puts(nums[n]);
n = (n + 1) % 5;
}

puts("Signal handler called, exiting.");

return 0;
}

输出:

paul@horus:~/src/sandbox$ ./sig
One
Two
Three
Four
Five
One
^ZTwo
Three
Four
Five
One
Signal handler called, exiting.
paul@horus:~/src/sandbox$

您可以看到在输入 Ctrl-Z 和信号的实际传递之间存在延迟,这是完全正常的并且根据内核实际传递信号的方式可以预期。

关于c - 在 C 中处理 SIGTSTP 信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40098170/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com