进程信号的概念、产生及实现(注册、注销、处理、捕捉、阻塞)分析

18 篇文章 0 订阅
17 篇文章 0 订阅

先思考两个问题:
进程创建出的子进程,有可能在子进程退出时产生一个僵尸进程,是由于子进程退出时,父进程来不及回收子进程的退出信息,导致子进程成为僵尸进程,为什么父进程来不及回收子进程的退出信息?
原因:
子进程在退出的时候,会给父进程发送一个 SIGCHID 信号,操作系统对 SIGCHID 的默认处理方式是忽略处理

从信号角度理解,为什么进程等待就可以解决僵尸进程?
原因:
wait 阻塞父进程,只干一件事,即当子进程退出,然后发送 SIGCHID 信号,wait 处理 SIGCHID 信号,就会调用程序员自己定义的 SIGCHLD 信号处理函数,回收子进程的退出信息

信号基本概念

信号是进程之间事件异步通知的一种方式,属于软中断,即打断正在运行的进程,使之去处理信号的事件

信号种类

Linux中有62种信号:
1-31:不可靠信号,信号有可能会丢失,非实时信号
34-64:可靠信号,信号不会丢失,实时信号

信号实现

信号的产生

硬件产生
ctrl + c:给前台进程发送一个SIGINT
ctrl + z:给前台进程发送一个 20 号信号,SIFTSTP
ctrl + |:给前台进程发送一个SIGQUIT

软件产生
kill命令是调用kill函数实现的,kill函数可以给一个指定的进程发送指定的信号

kill [pid] 给前台进程发送一个SIGTERM信号
kill -[signal][pid] 给前台进程发送一个SIGKILL命令

raise函数可以给当前进程发送指定的信号(自己给自己发信号)
abort函数使当前进程接收到信号而异常终止,谁调用给谁发送SIGABRT
alarm函数:定时器函数

程序崩溃原因:
如果产生 6 号信号:SIGABRT,有可能是 double free,有一种情况叫内存越界,然后程序没有发生段错误
如果产生 11 号信号:解引用空指针,内存访问越界

  int alarm(unsigned int sec);
    发送SIGALRM信号

信号的注册

在这里插入图片描述

  1. 非可靠信号
    第一次注册:更改sign位图,然后在 sigqueue 队列中,添加对应信号的节点
    之后注册:如果sign位图中,对应信号的bit位已经置1,则不会去想sigqueue队列当中再去添加节点,当前这个信号就被丢弃,所以说1-31为非可靠信号
  2. 可靠信号
    第一次注册:更改sign位图,然后在 sigqueue 队列中,添加对应信号的节点
    之后注册:如果sign位图中,对应信号的bit位已经置1,说明已经收到了一个可靠信号,不用更改 sign 问题当中对应bit位中的 1,但需要在sigqueue队列当中再去添加对应信号的处理节点,表示当前进程需要多次处理多少次该可靠信号,当前信息不会被丢弃,所以说34-64 为可靠信号

信号的注销

  1. 非可靠信号
    将sign位图当中对应的标志位置置0,并且将 sigqueue 队列当中的节点信息进行出队操作
  2. 可靠信号
    将待处理信号的节点从 sigqueue 当中进行出队操作,判断当前 sigqueue 队列当中是否还有和待处理信号相同信息的节点,如果还有则不更改 sign 位图当中对应的 bit 位当中的 1 变为 0,如果没有,则更改 sign 位图当中对应 bit 为中的 1 变为 0

信号的处理

操作系统当中会给每一个信号都预定一个信号的处理方式,其实就是当进程收到一个信号时,进程自己默认的调用函数的方式

例:SIGINT--> exit_()

默认处理方式

SIGINT:调用终止进程的函数

忽略处理方式

虽然当前进程收到了信号,但是并不去理睬

自定义处理方式

signal函数:可以重置当前操作系统对信号的处理方式
sighandler_t signal(int signum, sighandler_t handler)
    signum:确认重置的信号是哪个
    handler:定义一个函数指针
        typedef void(*sighandler_t)(int)
        int类型的参数:是操作系统传递给我们的当前收到的信号值
        void是返回值:即在这里插入图片描述不需要返回
9 号信号不可以被更改信号处理方式
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
    signum:确认重置的信号是哪个
        struct sigaction
        {
            void(*sa_handler)(int)-->信号默认的调用函数
            void(*sa_sigaction)(int, siginfo_t*, void*)
            int sa_flags;如果sa_flags 取值是SA_SIGINFO,才会当收到信号的时候默认调用sa_sigaction来进行处理
                默认情况下:sa_flags 取值为 0 ,一般情况下都是在调用 sa_handler
            sigset_t sa_mask:表示当前进程正在处理信号的时候,在这个时候也有可能收到新的信号,将新的信号先放到sa_mask 里面
            void(*sa_restorer)(void):预留的信息
        };
    act:表示当前信号修改成什么处理方式,即操作系统收到该信号时,调用哪个函数进行处理
    oldact:表示操作系统之前对收到当前信号的处理方式

自定义信号处理流程
前提:
1.在PCB中有一个sighand_struct结构体的指针,在这个结构体当中,有一个action数组,数组的每一个元素都对应一个信号的处理逻辑,每一个元素的类型都是一个struct k_sigaction

2.在struct k_sigaction当中有一个元素是struct sigaction sa,在sa元素当中有一个变量是sa_handler,这个sa_handler保存了信号的处理函数的地址
在这里插入图片描述
过程:
1.使用操作系统默认的处理方式:
当PCB中pending位图中某个信号的bit位被置1,则表示当前进程收到信号,当操作当前程序进入内核时,就会在PCB当中寻找sighandler_struct指针,根据指针找到sa_handle,再去调用所指向函数

2.自定义处理信号:
signal 函数:相当于更改sa_handler当中保存的函数地址,即更换操作系统对于信号处理的默认执行函数地址,从而使处理信号时可以调用自定义函数
sigaction 函数:相当于更改action 数组中元素,依旧是意味着直接更改结构体,达到修改信号处理函数地址的目的

所以signal 函数是依赖 sigaction 实现的

信号的捕捉

在这里插入图片描述
当一个进程从内核态返回到用户态的时候需要调用 do_signal 函数去判断当前是否有信号需要处理

有[自定义处理方式]:

返回用户态执行用户所定义的信号执行函数
调用 sigreturn 函数返回内核
调用 do_signal 函数
逻辑回到处理信号的逻辑,再去判断是否有信号需要处理,直到没有信号需要处理,调用 sys_return 函数真正返回用户态

没有:

调用 sys_return 函数真正返回用户

信号的阻塞

  1. 阻塞的概念
    信号的阻塞并不是信号不能被注册(pending 位图当中可以正常被置为 1) ,而是当操作系统在判断 pending 位图时,发现了某一个 pending 当中的某一个位已经置 1 ,表示收到某个信号
    还需要在 block 位图查看对应信号的 bit 是否置 1
    0:处理该信号
    1:不处理该信号(阻塞)
    在这里插入图片描述
    即操作系统在处理时会去判断 block 位图来进行判断当前信号是否不用处理
  2. int sigprocmask(int how, const sigset_t* set, sigset_t* oldset)
    how:以何种方式来使用函数
    SIG_BLOCK:可以设置某个信号为阻塞状态
    block(new) = block(oid) | set (9、19号信号不可以被阻塞)
    SIG_UNBLOCK:可以设置某个信号为非阻塞状态
    block(new) = block(oid) &(~ set)
    SIG_SETMASK:可以设置新的位图
    不关心 block(old),直接用 set 来代表 block(new)
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值