Linux进程信号

信号

  • 信号是什么?
    • 是一个软件中断,通知进程发生了某个事件,打断当前操作去处理这个事件
    • 信号有很多种类,每个信号代表一个事件
  • 信号种类
    • 62种
    • 1~31:非实时信号(继承自UNIX)
    • 34~64:实时信号(Linux补充)
      在这里插入图片描述
  • 生命周期

  • 信号的产生:
    • 硬件:ctrl + c(SIGINT) ctrl + | () ctrl + z(SIGTSTP)
    • 软件:
      • kill signo pid
      • int kill(pid_t pid,int sig) 给pid进程发送sig信号 (获取自己的pid:getpid() )
      • int raise(int sig) 给调用进程发送sig信号
      • void abort(void) 给调用进程发送SIGABRT信号
      • unsigned alarm(unsigned int seconds)(定时器,sec秒之后通知进程)
        seconds为零:取消上一个计时器
      • core dumped:核心转储,文件命名方式:core.pid
        • ulimit -a 查看 core dumped(核心转储)
        • ulimit -c 1024//设置core文件的最大大小,单位是kb
        • core.pid
        • gdb ./main -> core-file core.pid -> bt
  • 信号的注册:
    • 在pcb的struct sigpending -> signal(位图)中标记收到了哪些信号,并且为这个信号组织一个sigqueue节点,添加到链表中
    • 可靠信号: 34~64 :修改位图为1,并且为每个到来的信号都添加一个新的sigqueue节点
    • 非可靠信号: 1~31 :判断位图是否为1,为1则什么也不做(事件丢失);否则添加节点修改位图
      所以非可靠信号最多可以有1个节点,可靠信号可以有多个节点
  • 信号注销
    • 可靠信号和非可靠信号删除不同
    • 可靠信号删除时去掉一个链表节点后需要判断是否还有相同的节点
      • 如果有相同节点,位图置为1
      • 如果没有相同节点,位图置0
    • 非可靠信号直接删除节点,位图置0
  • 信号处理
    • 默认处理:操作系统中定义好的默认处理方式
    • 忽略处理:什么也不做
    • 自定义处理方式:用户自己定义的处理方式
    • 修改信号处理方式: signal
    • 默认:SIG_DFL
    • 忽略:SIG_IGN
    • sigaction(SIGINT,&act,&old) 用act替换SIGINT,将SIGINT保存在old中)
    • 自定义信号处理方式的捕捉流程:
      • 一个进程因为系统调用/中断/异常从用户态切换到内核态运行,完成功能后准备返回用户态的时候,查看是否有信号待处理,如果有,并且是默认或者忽略处理方式,则在内核态直接完成。如果有自定义处理方式,则返回用户态调用信号处理函数sigcb,完毕之后调用sigreturn返回内核态,当没有信号待处理,则调用sys_return返回用户态主控流程。
        在这里插入图片描述
  • 信号的阻塞
    • 阻止信号被处理(递达)
    • 在pcb中有一个信号阻塞集合,这个信号阻塞集合的作用就是用于标记哪些信号到来的时候暂时不被处理
      SIG_BLOCK–block = block | set ->将set中的信号添加到阻塞集合
      SIG_UNBLOCK–block = block & (~set)–>将set中的信号解除阻塞
      SIG_SETMASK–block = set—>将阻塞集合设置位set中的信号
      在这里插入图片描述
      在所有信号中:SIGKILL -9 (强杀) SIGSTOP -19(停止) 无法被阻塞,无法被定义,无法被忽略
    • 可靠信号和不可靠信号的区别
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
void sigcb(int signo)
{
  printf("recv signo:%d\n",signo);
  //通过打印查看收到信号
}

int main(int argc,char *argv[])
{
  sigset_t set , oldset;

  signal(SIGINT,sigcb);   //修改信号处理方式为sigint信号
  signal(40,sigcb);   //修改信号处理方式为可靠信号40
  
  sigemptyset(&set);
  sigfillset(&set);   //所有信号添加到set集合
  sigprocmask(SIG_BLOCK,&set,&oldset);//set集合设置为阻塞
  printf("press enter to continue\n");
  getchar();
  sigprocmask(SIG_UNBLOCK,&set,NULL);
  sigprocmask(SIG_SETMASK,&oldset,NULL);
  //通过将所有信号设置为阻塞,测试9号信号和19号信号不可被阻塞的特性

  return 0;
}

这里使用4次40号信号
在这里插入图片描述
ctrl+c使用了7次只打印了1次,40号信号使用了4次打印了四次
这就是可靠信号和不可靠信号的区别
在这里插入图片描述

  • 竞态条件
  • 可重入/不可重入函数
    • 函数是否可以在多个执行流中重复进入(调用),而不是出现异常问题;
    • 如果可能出现问题就是不可重入函数,否则就是可重入函数
    • 函数可重入与不可重入的关键点:是否在函数中对全局数据进行非原子操作
    • 当用户自己设计函数或者调用别人函数的时候就需要考虑函数是否可重入
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值