2012年2月1日 星期三

從 /proc/PID/status 了解執行中程式處理 signal 的方式

man proc 可得知在 /proc/PID/status 裡有給人讀的 process 資訊, 其中 SigXXX 是關於 signal 的處理方式, 比方 SigIgn 表示忽略該 signal; SigCgt 表示有註冊自己的 signal handler。

比較需要花點心思的地方, 在於怎麼讀 signal mask。這裡有提到解碼方式, 每個數字用四個 bit 表示四個號碼, 從最右側開始遞增。

以這個程式為例:

#include <stdio.h>
#include <signal.h>

void handler(int signum) {
}

int main(void) {
    signal(SIGQUIT, SIG_IGN);
    signal(SIGHUP, handler);
    signal(SIGPIPE, handler);
    while (1) ;
    return 0;
}

它的 /proc/PID/status 如下:

SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000004
SigCgt: 0000000000001001

表示 3 號 signal (SIGQUIT) 設為 ignore (1, 2, 4 -> 4 表示第三個號碼), 1 號和 13 號 (SIGHUP 和 SIGPIPE) 有註冊 handler。signal 的號碼可從 man 7 signal 得知, 或在 include signal.h 後, 用 gcc -E -dD 展開看也可以。

2012-02-02 更新

Scott 在留言提供正式的解釋, 附註在此:

這是用 16 進位顯示一個 64 bit 的 bitmask,每個 bit 對應到一個 signal。 bits 從 0 開始編號而 Linux signals 從 1 開始編號,故 bit 0 代表 1 號 signal (SIGHUP), bit 1 代表 2 號 signal (SIGINT)。

原本寫的時候想不起來正式的說法, 想說就隨手寫個「白話版」吧。原本的「白話版」也留著, 有不同描述方式, 應該多少會有幫助吧。

4 則留言:

  1. > 表示 3 號 signal (SIGQUIT) 設為 ignore (1, 2, 4 -> 4 表示第三個號碼)

    老天爺,初學者看到了真的這樣數而不是取 log2 還得了。整數中的 bit 還是要從 0 開始編號啦:

    SigIgn: 0000000000000004
    中只有 bit 2 是 1, 代表 3 號 signal (SIGQUIT),設為 ignore (Linux signals 從 1 開始編號)

    SigCgt: 0000000000001001
    中 bit 0 與 12 是 1,代表 1 號和 13 號 signal (SIGHUP 和 SIGPIPE) 有註冊 handler

    回覆刪除
  2. 平時都直接背 2**i = x 來查 i, 久了都忘了有個標準函數叫 log2 ...

    回覆刪除
  3. > 每個數字用四個 bit 表示四個號碼, 從最右側開始遞增

    『一般人』不會這樣講,我們會說:『這是用 16 進位顯示一個 64 bit 的 bitmask,每個 bit 對應到一個 signal。 bits 從 0 開始編號而 Linux signals 從 1 開始編號,故 bit 0 代表 1 號 signal (SIGHUP), bit 1 代表 2 號 signal (SIGINT)。』

    『用 16 進位顯示』一般當然也不用講,因為只有 16 進位與 2 進位兩種選擇,而從情境看得出不是 2 進位。

    回覆刪除
  4. 多提 16 進位表示也不錯, 我將它補進去了, 謝啦

    回覆刪除

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...