2013-06-14 40 views

Trả lời

14

Như đã nói bởi những người khác, chỉ có một bộ xử lý tín hiệu có thể được đặt, đó là bộ xử lý tín hiệu cuối cùng. Sau đó, bạn sẽ phải tự quản lý hai chức năng. Chức năng sigaction có thể trả lại trình xử lý tín hiệu đã cài đặt trước đó mà bạn có thể tự gọi cho mình.

Something như thế này (mã chưa được kiểm tra):

/* other signal handlers */ 
static void (*lib1_sighandler)(int) = NULL; 
static void (*lib2_sighandler)(int) = NULL; 

static void aggregate_handler(int signum) 
{ 
    /* your own cleanup */ 
    if (lib1_sighandler) 
     lib1_sighandler(signum); 
    if (lib2_sighandler) 
     lib2_sighandler(signum); 
} 

... (later in main) 
struct sigaction sa; 
struct sigaction old; 

lib1_init(...); 
/* retrieve lib1's sig handler */ 
sigaction(SIGINT, NULL, &old); 
lib1_sighandler = old.sa_handler; 

lib2_init(...); 
/* retrieve lib2's sig handler */ 
sigaction(SIGINT, NULL, &old); 
lib2_sighandler = old.sa_handler; 

/* set our own sig handler */ 
memset(&sa, 0, sizeof(sa)); 
sa.sa_handler = aggregate_handler; 
sigemptyset(&sa.sa_mask); 
sigaction(SIGINT, &sa, NULL); 
+0

Chúng ta bỏ lỡ một 'trở lại; 'trong' if (lib1_sighandler) 'khối? –

+0

@rajraj, no, why? Chúng ta cần gọi ** cả hai ** xử lý. 'If' chỉ đảm bảo con trỏ không phải là NULL. Chỉ trong trường hợp, vì bạn không muốn va chạm bên trong một bộ xử lý tín hiệu. – Shahbaz

1

chúng tôi có thể xử lý nhiều tín hiệu với bộ xử lý tín hiệu đơn lẻ nhưng nhưng không thể có nhiều bộ xử lý tín hiệu cho cùng một tín hiệu.

void sig_handler(int signo) 
{ 
if (signo == SIGINT) 
printf("received SIGINT 1\n"); 
} 
void sig(int signo) 
{ 
    if (signo == SIGINT) 
     printf("received SIGINT 2\n"); 
} 
    int main(void) 
    { 
     if(signal(SIGINT, sig_handler) == SIG_ERR) 
      printf("\ncan't catch SIGINT\n"); 

     if (signal(SIGINT, sig) == SIG_ERR) 
      printf("\ncan't catch SIGINT\n"); 
    // A long long wait so that we can easily issue a signal to this process 
    while(1) 
     sleep(1); 
    return 0; 
    } 

nếu u cố gắng chạy mã này u sẽ tìm thấy trình xử lý tín hiệu được gán cuối cùng được đặt cho tín hiệu đó. tôi nghĩ rằng nó không thể có một xử lý tín hiệu nhiều cho cùng một tín hiệu.

6

Chỉ có thể cài đặt một bộ xử lý tín hiệu cho mỗi tín hiệu. Chỉ trình xử lý được cài đặt mới nhất sẽ hoạt động.

1

Như bạn có thể thấy trong trang hướng dẫn cho sigaction, trình xử lý tín hiệu mới sẽ thay thế thẻ cũ và bộ xử lý tín hiệu cũ được trả về.

Nếu bạn có hai tín hiệu không sử dụng (ví dụ: SIGUSR1SIGUSR2), hãy gán các tín hiệu đó cho hai bộ xử lý tín hiệu cho SIGINT. Sau đó, bạn có thể viết Trình xử lý tín hiệu của riêng bạn cho SIGINT và từ đó, bạn có thể tăng tín hiệu không sử dụng cần thiết theo ý muốn.

1

Shabaz nhấn đinh trên đầu. Tuy nhiên, nếu bạn đang tìm kiếm một cái gì đó tất cả các thư viện của bạn có thể sử dụng (với điều kiện bạn có quyền truy cập vào mã nguồn), bạn có thể làm một cái gì đó dọc theo dòng sau đây:

linked_list* sigint_handlers = NULL; 

void sighand_init(sighand_config_t* config) { 
    struct sigaction action; 
    memset(&signalaction, 0, sizeof(signalaction)); 
    action.sa_handler = &sighand_main; 

    // Order is important, in case we get a signal during start-up 
    sigint_handlers = linked_list_new(); 
    sigaction(SIGINT, &action); 
} 

void sighand_main(int signum) { 
    if (signum == SIGINT) { 
     linked_list_node* node = linked_list_head(sigint_handlers); 
     while ((node = node->next) != NULL) { 
      node->object(signum); 
     } 
     if (sighand_config.exitonint) { 
      app_exit(0); 
     } 
    } 
} 

void sighand_add_int_handler(void (*handler)(int)) { 
    if (handler == NULL) return; 
    linked_list_add(sigint_handlers, handler); 
} 

void sighand_destroy() { 
    ... 
    linked_list_destroy(signint_handlers); 
    ... 
} 

Hoặc, bạn có thể sử dụng này cho mình, và sau khi tải từng thư viện, hãy xử lý và sau đó gọi add_handler. Một cái gì đó dọc theo dòng:

loadlibrary(lib1.so); 
sigaction1 = signalget(SIGINT); 

loadlibrary(lib2.so); 
sigaction2 = signalget(SIGINT); 

sighand_init(...); 
sighand_add_int_handler(sigaction1.sa_handler); 
sighand_add_int_handler(sigaction2.sa_handler); 

Chỉ cần một vài suy nghĩ, Anthony

Các vấn đề liên quan