elm*_*zun 5 c scope signals signal-handling
这是问题:这个程序应该从stdin接收输入并计算插入的字节数; SIGUSR1信号将停止主程序并在文件标准错误上打印当我发送SIGUSR1时已经复制了多少字节.
这就是我老师要我这样做的方式:在一种终端类型中
cat /dev/zero | ./cpinout | cat >/dev/null
Run Code Online (Sandbox Code Playgroud)
而从第二个终端发送信号
kill -USR1 xxxx
Run Code Online (Sandbox Code Playgroud)
其中xxxx是cpinout的pid.
我更新了以前的代码:
/* cpinout.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#define BUF_SIZE 1024
volatile sig_atomic_t countbyte = 0;
volatile sig_atomic_t sigcount = 0;
/* my_handler: gestore di signal */
static void sighandler(int signum) {
if(sigcount != 0)
fprintf(stderr, "Interrupted after %d byte.\n", sigcount);
sigcount = contabyte;
}
int main(void) {
int c;
char buffer[BUF_SIZE];
struct sigaction action;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = sighandler;
if(sigaction(SIGUSR1, &action, NULL) == -1) {
fprintf(stderr, "sigusr: sigaction\n");
exit(1);
}
while( c=getc(stdin) != EOF ) {
countbyte++;
fputc(c, stdout);
}
return(0);
}
Run Code Online (Sandbox Code Playgroud)
在评论中您提到您正在运行命令:
\n\ncat /dev/zero | ./namefile | cat >/dev/null
行为其实很好。/dev/zero是无穷无尽的零流,它们被发送到程序。所以它的计数速度非常快。当你打断时,它就会停止,你只剩下一个很大的数字。
该问题可能与以下事实有关:更新全局变量时可能会调用信号处理程序(如果这需要多个指令)。然而,GNU 文档指出,可以安全地假设 anint在 POSIX 系统上始终是原子的。
我能想到的唯一另一种可能性是您fputc在循环中调用处理程序(但是,如果程序没有调用它,则在处理程序中调用printf应该是安全的)。printf尝试fputc从循环中删除以查看是否可以解决问题。
编辑:
\n\n这似乎很能说明问题。这与从信号处理程序中安全调用的函数类型有关:
\n\n\n\n\n如果函数使用静态数据结构进行内部簿记,那么它们也可以是不可重入的。此类函数最明显的示例是 stdio 库的成员(printf()、scanf() 等),它们更新缓冲 I/O 的内部数据结构。因此,当使用 printf 时() 在信号处理程序中,如果处理程序在中间中断主程序,我们有时可能会看到奇怪的输出\xe2\x80\x94,甚至程序崩溃或数据\n损坏\xe2\x80\x94执行对 printf() 或另一个 stdio 函数的调用。\n(Linux 编程接口)
\n
你的程序正在中断一个 stdio 函数,这似乎非常适合这一点。\n
#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\nint countbyte = 0; // for main program\nint sigcount = 0; // for signal handler\n\n/* my_handler: signal handler */\nstatic void sighandler(int signum)\n{\n sigcount = countbyte;\n}\n\nint main(void)\n{ \n int c;\n struct sigaction sigact;\n\n sigemptyset(&sigact.sa_mask);\n sigact.sa_flags = 0;\n sigact.sa_handler = sighandler;\n sigaction(SIGUSR1, &sigact, NULL);\n while ((c = getc(stdin)) != EOF) {\n countbyte++;\n fputc(c, stdout);\n }\n if (sigcount != 0) {\n printf("Interrupted after %d bytes\\n", sigcount);\n }\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n