[Linux][进程信号][一][信号基础][如何产生信号]详细解读

目录


0.前言预备

1.系统定义的信号列表

  • **[1, 31]:**普通信号

  • **[34, 64]:**实时信号

  • 这些信号在什么条件下产生,默认的处理动作是什么,可以通过 man 7 signal 查看

2.核心转储 -- Core Dump

  • 当一个进程要异常终止时,可以选择把当前进程在内存中的相关核心数据转存到磁盘上,文件名通常是core,这叫做Core Dump
  • 进程异常终止通常是因为有Bug,事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)
    • 使用:core -file core.pid
  • 默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全
    • 一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存在PCB中)
    • 在开发调试阶段可以用ulimit 命令改变这个限制,允许产生core文件
      • ulimit -a
      • ulimit -c
      • 当前bash会话有效

1.信号基础

1.信号概念

  • 信号是进程之间事件异步通知的一种方式,属于软中断
    • 本质是一种通知机制
  • 理解信号思路
    • 进程要处理信号,必须具备信号"识别"能力(看到 + 处理动作)
    • 进程为什么能够"识别"信号?
      • 程序员通过代码提前设置好的
    • 信号产生是随机的,进程可能正在忙自己的事情
      • 信号可能后续被处理,不一定是立即处理
    • 信号会临时的记录下对应的信号,方便后续进行处理
      • 何时处理?
        • 合适的时候
    • 一般而言,信号的产生相对于进程而言是异步的

2.信号处理方式概览

  • 执行该信号的默认处理动作
  • 忽略此信号
  • 自定义动作(捕捉信号)
    • 提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数
  • 信号捕捉初识
    • **功能:**捕获特定的信号,执行自定的方法
    • 原型:sighandler_t signal(int signum, sighandler_t handler);
    • 参数:
      • **signum:**要捕获的信号
      • **handler:**函数指针,要执行的自定方法
    • 返回值:
      • 不在乎
    • 注意:
      • signal函数,仅仅是修改进程对特性信号的后续处理动作,不是直接调用对应的处理动作
      • 如果后续没有任何SIGNAL信号产生,handler永远不会被调用

3.理解信号如何被保存

  • 需要解决两个问题 --> 什么信号?是否产生?
  • 进程PCB内部保存了**信号位图**字段
    • 第几个比特位表示什么信号
    • 01表示是否产生信号

4.信号发送的本质

  • 信号位图在task_struct --> task_struct内核数据结构 --> OS掌控
  • 信号发送的本质:OS向目标进程写信号,OS直接修改PCB中的指定的位图结构,完成"发送"信号的过程

2.如何产生信号?

1.终端按键产生信号

  • 键盘的工作方式是通过中断方式 进行的
    • 便可以**识别组合键,**如Ctrl + c
  • OS解释组合键 --> 查找进程列表 --> 找到前台运行的进程 --> OS写入对应的信号到进程内部的位图结构中

2.系统调用接口

1.kill()

  • **功能:**给指定的进程发送指定的信号
  • 原型:int kill(pid_t pid, int sig);

2.raise()

  • **功能:**给当前进程发送指定的信号 --> 自己给自己发信号
  • 原型:int raise(int sig);

3.abort()

  • **功能:通常用来终止进程,发送SIGABRT(6)**信号
  • 原型:void abort(void);

4.如何理解?

  • 用户调用系统接口 --> 执行OS对应的系统调用代码 --> OS提取参数,或者设置特定的数值 --> OS****向目标进程写信号 --> 修改对应进程的信号标记位 --> 进程后续会处理信号 --> 执行对应的处理动作

3.由软件条件产生信号

  • 如:管道 读端不光不读,而且还关闭了,写端一直在写,会发生什么问题?
    • 写没有意义,OS会自动终止对应的写端进程,通过发送信号(SIGPIPE)的方式
  • 如:alarm() && SIGALRM
    • 功能:
      • 设定一个闹钟,告诉内核在seconds秒之后给当前进程发SIGALRM信号,该信号的默认处理动作是终止当前进程
      • 闹钟一旦触发,就自动移除了
  • 原型:unsigned int alarm(unsigned int seconds);
  • 返回值:
    • 0
    • 以前设定的闹钟时间还余下的秒数
  • 如何理解?
    • OS先识别到某种软件条件触发或不满足某条件 --> OS构建信号,发送给指定的进程

4.硬件异常产生信号

  • 硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号
    • 例如:当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为SIGFPE信号发送给进程
    • 例如:当前进程访问了非法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程
  • 由此看出,在C/C++中,除零,内存越界等异常,在系统层面上,是被当成信号处理的

5.总结

  • 所有的信号,有他的来源,但最终全部都是被OS识别,解释,并发送的
相关推荐
凯哥是个大帅比15 分钟前
ubuntu20.04 GLIBC从2.35降级到2.31
linux
iHero17 分钟前
【Ubuntu】在 Ubuntu 22.04.3 LTS 安装 davfs2 通过 Nextcloud WebDAV 挂载到 Ubuntu 的目录上
linux·ubuntu·nextcloud
心勤则明18 分钟前
Netty配置SSL证书加密
服务器·https·ssl
清园暖歌19 分钟前
Ubuntu 不重装系统增加交换空间大小
linux·运维·ubuntu·交换空间
黎相思20 分钟前
操作系统迁移(CentOs -> Ubuntu)
linux·ubuntu·gitee·centos
写bug如流水23 分钟前
在Ubuntu 20.04上安装pgAdmin 4
linux·运维·ubuntu
冰红茶兑滴水30 分钟前
Linux 线程控制
linux·c++·算法
IT良42 分钟前
while循环及简单案例
linux·服务器
码哝小鱼1 小时前
iptables限制网速
linux·服务器·网络
Persistence is gold1 小时前
cassandra指定配置文件的docker启动方法
运维·docker·容器