信号处理程序不会看到全局变量

这是问题:这个程序应该从stdin接收输入并计算插入的字节数; SIGUSR1信号将停止主程序并将在文件标准错误上打印当我发送SIGUSR1时已经复制了多少字节。

这就是我老师要我这样做的方式:在一种终端类型中

cat /dev/zero | ./cpinout | cat >/dev/null 

而从第二个终端发送信号

 kill -USR1 xxxx 

其中xxxx是cpinout的pid。

我更新了我以前的代码:

 /* cpinout.c */ #include  #include  #include  #include  #include  #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); } 


编辑

在您提到的评论中,您正在运行以下命令:

cat /dev/zero | ./namefile | cat >/dev/null

这种行为实际上很好。 /dev/zero是一个无休止的零流,它被发送到程序。 所以它很快就算了起来。 当你打断时,它会停止并且你留下了很多。


该问题可能与以下事实有关:可以在更新全局变量时调用信号处理程序(如果这需要多个指令)。 但是,GNU文档声明可以安全地假设int在POSIX系统上始终是primefaces的。

我能想到的唯一另一种可能性是你在循环中调用fputc ,在处理程序中使用printf (但是如果程序没有调用printf ,则应该可以安全地调用printf )。 尝试从循环中删除fputc以查看它是否可以解决问题。

编辑:

这似乎可以解释这个问题。 这涉及从信号处理程序中安全调用的函数类型:

如果函数使用静态数据结构进行内部簿记,则函数也可以是非等效的。 此类函数最明显的例子是stdio库(printf(),scanf()等)的成员,它们更新缓冲I / O的内部数据结构。 因此,当在信号处理程序中使用printf()时,如果处理程序在执行对printf()或其他stdio的调用过程中中断主程序,我们有时可能会看到奇怪的输出 – 甚至是程序崩溃或数据损坏function。 ( Linux编程接口

您的程序正在中断stdiofunction,这似乎完全符合这一要求。


这是另一种方法:

 #include  #include  #include  #include  int countbyte = 0; // for main program int sigcount = 0; // for signal handler /* my_handler: signal handler */ static void sighandler(int signum) { sigcount = countbyte; } int main(void) { int c; struct sigaction sigact; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigact.sa_handler = sighandler; sigaction(SIGUSR1, &sigact, NULL); while ((c = getc(stdin)) != EOF) { countbyte++; fputc(c, stdout); } if (sigcount != 0) { printf("Interrupted after %d bytes\n", sigcount); } return 0; } 

信号只能根据C89和POSIX 7标准写入volatile sig_atomic_t变量:

如果信号处理程序引用除了errno [Option End]以外的任何对象[CX] [Option Start]以及静态存储持续时间,而不是通过为声明为volatile sig_atomic_t的对象赋值,则行为未定义

实现通常提供更多,但我怀疑使用非易失性全局变量或printf是由您提供的。