信号提供了一种处理 异步事件 的方法,产生信号的时间对进程而言是随机出现的。
signal函数
void (*signal (int signo, void (*func)(int))(int);
:signal的参数列表为一个信号值signo,一个 void (*)(int)型的函数指针,返回值为 void (*)(int) 型的
- func的取值:
- 常数 SIG_IGN:忽略信号(SIGKILL和SIGSTOP是不能忽略的)
- 常数 SIG_DEF:采用系统默认动作
- 当接到此信号后要调用的函数的地址
- signal 函数相当于一个注册作用,它让进程可以告诉内核,当指定的信号到来时,应该采取什么操作。
进程创建和启动
- 进程调用 fork 时,子进程继承父进程的信号处理方式
- exec时,原先设置为要捕捉的信号都改为系统默认动作,其他信号不变
- 例如 shell 处理后台作业的中断和退出信号,shell自动将后台作业中对中断和退出信号的处理方式设置为忽略。这样在按中断键,后台作业就不会受到影响
中断的系统调用:
- 如果在进程执行一个低速的系统调用而阻塞,期间捕捉到一个信号,则该系统调用就被中断不再继续
- 被中断的系统调用的自动再启动:被中断时,自动重新启动
可重入函数:
- 可以被中断的函数,在函数的任何执行时刻中断它,OS转而去执行其他代码,而返回该函数时不会发生什么错误
- 不可重入的函数:由于使用了一些系统资源,比如全局变量区,中断向量表等,如果被中断的话,会出现问题
信号相关的函数:
- kill:
int kill(pid_t pid, int signo);
- pid > 0:把信号发给ID为pid的进程
- pid == 0:把信号发送给与发送进程同一进程组,且发送进程有权向其发送信号的进程
- pid < 0:发送给进程组ID等于pid绝对值,且发送进程有权向其发送
- raise:
int raise(int signo);
:向自身发送信号- alarm:
unsigned int alarm(unsigned int seconds);
:设置一个时钟值,当超时时产生一个SIGALRM信号- pause:使进程挂起,直到捕捉到一个信号
信号阻塞:
- 让系统暂时保留信号,待以后发送,信号会在解除阻塞后继续传递
- 使用 sigprocmask() 阻塞信号的传递。一般在要操作一些全局变量前,用 sigprocmask 阻塞信号,在操作结束后恢复信号的传递。
- 信号集:sigset_t
- 初始化: sigemptyset、sigfillset,成功返回0,失败返回 -1
-
int sigemptyset(sigset_t * set);
:不包含任何信号的信号集 -
int sigfillset(sigset_t * set);
:包含所有信号的信号集
-
- 增删信号:sigaddset、sigdelset,成功返回0,失败返回 -1
int sigaddset(sigset_t * set, int signo);
int sigdelset(sigset_t * set, int signo);
- 判断是否存在:
int sigismember(const sigset_t * set, int signo);
,是则返回1,否则返回0
- 初始化: sigemptyset、sigfillset,成功返回0,失败返回 -1