这是问题:这个程序应该从stdin接收输入并计算插入的字节数; SIGUSR1信号将停止主程序并在文件标准错误上打印当我发送SIGUSR1时已经复制了多少字节。
这就是我的老师要我这样做的方式:在一个终端类型
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 = 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);
}
答案 0 :(得分:3)
信号只能根据C89和POSIX 7标准写出volatile sig_atomic_t
个变量:
如果信号处理程序引用除了errno [Option End]以外的任何对象[CX] [Option Start]以及静态存储持续时间,而不是通过为声明为volatile的对象赋值sig_atomic_t
,则行为未定义
实现通常提供更多,但我怀疑使用非易失性全局变量或printf是由您提供的。
答案 1 :(得分:2)
<小时/> 的修改
在您提到的评论中,您正在运行命令:
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;
}