2013-02-28 73 views
2

所以這是我現在有的問題,我創建了2個不同的程序(1將管理另一個,而另一個將被執行多次)。程序將通過信號來回傳遞。我的問題是,是否有可能(以及如何)獲得發送信號的程序的進程ID。 我的程序使用signal()來捕獲信號並kill()發送它們。C - 獲取信號處理的進程ID

回答

2

請勿使用signal(),它已過時。如果有,請使用sigaction(),它提供了一個接口來獲取發件人的進程ID。

+1

它不會捕獲sigkill和sigstop。例如,如果您從第二個進程按ctrl + c,它將不會被sigaction()捕獲。 – 2013-02-28 08:30:16

+0

嗯,那很好,我怎麼用sigaction()來捕捉它? – Chris 2013-02-28 08:33:01

+0

@Chris:對於一個'sigaction()'示例以及關於信號處理的索引刷新,請看[本文](http://lazarenko.me/2013/01/15/how-not-to-write -a-signal-handler /),這是我前一段時間寫的。 – 2013-02-28 14:48:04

3

儘管signal()是標準C庫,但該函數不是可移植的,其行爲取決於系統。更好地使用POSIX.1的sigaction()。

下面是如何使用的sigaction用處理程序空隙ħ(INT SIG)的例子:

int mysignal (int sig, void (*h)(int), int options) 
{ 
    int r; 
    struct sigaction s; 
    s.sa_handler = h; 
    sigemptyset (&s.sa_mask); 
    s.sa_flags = options; 
    r = sigaction (sig, &s, NULL); 
    if (r < 0) perror (__func__); 
    return r; 
} 

選項在人的sigaction說明。一個不錯的選擇是options=SA_RESTART

要知道發送信號的進程的PID,請設置options=SA_SIGINFO,並使用sa_sigaction回調代替sa_handler;它將收到一個siginfo_t結構,它有一個si_pid字段。您可以使用sigqueue將數據與信號相關聯。

一般來說,使用信號以安全的方式通信是一個壞主意(當發送n個信號時,只有第一個信號有機會被傳送;沒有掛鉤來關聯其他數據;可用的用戶信號只有兩個)。更好地使用管道,命名管道或套接字。

1

要獲得發送信號的進程的進程ID,您需要在選項SA_SIGINFO中包含該進程。如果你這樣做,sigaction的接口稍有不同。這裏是一個正確的處理程序的例子,以及如何設置它。 (包括我SA_RESTART的,只是因爲它通常是一個好主意的選項,但不是必需的)

// example of a handler which checks the signalling pid 
void handler(int sig, siginfo_t* info, void* vp) { 
    if (info->si_pid != getpid()) { 
    // not from me (or my call to alarm) 
    return; 
    } 
    // from me. let me know alarm when off 
    alarmWentOff = 1; 
} 

這裏是我的設置處理器通用代碼:

typedef void InfoHandler(int, siginfo_t *, void *); 

InfoHandler* 
SignalWithInfo(int signum, InfoHandler* handler) 
{ 
    struct sigaction action, old_action; 

    memset(&action, 0, sizeof(struct sigaction)); 
    action.sa_sigaction = handler; 
    sigemptyset(&action.sa_mask); /* block sigs of type being handled */ 
    action.sa_flags = SA_RESTART|SA_SIGINFO; /* restart syscalls if possible */ 

    if (sigaction(signum, &action, &old_action) < 0) 
perror("Signal error"); 
    return (old_action.sa_sigaction); 
} 

最後,對於這種特殊情況:

SignalWithInfo(SIGALRM, handler); 
-1

它現在改變了。信號信息顯示不是1 pid,而是簡單的數字號碼。這符合killall過程。可能是枚舉/ proc /目錄,找到/ proc/DIGIT,打開/ proc/DIGIT/comm,讀取並關閉它。可能是,acueried名稱將被「關機」或「重啓」