APUE编程:70---信号处理(信号概念及分类)

一、信号的定义与编号

  • 首先,每个信号都有一个名字。这些名字都以三个字符SIG开头
  • 在头文件#include<signal.h>中,信号名都被定义为正整数常量
  • 注意事项:
    • 实际上,实现将各信号定义在另一个头文件中,但是该头文件有包括在<signal.h>中,内核包括对用户级应用程序有意义的头文件,这被认为是一种不好的形式
    • 所以如若应用程序和内核两者都需要使用同一定义,那么就将有关信息放置在内核头文件中,然后用户级头文件再包括该内核头文件
    • 于是,FreeBSD 8.0和Mac OS X10.6.8将信号定义在<sys/signal.h>中,Linux 3.2.0将信号定义在<bits/signum.h>中,Solaris 10将信号定义在<sys/iso/signal_iso.h>中

编号为0的信号

  • 不存在编号为0的信号
  • kill函数对信号编号为0有特殊的应用。POSIX.1将此种信号编号值成为空信号

二、产生信号的条件

  • ①当用户按某些终端键时,引发终端产生的信号例如在终端按Delete键(或者许多系统中的Ctrl+C键)通常产生中断信号(SIGINT),这是停止一个已失去控制程序的方法
  • ②硬件异常产生信号:除数为0、无效的内存引用等。这些条件通常由硬件检测到,并通知内核。然后内核为该条件发生时正在运行的进程产生适当的信号。例如,对执行一个无效内存引用的进程产生SIGSEGV信号
  • ③进程调用kill函数可将任意信号发送给另一个进程或进程组。当然kill函数有一些限制:接收信号进程和发送信号进程的所有者必须相同,或发送信号进程的所有者必须是超级用户
  • ④用户可用kill命令将信号发送给其他进程。此命令只是kill函数的接口
  • ⑤当检测到某种软件条件已经发生,并应将其通知有关进程时也产生信号。这里指的不是硬件产生条件(如除以0),而是软件条件。例如SIGURG(在网络连接上传来带外的数据)、SIGPIPE(在管道的读进程已终止,一个进程写此管道)、SIGALRM(进程所设置的定时器已经超时)

三、信号的处理

  • 产生信号的事件对进程而言是随机出现的。进程不能只是测试一个变量(例如errno)来判别是否发生了一个信号,而是必须告诉内核“在此信号发生时,请执行下列操作”
  • 信号的处理有三种方式

方式一:忽略此信号

  • 大多数信号都可使用这种方式进行处理,但有两种信号却决不能被忽略。 它们是:SIGKILL和SIGSTOP
  • 这两种信号不能被忽略的原因是:它们向超级用户提供一种使进程终止或停止的可靠方法。另外,如果忽略某些由硬件异常产生的信号(例如非法存储访问或除以0),则进程的行为是未定义的

方式二:捕捉信号

  • 为了做到这一点要通知内核在某种信号发生时,调用一个用户函数。在用户函数中,可执行用户希望对这种事件进行的处理
  • 例如,若编写一个命令解释器,当用户用键盘产生中断信号时,很可能希望该命令解释器返回到主循环,终止正在为该用户执行的命令。 如果捕捉到SIGCHLD信号,则表示子进程已经终止,所以此信号的捕捉函数可以调用waitpid以取得该子进程的进程ID以及它的终止状态
  • 又例如,如果进程创建了临时文件,那么可能要 为SIGTERM信号编写一个信号捕捉函数以清除临时文件(SIGTERM是终止信号,kill命令传送的系统默认信号是终止信号)
  • 注意:不能捕捉SIGKILL和SIGSTOP信号

方式三:执行系统默认动作

  • 不同的信号默认动作不同
  • 对大多数信号的系统默认动作是终止该进程

四、信号的注意事项

  • 1.SIGKILL和SIGSTOP信号不能被忽略和捕捉
  • 2.当一个进程调用fork时,其子进程继承父进程的信号处理方式。因为子进程在开始时复制了父进程内存映像,所以信号捕捉函数的地址在子进程中是有意义的
  • 3.当执行一个程序时,所有信号的状态都是系统默认或忽略。通常所有信号都被设置为它们的默认动作,除非调用exec的进程忽略该信号。确切的将,exec函数将原先设置为要捕捉的信号都更改为默认动作,其他信号的状态则不变(一个进程原先要捕捉的信号,当其执行一个新程序后,就不能再捕捉了,因为信号捕捉函数的地址很可能在所执行的新程序文件中已无意义)

五、信号的种类

  • 不同系统的信号种类:
    • V7有15种不同的信号
    • SVR4和4.4BSD均有31种不同的信号
    • FreeBSD 8.0支持32种信号
    • Mac OS X 10.6.8以及Linux 3.2.0都支持31种信号
    • Solaris 10支持40种信号
    • 但是,FreeBSD、Linux、Solaris作为实时扩展都支持另外的应用程序定义的信号。SUSv4已经把POSIX实时扩展信号接口移至基础规范说明中
  • 在下列条件下不产生core文件:
    • 1.进程是设置用户ID的,而且当前用户并非程序文件的所有者
    • 2.进程是设置组ID的,而且当前用户并非该程序文件的组所有者
    • 3.用户没有写当前工作目录的权限
    • 4.文件已存在,而且用户对该文件没有写权限
    • 5.文件太大(RLIMIT_CORE限制)
  • core文件的权限(假设该文件在此之前并不存在)通常是用户读/写的,但是Mac OS X只设置为用户读
  • 下图解释说明:
    • “•”表示此种信号定义为基本POSIX.1规范部分。“XSI”表示该信号定义在XSI扩展部分
    • 默认动作中终止+core表示:终止程序并且产生core文件

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值