C 信号处理器赢得';看不到全局变量
问题是:这个程序应该接收stdin的输入,并计算插入的字节数;SIGUSR1信号将停止主程序,并在文件上打印标准错误,即发送SIGUSR1时复制了多少字节 我的老师希望我这样做:在一个终端运行C 信号处理器赢得';看不到全局变量,c,signals,scope,signal-handling,C,Signals,Scope,Signal Handling,问题是:这个程序应该接收stdin的输入,并计算插入的字节数;SIGUSR1信号将停止主程序,并在文件上打印标准错误,即发送SIGUSR1时复制了多少字节 我的老师希望我这样做:在一个终端运行 cat /dev/zero | ./cpinout | cat >/dev/null 而从第二个终端发送信号时 kill -USR1 xxxx 其中xxxx是cpinout的pid 我更新了以前的代码: /* cpinout.c */ #include <stdio.h> #inc
cat /dev/zero | ./cpinout | cat >/dev/null
而从第二个终端发送信号时
kill -USR1 xxxx
其中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 = countbyte;
}
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);
}
/*cpinout.c*/
#包括
#包括
#包括
#包括
#包括
#定义BUF_大小1024
易失性信号原子计数字节=0;
易挥发sig_原子sig_t sigcount=0;
/*我的处理器:gestore di信号*/
静态无效信号发生器(内部信号){
如果(sigcount!=0)
fprintf(stderr,“在%d字节后中断。\n”,sigcount);
sigcount=countbyte;
}
内部主(空){
INTC;
字符缓冲区[BUF_大小];
结构动作;
sigemptyset(和action.sa_mask);
action.sa_标志=0;
action.sa_handler=sighandler;
if(sigaction(SIGUSR1,&action,NULL)=-1){
fprintf(stderr,“sigusr:sigaction\n”);
出口(1);
}
while(c=getc(stdin)!=EOF){
countbyte++;
fputc(c,stdout);
}
返回(0);
}
根据C89和标准,信号只能写入易失性sig\u原子\u t
变量:
如果信号处理程序引用除errno[Option End]之外的任何对象[CX][Option Start],且该对象具有静态存储持续时间,而不是通过向声明为volatile sig_原子的对象赋值,则该行为是未定义的
实现通常提供更多,但我怀疑使用非易失性全局变量或printf是否是您提供的。编辑 在您提到的注释中,您正在以以下方式运行命令:
cat/dev/zero |/namefile | cat>/dev/null
这种行为其实很好/dev/zero
是一个源源不断的零,它们被发送到程序中。所以它很快就把它们计算出来了。当你中断时,它会停止,剩下的是一个很大的数字
问题可能与以下事实有关:在更新全局变量时可能会调用信号处理程序(如果这需要多条指令)。然而,GNU文档指出,可以安全地假设,
int
在POSIX系统上始终是原子的
我能想到的唯一的另一种可能性是,在循环中调用fputc
,在处理程序中调用printf
(但是,如果程序没有调用它,在处理程序中调用printf
应该是安全的)。尝试从循环中删除fputc
,看看它是否解决了问题
编辑:
这似乎可以解释这个问题。这与从信号处理程序中安全调用的函数类型有关:
如果函数使用静态数据结构,那么它们也可以是非进入函数
他们的内部簿记。最明显的例子就是这样
函数是stdio库的成员(printf(),scanf(),
等等),更新缓冲I/O的内部数据结构。
因此,当从信号处理程序中使用printf()时,我们可能
有时会看到奇怪的输出,甚至程序崩溃或数据丢失
如果处理程序在中间中断主程序
执行对printf()或其他stdio函数的调用。
(Linux编程接口)
您的程序正在中断一个stdio函数,它似乎非常适合这个函数。
以下是另一种方法:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
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;
}
#包括
#包括
#包括
#包括
int countbyte=0;//主程序
int sigcount=0;//用于信号处理器
/*我的处理器:信号处理器*/
静态无效信号发生器(内部信号)
{
sigcount=countbyte;
}
内部主(空)
{
INTC;
struct-sigaction-sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_标志=0;
sigact.sa_handler=signandler;
sigaction(SIGUSR1和sigact,NULL);
而((c=getc(stdin))!=EOF){
countbyte++;
fputc(c,stdout);
}
如果(sigcount!=0){
printf(“在%d字节之后中断,\n”,sigcount);
}
返回0;
}
您能否给出一个提示,为什么您认为signal和sigaction之间的差异在这里是相关的?@AProgrammer-文档中指出,signal()的行为在UNIX版本中有所不同,在Linux的不同版本中也有不同。避免使用:使用sigaction(2)代替。。。signal()的唯一可移植用途是将信号的配置设置为SIG_DFL或SIG_IGN。使用signal()建立信号处理程序时的语义因系统而异(POSIX.1明确允许这种变化);不要将其用于此目的。是的,unix变体之间的行为存在差异,我不知道与报告的问题有关。@AndreaMazzocchi-您的操作系统是什么?Linux Xubuntu 12.10 3.5.0-23-generic即使使用sigaction>,也无法工作。<我仍然复制了数百万字节