2012-04-18 58 views
0

我正試圖編寫簡單的程序,在Linux中使用實時信號。但是,我遇到了奇怪的現象,首先代碼:Linux和實時信號

#include<signal.h> 
#include<sys/types.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include"errhandling.h" 
#include<string.h> 
#include<errno.h> 
#include<unistd.h> 

void baz(int sig,siginfo_t* info,void *context) 
{ 
    if (sig==SIGUSR1) 
     printf("SIGUSR1 %d\n",info->si_value.sival_int); 
    else if(sig==SIGRTMIN) 
     printf("SIGRTMIN %d\n",info->si_value.sival_int); 
    else 
     printf("SIGRTMIN+1 %d\n",info->si_value.sival_int); 
    return ; 
} 

void sig_output() 
{ 
    sigset_t set; 
    sigprocmask(0,NULL,&set); 
    printf("blokowane sa: "); 
    if (sigismember(&set,SIGUSR1)) 
     printf("SIGUSR1 "); 
    if(sigismember(&set,SIGUSR2)) 
     printf(" SIGUSR2"); 
    printf("\n"); 
    return ; 
} 


int received=0; 
int usr2=0; 

void foo(int sig) 
{ 
    return ; 
} 

void usr1_handler(int sig) 
{ 
    printf("usr1_handler\n"); 
    //++received; 
} 



void usr2_handler(int sig) 
{ 
    usr2=1; 
} 

int main(int argc,char **argv) 
{ 
    int i=0; 
    pid_t pid=getppid(); 
    struct sigaction a; 
    struct sigaction a2; 
    a.sa_flags=SA_SIGINFO; 
    sigset_t set; 
    sigemptyset(&set); 
    //sigaddset(&set,SIGRTMAX); 
    sigemptyset(&(a.sa_mask)); 
    sigemptyset(&(a2.sa_mask)); 
    a.sa_sigaction=baz; 
    sigaction(SIGRTMIN,&a,NULL); 
    a2.sa_handler=usr1_handler; 
    sigaction(SIGRTMIN+1,&a2,NULL); 
    //sigprocmask(SIG_SET,&(a.sa_mask),NULL); 
    while(!usr2) 
    { 
     printf("while\n"); 
     sigsuspend(&set); 

    } 
     //pause() 
    printf("after while\n"); 
    return EXIT_SUCCESS; 
} 

當我運行這個程序,它進入這個循環與sigsuspend我送這個節目SIGRTMIN一切正常的話 - 處理程序執行,並等待另一個信號,但當我發送SIGRTMIN + 1時,出現分段錯誤。

看來,實時信號我需要使用這個擴展的處理程序與3個參數,但爲什麼?它在某處指定了嗎?我在我的朋友OpenSUSE 12.1上運行這個程序,並且我沒有爲SIGRTMIN + 1得到分段錯誤,但是在我的Xubuntu 11.10上,當我發送SIGRTMIN + 1時,出現分段錯誤。我的系統有問題嗎?還是它依賴於實現?

+3

第1課:在信號處理程序不使用printf()函數。 – wildplasser 2012-04-18 12:19:04

+0

我知道這一點 - 這只是出於沮喪,因爲我想獲得一些信息 - 如果他進入我的信號處理程序。 – Andna 2012-04-18 12:21:11

+0

用vsnprintf()把它替換成本地緩衝區和write(),你可能就沒事了。 – wildplasser 2012-04-18 12:22:35

回答

2

看來你缺少一個處理程序分配給a2.sa_sigaction


一般來說,是不是由原始的整數值是指信號,作爲定義的各種信號可能是特定於平臺的好主意。


Update:確保struct sigaction結構由例如memset()荷蘭國際集團他們正確初始化爲0。

+0

你是對的 - 它在複製代碼期間失蹤了,我改變了第一篇文章,我仍然得到SIGRTMIN + 1 – Andna 2012-04-18 12:25:52

1

不要使用printf()和朋友在信號處理中。不要固執......這是一個替代品。

#include <stdarg.h> 

int myprintf(const char *fmt, ...); 
int myprintf(const char *fmt, ...) 
{ 
    va_list args; 
    char buff[512]; 
    int rc; 

    va_start(args, fmt); 

    rc = vsnprintf (buff, sizeof buff, fmt, args); 
    va_end (args); 

    if (rc >0 && rc < sizeof buff) write(1, buff, rc); 

    return rc; 
} 

UPDATE:這似乎工作:

#include <signal.h> 
#include <sys/types.h> 
#include <stdlib.h> 
#include <stdio.h> 
#pragma #include"errhandling.h" 
#include <string.h> 
#include <errno.h> 
#include <unistd.h> 
#include <stdarg.h> 

int myprintf(const char *fmt, ...); 
int myprintf(const char *fmt, ...) 
{ 
    va_list args; 
    char buff[512]; 
    int rc; 

    va_start(args, fmt); 
    rc = vsnprintf (buff, sizeof buff, fmt, args); 
    va_end (args); 

    if (rc > 0 && rc < sizeof buff) write(1, buff, rc); 

    return rc; 
} 

void baz(int sig, siginfo_t *info, void *context) 
{ 
#define INFO_VAL(p) p?p->si_value.sival_int:0 
    if (sig==SIGUSR1) 
     myprintf("SIGUSR1 %d\n", INFO_VAL(info)); 
    else if(sig==SIGRTMIN) 
     myprintf("SIGRTMIN %d\n", INFO_VAL(info)); 
    else 
     myprintf("SIGRTMIN%+d %p\n", sig-SIGRTMIN, INFO_VAL(info)); 
    return ; 
#undef INFO_VAL 
} 

void sig_output() 
{ 
    sigset_t set; 
    sigprocmask(0,NULL,&set); 
    myprintf("blokowane sa: "); 
    if (sigismember(&set,SIGUSR1)) 
     myprintf("SIGUSR1 "); 
    if(sigismember(&set,SIGUSR2)) 
     myprintf(" SIGUSR2"); 
    myprintf("\n"); 
    return ; 
} 
volatile int received=0; 
volatile int usr2=0; 

void foo(int sig) 
{ 
    return ; 
} 

void usr1_handler(int sig) 
{ 
    myprintf("usr1_handler\n"); 
    //++received; 
} 



void usr2_handler(int sig) 
{ 
    usr2=1; 
} 

int main(int argc,char **argv) 
{ 
    int i=0; 
    pid_t pid=getppid(); 
    struct sigaction a, a2; 
    sigset_t set; 

    sigemptyset(&set); 
    //sigaddset(&set,SIGRTMAX); 
    sigemptyset(&a.sa_mask); 
    sigemptyset(&a2.sa_mask); 
    a.sa_flags = 0; 
    a2.sa_flags = SA_SIGINFO; 
    a2.sa_sigaction = baz; 
    a.sa_handler = usr1_handler; 
    sigaction(SIGUSR1,&a,NULL); 

    a.sa_handler = usr2_handler; 
    sigaction(SIGUSR2,&a,NULL); 

    sigaction(SIGRTMIN+1,&a2,NULL); 
    sigaction(SIGRTMIN+2,&a2,NULL); 
    sigaction(SIGRTMIN+3,&a2,NULL); 
    //sigprocmask(SIG_SET,&(a.sa_mask),NULL); 
    while(!usr2) 
    { 
     myprintf("while(!usr2)\n"); 
     sigsuspend(&set); 

    } 
     //pause() 
    myprintf("after while\n"); 
    return EXIT_SUCCESS; 
} 
+0

的段錯誤我敢打賭這個'a.sa_flags = 0;'完成了這項工作。 – alk 2012-04-18 14:31:48

+0

是的,metoo。我在你的回答中看到了,而我已經把它放到了我的本地副本中。 (a和a2的處理在很多地方有所不同) – wildplasser 2012-04-18 14:39:59

+0

這沒有幫助。 'snprintf'沒有被指定爲異步信號安全的,並且在現實世界中(例如glibc),它是非常異步信號不安全的(它甚至稱爲「malloc」)。理想情況下'snprintf' *應該被指定爲異步信號安全的,但是讓每個人修復其不好的實現並不是一件容易的事情... – 2012-04-18 14:40:00