
正文
三十、Linux 进程与信号——信号的概念及 signal 函数
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
30.1 信号的基本概念
-
信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化
-
信号是软件中断
-
信号是异步事件
-
不可预见
-
信号有自己的名称和编号
-
信号和异常处理机制
-
信号发生的来源
-
硬件来源:如按下键盘或其他硬件故障,信号是由驱动程序产生
-
软件来源:最常用发送信号的系统函数是 kill(),raise(),alarm() 和 setitimer() 等函数,软件来源还包括一些非法运算等操作,软件设置条件(如:gdb调试),信号是由内核产生。
- 不可预见
- 信号有自己的名称和编号
- 信号和异常处理机制
- 硬件来源:如按下键盘或其他硬件故障,信号是由驱动程序产生
- 软件来源:最常用发送信号的系统函数是 kill(),raise(),alarm() 和 setitimer() 等函数,软件来源还包括一些非法运算等操作,软件设置条件(如:gdb调试),信号是由内核产生。
查看系统当中的信号:kill -l
-
[1 ~ 31] 信号称为非实时信号
- 发送的信号可能丢失,不支持信号排队
-
[32 ~ 64] 信号称为实时信号
- 发送的多个实时信号都会被接受,支持信号排队
- 信号无优先 信号定义的地方:/usr/include/bits/signum.h 和 signum-generic.h
30.2 信号的处理和变革
30.2.1 信号的处理
-
忽略信号
-
SIGKILL 和 SIGSTOP 永远不能忽略
-
忽略硬件异常
-
进程启动时 SIGUSR1 和 SIGUSR2 两个信号被忽略
-
执行默认操作
-
每个信号有默认动作,大部分信号默认动作是终止进程
-
捕获信号
-
告诉内核出现信号时调用自己的处理函数
-
SIGKILL 和 SIGSTOP 不能被捕获
30.2.2 信号变革
-
信号出现在早期的 UNIX 中
-
早期信号模型是不可靠的
-
BSD 和 SYSTEM V 分别对早期信号进行扩展,但是相互不兼容
-
POSIX 统一了上述两种模型,提供了可靠信号模型
30.3 signal 函数
#include <signal.h>
void (*signal(int signo, void (*func)(int )))(int );
-
函数功能:向内核登记信号处理函数
-
函数参数:
-
signo:要登记的信号值
-
func:
-
信号处理函数指针
-
SIG_IGN:忽略信号
-
SIG_DFL:采用系统默认的方式处理信号,执行默认操作
-
返回值:若成功,则返回先前的信号处理函数指针,出错,则返回 SIG_ERR
- SIGKILL 和 SIGSTOP 永远不能忽略
- 忽略硬件异常
- 进程启动时 SIGUSR1 和 SIGUSR2 两个信号被忽略
- 每个信号有默认动作,大部分信号默认动作是终止进程
- 告诉内核出现信号时调用自己的处理函数
- SIGKILL 和 SIGSTOP 不能被捕获
#include <signal.h>
void (*signal(int signo, void (*func)(int )))(int );
- 函数功能:向内核登记信号处理函数
-
函数参数:
- signo:要登记的信号值
-
func:
- 信号处理函数指针
- SIG_IGN:忽略信号
- SIG_DFL:采用系统默认的方式处理信号,执行默认操作
- 返回值:若成功,则返回先前的信号处理函数指针,出错,则返回 SIG_ERR
signal 函数原型如下:
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h> /** 定义信号处理函数
* signo 进程捕获到的信号
*/
void sig_handler(int signo)
{
printf("%d, %d occured\n", getpid(), signo);
} int main(void)
{
/** 向内核登记信号处理函数以及信号值 */
if(signal(SIGTSTP, sig_handler) == SIG_ERR) {
perror("signal sigtstp error");
} if(signal(SIGINT, sig_handler) == SIG_ERR) {
perror("signal sigint error");
} if(signal(SIGUSR1, sig_handler) == SIG_ERR) {
perror("signal usr1 error");
} if(signal(SIGUSR2, sig_handler) == SIG_ERR) {
perror("signal usr2 error");
} if(signal(SIGKILL, SIG_IGN) == SIG_ERR) {
perror("signal sigtstp error");
} if(signal(SIGSTOP, SIG_IGN) == SIG_ERR) {
perror("signal sigint error");
}
int i = ;
while(i < ) {
printf("%d out %d\n", getpid(), i++);
sleep();
} return ;
}







