Posted on 2007-09-05 12:22
ZelluX 阅读(350)
评论(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