Unix环境高级编程(三)信号专题(1)

2 篇文章 0 订阅
1 篇文章 0 订阅

Unix环境高级编程(三)信号专题(1)

原文连接:访问原文

中断的概念

要了解信号的概念,先要了解什么是中断?中断是系统对于异步事件的响应,所谓异步事件的响应就是指:

进程执行代码的过程中可以随时被打断,然后去执行异常处理程序生活中的中断和计算机系统中的中断。

中断的组成包括:

中断信号
* 中断源
* 现场信息
* 中断处理程序
* 中断向量表

这和我们生活中的一些例子很像,比如:张三看书,设置闹钟,厨房烧水。闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读。

其中中断分为两类:硬中断和软中断
硬中断也称外部中断,是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断。
软中断也称内部中断,是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断。

信号的概念

信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断。
首先,每个信号都有一个名字。这些名字都以三个字符SIG开头。例如,SIGABRT是夭折信号,当进程调用abort函数时产生这种信号。
信号的定义在头文件<signal.h>中这些信号都被定义为正整数,范围在1~64。其中1~32号信号是不可靠信号,33~64为前32种不可重入信号的可靠版本,其名称在不可靠信号名称加R。我们可以通过命令kill -l来查看Linux内核支持的信号,64中信号如下:
enter description here

信号和中断的异同

  • 信号与中断的相似点:
    1. 采用了相同的异步通信方式;
    2. 当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;
    3. 都在处理完毕后返回到原来的断点;
    4. 对信号或中断都可进行屏蔽。
  • 信号与中断的区别:
    1. 中断有优先级,而信号没有优先级,所有的信号都是平等的;
    2. 信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;
    3. 中断响应是及时的,而信号响应通常都有较大的时间延迟。

信号名称及常用信号

信号名称描述
SIGABRT进程停止运行
SIGALRM警告钟
SIGFPE算述运算例外
SIGHUP系统挂断
SIGILL非法指令
SIGINT终端中断
SIGKILL停止进程(此信号不能被忽略或捕获)
SIGPIPE向没有读者的管道写入数据
SIGSEGV无效内存段访问
SIGQUIT终端退出
SIGTERM终止
SIGUSR1用户定义信号1
SIGUSR2用户定义信号2
SIGCHLD子进程已经停止或退出

信号的处理

进程对信号有三种处理:
1. 忽略信号
不采取任何操作、有两个信号不能被忽略:SIGKILL(9号信号)和SIGSTOP。
2. 捕获并处理信号
内核中断正在执行的代码,转去执行先前注册过的处理程序。SIGKILL(9号信号)和SIGSTOP不能被捕获。
3. 执行默认操作
默认操作通常是终止进程,这取决于被发送的信号。

这里要理解为什么以上两种信号(SIGKILL和SIGSTOP)不能被忽略。其原因是:如果应用程序可以忽略这2个信号,系统管理无法杀死、暂停进程,无法对系统进行管理。

signal函数

signal函数有两个作用:
1. 站在应用程序的角度,注册一个信号处理函数;
2. 忽略信号、设置信号默认处理 信号的安装和恢复。

其函数定义如下:

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

signum指定信号种类,handler指定信号的处理函数,也可以是下面两个特殊值:SIG_IGN(屏蔽该信号)和 SIG_DFL(恢复默认行为)。
signal返回原先的信号处理句柄,出错时返回SIG_ERR,并设置error值。

singnal编程实战

我们先来写一个信号处理函数,这个信号处理函数,实现打印信号值得功能,并且判断信号是否是SIGQUIT,如果是就退出进程。

void handler(int num)
{
    printf("recv num:%d \n", num);
}

在主函数中,我们注册此信号,并使进程进入暂停此时用户按(ctrl+c)将执行打印函数,程序无法退出,直到用户键入字符‘a’为止,我们让信号恢复默认行为,再执行==ctrl+c==时,程序退出。

void main()
{
    char   tmpchar;
    signal(SIGINT, handler);

    printf("if you input 'a' will recove the default behavior of signal\n");
    while((tmpchar = getchar()) != 'a')
    {
        pause();
    }

    //让这个信号恢复默认行为
    signal(SIGINT, SIG_DFL);
    while(1)
    {
        pause();
    }
    printf("main----end\n");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值