操作系统与网络 (8. 信号Signal)

希望的事,迟早会实现,但实现的希望,总是变了味的!

8. 信号Signal

8.1 概念
  • 信号是进程之间实现异步通知的一种方式,对进程来说是软中断,前提是得识别这个信号。
8.2 信号分类
8.2.1 信号的查看
  • 使用kill -l命令查看
8.2.2 信号的说明
  • 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在 signal.h 中找到,例如其中有定义 #define SIGINT 2
8.2.3 信号分类

(总共有62种)
可靠信号(实时信号)
34~64号信号
非可靠信号(非实时信号)
1~31号信号

8.3 信号的功能
  • (1)通知进程发生了哪些事件,应该怎么处理;
  • (2)信号实际上也可以归为一类进程间通信;
8.4 信号的生命周期
8.4.1 信号产生

(1)硬件产生(终端按键产生)

  • ctrl +c(中断信号)
  • ctrl + |(退出信号)
  • ctrl +z(停止信号)
    core dump
  • 定义:当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,这叫做Core Dump。
  • 进程异常终止:通常是因为有Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做 Post-mortem Debug(事后调试)。

(2)软件产生

  1. 调用系统函数向进程发送信号
    kill -signum pid 即 kill -SIGSEGV 4568 或 kill -11 4568
    raise(sigmnum)
    kill(pid,signum)

总结:kill命令是调用kill函数实现的。kill函数可以给一个指定的进程发送指定的信号,raise函数可以给当前进程发送指定的信号(自己给自己发信号)。
2. 由软件条件产生信号
abort()
alarm(nsec)
sigqueue函数
3. 硬件异常产生信号

8.4.2 信号注册
  • (1)在pcb中的未决信号集中进行标记,并且在sigqueue中添加节点;
  • (2)可靠信号注册
    不管信号是否已经注册,都会向链表中添加一个新的信号结点(事件不会丢失);
  • (3)非可靠信号注册
    判断pcb中的 pending位图 中相应的信号是否已经注册(位图是否已经置为1);若已经注册,则不做任何操作(事件丢失);
8.4.3 信号注销

(1)从sigqueue链表中移除信号结点,修改未决信号位图
(2)可靠信号

  • 结点可能有多个,注销就是删除一个结点,判断链表中是否还有相同信号的结点,若没有则删除,则位图置为0;否则位图不变依然需要标记有这个信号待处理。

(3)非可靠信号

  • 结点只有一个,注销就是删除结点,位图置为0。
8.4.4 信号处理

(1)定义

  • 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。

(2)信号处理方式

    1. 默认处理方式
      执行该信号的默认处理动作;
    1. 忽略此信号
      处理动作中什么都没做;
    1. 自定义处理方式
      signal(signum,handle);
      sigaction(int signal,struct sigaction* act,struct sigaction* oact);
8.5 信号的阻塞
8.5.1 信号以及其他相关概念
  • 信号的阻塞
    在内核的 pcb 中有一个阻塞信号集合,标记哪些信号到来之后暂时不处理。
  • 信号未决
    信号从产生到递达之间的状态,称为信号未决(Pending)。
  • 阻塞和忽略的区别
    只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
8.5.2 信号在内核中的表示
  • 信号的两个标志位
    阻塞(block)和未决(pending),还有一个函数指针表示处理动作;
    信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。
8.5.3 sigset_t(信号集)
  1. 每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。
  2. 未决和阻塞标志可以用相同的数据类型 sigset_t 来存储,sigset_t 称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态;在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
  3. 阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。
8.5.4 信号集操作函数

(1)信号集操作函数

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);

(2)sigemptyset

  • 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应 bit 清零,表示该信号集不包含任何有效信号;

(3)sigfillset

  • 函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示该信号集的有效信号包括系统支持的所有信号;
    (4)sigismember
  • 是一个布尔函数,用于判断一个信号集的有效信号中是否包含;
    (5)返回值
  • 这四个函数都是成功返回0,出错返回-1;
    (6)注意
  • 在使用 sigset_ t 类型的变量之前,一定要调用 sigemptyset 或 sigfillset 做初始化,使信号集处于确定的状态。初始化 sigset_t 变量之后就可以在调用 sigaddset 和 sigdelset 在该信号集中添加或删除某种有效信号。
8.6 函数的可重入与不可重入
  • 重入概念
    同时在多个执行流中进入同一个函数执行。
  • 可重入
    函数重入之后不会出现数据二义性等异常。
  • 不可重入
    函数重入之后会出现数据的二义性/逻辑混乱。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值