2010-03-20 47 views
19

Làm cách nào để thực hiện xử lý tín hiệu cho Ctrl-C và Ctrl-D trong C .... Vì vậy, nếu nhấn Ctrl-C thì chương trình sẽ bỏ qua và cố gắng lấy lại dữ liệu nhập từ người dùng. ..If Ctrl-D được nhấn sau đó chương trình sẽ chấm dứt ...Xử lý tín hiệu trong C

chương trình My sau:

int main(){ 
char msg[400]; 

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

Cảm ơn,

Dave

+3

tôi sẽ không đề nghị này. Có rất ít trường hợp, tôi có thể nghĩ về một ý tưởng hay cho một chương trình để ghi đè chức năng giết của Ctrl-C - một công cụ kết nối từ xa như SSH là một trong số chúng. –

+0

Đây chỉ là một sự hiểu biết về cách xử lý tín hiệu – Dave

+1

Bất kỳ loại chương trình thông dịch viên nào cũng nên bắt ctrl-C để hủy bỏ chương trình được lưu trữ, nếu chương trình đang chạy. – Potatoswatter

Trả lời

2

Trong ví dụ của bạn có vẻ như bạn don' t cần CTRL-C handli ở tất cả. Một "tín hiệu (SIGINT, SIG_IGN)" có vẻ đủ cho bạn, trừ khi ứng dụng của bạn phải xử lý một SIGINT đến từ một số nguồn khác. CTRL-D thường không tạo ra tín hiệu, nó chỉ đơn giản là truyền đạt điều kiện EOF. Bạn có thể kiểm soát chung hành vi của thiết bị đầu cuối của bạn (chúng ta đang nói về đầu vào giao diện điều khiển, nó không phải là?) Bằng cách sử dụng termios library (cũng here). Bạn có thể bật, xác định lại hoặc tắt tùy chọn "gián đoạn" nhân vật (Ctrl-C), các EOF một và nhiều người khác (XON, XOFF, kiểm soát modem ...)

Trân

13

Thứ nhất, tổ hợp phím Ctrl + D là một chỉ báo EOF mà bạn không thể bẫy, khi một chương trình đang chờ đầu vào, nhấn Ctrl + D biểu thị kết thúc tệp và không mong đợi thêm đầu vào. Mặt khác, sử dụng tổ hợp phím Ctrl + C để chấm dứt một chương trình - đó là SIGINT, có thể rơi vào bẫy bằng cách làm này:

#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

Trình xử lý SIG_IGN phù hợp với nhu cầu của OP. – outis

+2

Tại sao sigact lại là biến toàn cục? Tại sao làm sạch fiddle với nó; bạn sẽ phải gọi sigaction() một lần nữa để thay đổi sigact ảnh hưởng đến cách chương trình hoạt động. –

+0

@JonathanLeffler: Ông có thể giải thích cho tôi tốt hơn tại sao không phải là một ý tưởng tốt tuyên bố sigact toàn cầu, xin vui lòng? Tôi muốn hiểu điểm này. Cảm ơn bạn. – Kyrol

31

Khi giao dịch với tín hiệu POSIX, bạn có hai phương tiện theo ý của bạn. Thứ nhất, cách dễ dàng (nhưng không được chấp nhận), signal(). Thứ hai, cách thanh lịch, hiện tại nhưng phức tạp hơn, sigaction(). Vui lòng sử dụng sigaction() trừ khi bạn thấy rằng nó không có sẵn trên một số nền tảng mà bạn cần phải làm việc trên.

This chapter hướng dẫn sử dụng glibc giải thích sự khác biệt giữa hai và cung cấp mã ví dụ tốt về cách sử dụng cả hai. Nó cũng liệt kê các tín hiệu có thể được xử lý, đề nghị cách nên xử lý và tìm hiểu sâu hơn về cách cho biết bất kỳ tín hiệu nào đã cho (hoặc không) hiện đang xử lý . Đó là cách mã nhiều hơn tôi muốn dán vào một câu trả lời ở đây, do đó các liên kết.

Nó thực sự đáng giá một hoặc hai giờ nó sẽ đưa bạn đến đọc các liên kết và làm việc thông qua các ví dụ. Xử lý tín hiệu (đặc biệt là trong các chương trình daemonize) là cực kỳ quan trọng. Một chương trình tốt nên xử lý tất cả các tín hiệu gây tử vong có thể được xử lý (nghĩa là SIGHUP) và bỏ qua một cách rõ ràng các tín hiệu mà nó có thể không sử dụng (ví dụ: SIGUSR1/SIGUSR2). Nó cũng sẽ không làm tổn thương để nghiên cứu sự khác biệt giữa tín hiệu thời gian bình thường và thời gian thực, ít nhất là lên đến sự hiểu biết về cách hạt nhân sáp nhập trước và không phải là sau này.

Khi bạn làm việc thông qua nó, bạn có thể cảm thấy có xu hướng viết lên một cách dễ dàng để sửa đổi tập hợp các chức năng để xử lý tín hiệu của bạn và sử dụng lại mã đó nhiều lần.

Xin lỗi vì đã không đưa ra một đoạn mã nhanh chóng và dơ bẩn để cho bạn thấy làm thế nào để giải quyết nhu cầu trước mắt của bạn, nhưng điều này không phải là một chủ đề nhanh chóng và dơ bẩn :)

2

Đây là một chương trình để xử lý tín hiệu khi nhấn tổ hợp phím Ctrl + c

cú pháp cho chức năng tín hiệu là: 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()' không được chấp nhận và nên tránh nếu có thể, hầu như tất cả các nền tảng hiện đại (tiết kiệm cho một số nhúng) cung cấp '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. 
Các vấn đề liên quan