CSAPP - Explicitly Blocking Signals
Posted on 2007-09-05 12:22 ZelluX 閱讀(360) 評論(0) 編輯 收藏 所屬分類: System看了半天總算對這節有了個大致的感覺,首先看幾個和sigprocmask相關的函數:
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum); // Return: 0 if OK, -1 on error
int sigismember(const sigset_t *set, int signum); // Return: 1 if member, 0 if not, -1 on error
sigprocmask用于改變當前blocked signals的集合,how參數指定了具體的行為:
SIG_BLOCK 把set中的信號添加到blocked列表(blocked = blocked | set)
SIG_UNBLOCK 把set中的信號從blocked列表中移出(blocked = blocked & ~set)
SIG_SETMASK blocked = set
另外,如果oldset的值不是NULL的話,之前的blocked列表會保存在oldset中。
而sigaddset sigdelset sigfillset sigemptyset都是用于操作sigset_t列表的函數。
sigprocmask適用于在父子進程間同步的情況,以一個典型的UNIX shell程序為例,父進程需要在一個job list中記錄它所有的子進程,當父進程創建一個子進程時,它把子進程加入到job list中;當父進程reap一個子進程時,就從job list中移出這個進程。
如果不同步父子進程,有可能發生這種情況:
1. 父進程執行fork函數,內核調度新創建的子進程替換父進程運行
2. 在父進程能夠再次運行前,子進程終止,成為一個zombie,內核發送SIGCHLD信號給父進程
3. 父進程可以運行前,內核發現了未處理的(pending)SIGCHLD信號,讓它由父進程的handler處理
4. handler reap了終止的進程,調用deletejob函數,實際上沒有任何作用,因為父進程還沒有把該子進程加入列表
5. handler完成后,內核繼續運行父進程,后者調用fork完成后繼續,錯誤地把不存在的子進程加入了job list
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum); // Return: 0 if OK, -1 on error
int sigismember(const sigset_t *set, int signum); // Return: 1 if member, 0 if not, -1 on error
sigprocmask用于改變當前blocked signals的集合,how參數指定了具體的行為:
SIG_BLOCK 把set中的信號添加到blocked列表(blocked = blocked | set)
SIG_UNBLOCK 把set中的信號從blocked列表中移出(blocked = blocked & ~set)
SIG_SETMASK blocked = set
另外,如果oldset的值不是NULL的話,之前的blocked列表會保存在oldset中。
而sigaddset sigdelset sigfillset sigemptyset都是用于操作sigset_t列表的函數。
sigprocmask適用于在父子進程間同步的情況,以一個典型的UNIX shell程序為例,父進程需要在一個job list中記錄它所有的子進程,當父進程創建一個子進程時,它把子進程加入到job list中;當父進程reap一個子進程時,就從job list中移出這個進程。
如果不同步父子進程,有可能發生這種情況:
1. 父進程執行fork函數,內核調度新創建的子進程替換父進程運行
2. 在父進程能夠再次運行前,子進程終止,成為一個zombie,內核發送SIGCHLD信號給父進程
3. 父進程可以運行前,內核發現了未處理的(pending)SIGCHLD信號,讓它由父進程的handler處理
4. handler reap了終止的進程,調用deletejob函數,實際上沒有任何作用,因為父進程還沒有把該子進程加入列表
5. handler完成后,內核繼續運行父進程,后者調用fork完成后繼續,錯誤地把不存在的子進程加入了job list