CTRL-C处理程序无法正常工作

时间:2013-03-06 13:10:55

标签: c windows-7 handler interrupt

这个程序

#include <stdio.h> 
#include <signal.h>
#include <stdlib.h>
#include <windows.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

void INThandler(int);             

int  main(void)
{
   signal(SIGINT, INThandler);    

   char data[128];

   int n;

   while((n=read(0, data, 128)) > 0)
   {
   if(data[n] = '\n') break;
   }

   data[n] ='\0';

   printf("%s", data);

   return 0;
}

void  INThandler(int sig)
{
     char  c;

     signal(sig, SIG_IGN);             
     printf("OUCH, did you hit Ctrl-C?\n"    
            "Do you really want to quit? [y/n] ");
     c = getchar();                     
     if (c == 'y' || c == 'Y')          
         exit(0);                      
     else
      signal(SIGINT, INThandler);
}

不处理ctrl-c,但终止于该输入。 如果我通过

替换处理程序安装和返回之间的所有内容
while (1)                          
Sleep(1);

处理程序函数被调用并且有效,但我希望在那里有read()。

编辑:回顾这个程序,我注意到我有

if(data[n] = '\n') break;

我写了'='而不是'==',但是通过使用后者,它不能正常工作,我不明白为什么。不应该是检测'\ n'的比较吗? 另外,我搞乱了缓冲区,但如果我按下CTRL-C,我就无法保持输入。

2 个答案:

答案 0 :(得分:1)

示例代码没有考虑到两个问题:

  1. read()如果其进程收到信号,将中止其工作(请参阅man 2 read
  2. 只保证一些函数可以从信号处理函数中保存它们(参见man 7 signal)。 printf()getch() 属于这组“保存”功能。
  3. 可以使用更加差异化的方式来修复第一个问题,以处理read()返回的值。我应该计算已经读取了多少数据,以及传递给read()的缓冲区的一些智能调整。

    关于第二个问题,read()write()是执行信号处理程序的输入/输出的选择函数,因为它们被人工页面列为“保存”函数如上所述。

答案 1 :(得分:0)

这是因为您使用read(2)的实现不允许这样做。这是我编译程序,执行它并按^ C:

时得到的结果
$ ./program
^COUCH, did you hit Ctrl-C?
Do you really want to quit? [y/n] y
$

或如果我回答n并输入一些数据:

$ ./program
^COUCH, did you hit Ctrl-C?
Do you really want to quit? [y/n] n
test
test
$

由于read(2)是系统调用,因此它取决于您使用的系统。我使用Linux(3.2.0-4-686-pae),这里的行为正确。也许您应该考虑使用scanf(3)fread(3)代替stdio(3)代替您正在使用的平台(我认为win32)?或者也使用不同的实现,例如来自 Cygwin MinGW 的实现?