2010-03-20 2 views
19

Как я могу реализовать обработку сигналов для Ctrl-C и Ctrl-D в C .... Итак, если Ctrl-C нажата, программа проигнорирует и попытается снова получить вход от пользователя. ..если Ctrl-D нажата, то программа будет завершена ...Обработка сигналов в C

Моя программа следующим образом:

int main(){ 
char msg[400]; 

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

Спасибо,

Дэйва

+3

Я не рекомендовал бы это. Есть очень мало примеров, когда я могу подумать, где хорошая идея для программы переопределить функцию kill-Ctrl's - инструмент удаленного подключения, такой как SSH, являющийся одним из них. –

+0

Это просто для понимания того, как обращаться с сигналами. – Dave

+1

Любая программа-интерпретатор должна улавливать ctrl-C, чтобы прервать размещенную программу, если она запущена. – Potatoswatter

ответ

2

В вашем примере вы, кажется, не» t требуется рукоятка CTRL-C вообще. «Сигнал (SIGINT, SIG_IGN)» кажется вам достаточным, если ваше приложение не должно обрабатывать SIGINT, исходящий из какого-либо другого источника. CTRL-D обычно не генерирует сигналы, он просто передает состояние EOF. Вы можете контролировать поведение вашего терминала (речь идет о консольном вводе, это не так?), Используя termios library (также here). Вы можете включить, переопределить или отключить символ "прерывания" (CTRL-C), то EOF один, и многие другие (XON, XOFF, управление модемом ...)

С уважением

13

Во-первых, 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 */ 
} 
+0

Обработчик SIG_IGN будет соответствовать потребностям OP. – outis

+2

Почему sigact является глобальной переменной? Почему уборка с этим связана? вам нужно будет снова вызвать sigaction() для изменения sigact, чтобы повлиять на поведение программы. –

+0

@ JonathanLeffler: Не могли бы вы объяснить мне, почему это не хорошая идея объявить sigact global, пожалуйста? Я хотел бы понять этот момент. Спасибо. – Kyrol

31

При работе с сигналами POSIX, у вас есть два средства в вашем распоряжении. Во-первых, легкий (но устаревший) способ, signal(). Во-вторых, более элегантный, современный, но сложный способ, sigaction(). Используйте sigaction(), если вы не обнаружите, что он недоступен на какой-либо платформе, над которой вам нужно работать.

This chapter руководство пользователя glibc объясняет различия между ними и дает хороший пример кода о том, как использовать оба варианта. Он также перечисляет сигналы, которые могут быть обработаны, рекомендует, как они должны обрабатываться и углубляться в том, как рассказать, каким образом любой данный сигнал (или нет) в настоящее время составляет , являющийся. Это больше кода, чем хотелось бы вставить в ответ здесь, следовательно, ссылки.

Это действительно стоит часа или двух, чтобы вы могли прочитать ссылки и работать с примерами. Обработка сигналов (особенно в программах, которые демонизируют) чрезвычайно важна. Хорошая программа должна обрабатывать все фатальные сигналы, которые могут обрабатываться (то есть SIGHUP), и явно игнорировать сигналы, которые он может не использовать (то есть SIGUSR1/SIGUSR2).

Это также не помешает изучить разницу между нормальными и реальными сигналами времени, по крайней мере, до понимания того, как ядро ​​объединяет предыдущее, а не последнее.

После того, как вы пройдете через него, вы, вероятно, почувствуете склонность писать простой и удобный набор функций для обработки ваших сигналов и повторного использования этого кода снова и снова.

Извините за не давая быстрый и грязный фрагмент кода, чтобы показать вам, как решить насущную потребность, но это не быстрая и грязная тема :)

2

Это программа для обработки сигнала при нажатии Ctrl + с

синтаксис функции сигнала является: signal(signal name, function name);

#include<stdio.h> 
#include<signal.h> // for handling signal 

void signal_handler() 
{ 
    printf("Signal Handled here\n"); 
} 

main() 
{ 
    printf("In main function..\n"); 

    // SIGINT is signal name create when Ctrl+c will pressed 
    signal(SIGINT,signal_handler); 

    sleep(15); 

    printf("In main after called from signal_handle \n"); 

} 
+0

'signal()' устарел и его следует избегать по возможности, почти все современные платформы (за исключением некоторых встроенных) предлагают 'sigaction()'. –

0
#include<signal.h> 
#include<unistd.h> 
#include<stdio.h> 
void signal_catch() 
{ 
    printf("hi,Your signal catched Here"); 
} 
int main() 
{ 
    signal(SIGINT,signal_catch); 
//press ctrl+c 
    sleep(10); 
    return 0; 
}//end main 

//if you want to simply ignore ctrl+c interrupt use following code in main 

int main() 
{ 
    signal(SIGINT,SIG_IGN); 
    sleep(100); 
    return 0; 
}//end main 
//this program wont accept ctrl+c interrupt for 100 seconds. 
Смежные вопросы