Linux信号编程概述

中断

中断是系统对于异步事件的响应, 进程执行代码的过程中可以随时被打断,然后去执行异常处理程序;

计算机系统的中断场景:中断源发出中断信号 -> CPU判断中断是否屏蔽屏蔽以及保护现场 -> CPU(查询中断向量表, 找到中断服务程序的入口地址)执行中断处理程序 ->(处理完中断之后) ->恢复现场,继续执行原来的任务

中断分类

硬件中断(外部中断)

外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断

软件中断(内部中断)

内部中断是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断(如:执行除0操作, 由用户空间陷入内核空间等)。

信号

信号是UNIX/Linux系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。信号一般是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等;信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断;

信号与中断的相似点:

(1)采用了相同的异步通信方式;

(2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;

(3)都在处理完毕后返回到原来的断点;

(4)对信号或中断都可进行屏蔽。

信号与中断的区别:

(1)中断有优先级,而信号没有优先级,所有的信号都是平等的;

(2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;

(3)中断响应是及时的,而信号响应通常都有较大的时间延迟。

常用信号:

在这里插入图片描述

进程对信号的响应

忽略信号

不采取任何操作、有两个信号不能被忽略:SIGKILL和SIGSTOP。

[为什么进程不能忽略SIGKILL/SIGSTOP信号。(如果应用程序可以忽略这2个信号,系统管理无法杀死、暂停进程,无法对系统进行管理。)]

捕获并处理信号

内核中断正在执行的代码,转去执行先前注册过的处理程序。

执行默认操作

默认操作通常是终止进程,这取决于被发送的信号。

信号的默认操作:通过 man 7 signal 查看

在这里插入图片描述

信号安装-signal

typedef void (*__sighandler_t) (int);
#define SIG_ERR ((__sighandler_t) -1)
#define SIG_DFL ((__sighandler_t) 0)
#define SIG_IGN ((__sighandler_t) 1)
__sighandler_t signal(int signum, __sighandler_t handler);

参数

signal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出

handler这个函数必须有一个int类型的参数(即接收到的信号代码),它本身的类型是void, handler也可以是下面两个特殊值:

SIG_IGN 屏蔽该信号
SIG_DFL 恢复默认行为

//示例1
void handler(int sigNum)
{
    cout << "recv a signal = " << sigNum << endl;
}
 
int main(int argc, char *argv[])
{
    signal(SIGINT, handler);
    while (true)
        sleep(1);
}

RETURN VALUE

signal() returns the previous value of the signal handler, or SIG_ERR on error.

In the event of an error, errno is set to indicate the cause.

int main(int argc, char *argv[])
{
    sighandler_t oldHandler = signal(SIGINT, handler);
    if (oldHandler == SIG_ERR)
        err_exit("signal error");
 
    while (getchar() != '\n')
        sleep(1);
 
    // 等价于 signal(SIGINT, SIG_DFL)
    if (signal(SIGINT, oldHandler) == SIG_ERR)
        err_exit("signal error");
 
    while (true)
        sleep(1);
}
//实例: 捕获所有信号, 并打印信号的信息
int main()
{
    for (int i = 1; i < NSIG; ++i)
    {
        if (signal(i, sigHandler) == SIG_ERR)
        {
            cerr << "signal " << i << ": " << strsignal(i) << " set error";
            cerr << ", errno desc: " << strerror(errno) << endl;
        }
    }
 
    while (true)
        pause();
}
 
void sigHandler(int signo)
{
    cout << "catch a signal, signo = " << signo << ", desc: " << strsignal(signo) << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值