C中的信号处理

Dav*_*ave 21 c unix shell signals

如何在C中实现Ctrl-C和Ctrl-D的信号处理....所以如果按下Ctrl-C,程序将忽略并尝试再次从用户那里获得输入...如果Ctrl-D是按下然后程序将终止...

我的计划如下:

int main(){
 char msg[400];

 while(1){
   printf("Enter: ");
   fgets(msg,400,stdin);
   printf("%s\n",msg); 
 }
}
Run Code Online (Sandbox Code Playgroud)

谢谢,

戴夫

Tim*_*ost 32

处理POSIX信号时,您可以使用两种方法.首先,简单(但不推荐)的方式,signal().第二,更优雅,当前但复杂的方式,sigaction().请使用sigaction(),除非您发现某些平台无法使用它.

glibc手册的这一章解释了两者之间的差异,并给出了如何使用两者的良好示例代码.它还列出了可以处理的信号,建议他们如何应该被处理,更在如何告诉任何给定的信号是如何(或没有)目前深度去处理.这是比我想要粘贴到答案的代码更多的代码,因此链接.

你需要花一两个小时才能阅读链接并完成示例.信号处理(特别是在守护程序中)非常重要.一个好的程序应该处理所有可以处理的致命信号(即SIGHUP)并明确忽略它可能没有使用的信号(即SIGUSR1/SIGUSR2).

研究正常信号和实时信号之间的差异也不会有害,至少要了解内核如何合并先验而不是后者.

一旦完成它,您可能会倾向于编写一组易于修改的函数来处理信号并一遍又一遍地重复使用该代码.

很抱歉没有提供快速而脏的代码段来向您展示如何解决您的迫切需求,但这不是一个快速而肮脏的主题:)


t0m*_*13b 14

首先,Ctrl + D是一个无法捕获的EOF指示器,当程序等待输入时,按Ctrl + D表示文件结束并且不再需要输入.另一方面,使用Ctrl + C来终止程序 - 即SIGINT,可以通过这样做来捕获它:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>

static void signal_handler(int);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);

struct sigaction sigact;
char *progname;

int main(int argc, char **argv){
    char *s;
    progname = *(argv);
    atexit(cleanup);
    init_signals();
    // do the work
    exit(0);
}

void init_signals(void){
    sigact.sa_handler = signal_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig){
    if (sig == SIGINT) panic("Caught signal for Ctrl+C\n");
}

void panic(const char *fmt, ...){
    char buf[50];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, buf);
    exit(-1);
}

void cleanup(void){
    sigemptyset(&sigact.sa_mask);
    /* Do any cleaning up chores here */
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么sigact是一个全局变量?为什么清理会弄乱它; 你必须再次调用sigaction()来改变sigact以影响程序的行为方式. (2认同)
  • @Kyrol:它不需要成为一个全局变量; 它完全可以是函数中的局部变量,因为它仅在函数内部使用.当调用`sigaction()`时,内核会从结构中复制所需的信息; 之后你不需要保留这个值. (2认同)

Giu*_*ini 2

在您的示例中,您似乎根本不需要 CTRL-C handlind 。“signal(SIGINT,SIG_IGN)”对您来说似乎就足够了,除非您的应用程序必须处理来自其他来源的 SIGINT。CTRL-D 通常不生成信号,它只是传达 EOF 条件。您通常可以通过使用termios 库(也在此处)来控制终端的行为(我们正在谈论控制台输入,不是吗?)。您可以启用、重新定义或禁用“中断”字符 (CTRL-C)、EOF 和许多其他字符(XON、XOFF、调制解调器控制...)

问候