Linux系统下的信号

一、信号概念

1. 什么是信号
信号是软件中断,信号提供了一种异步处理事件的方法,它允许进程和内核中断其他进程。一个信号就是一条消息,它通知进程系统发生了一个某种类型的事件,在Linux系统中支持31中不同类型的信号
在我这篇文章中给大家列出了Linux系统支持的31个信号(https://blog.csdn.net/qq_34934140/article/details/116550027)。

每种信号都对应不同的系统类型,底层硬件异常是由内核异常处理程序处理的,正常情况下对用户是不可见的,信号提供了一种机制,通知用户进程发生了这些异常。每个信号都有自己的名字,他们都是以SIG开头,这些信号都包含在<signal.h>中。

产生信号的事件相对于进程来说是不可预见的,所以进程不可以测试一个变量来判断信号的产生,而必须告诉内核当信号发生时进程该如何处理。在信号出现时有以下三种处理方式
1)忽略信号,大多数信号采用这种处理方式,但是有两种信号不可用忽略,SIGKILL 和 SIGSTOP,因为他们向内核和超级用户提供了可靠的进程终止或停止的方法。
2)捕捉信号,通知内核在信号发生时调用一个用户函数,在用户函数中执行用户希望对该事件的处理方式。同样SIGKILL 和 SIGSTOP不可以被捕捉。
3)执行默认动作,系统会给所有信号一个默认动作,在(https://blog.csdn.net/qq_34934140/article/details/116550027)里面我已经详细列出。

2.信号术语
1)发送信号
内核通过更新目的进程上下文中的某个状态,发送一个信号给目的进程。发送信号的原因
a. 内核检测都一个系统事件,如硬件异常或子程序终止
b. 一个进程调用kill函数,显示地要求内核发送一个进程给目的进程,或者进程自己给自己发送信号。
2)接收信号
当目的进程被内核强迫以某种方式对信号的发送做出反应时,它就接收了信号。进程可以忽略这个信号也可以捕捉它做一个信号处理函数。
3)待处理信号
一个发出而没有被接收的信号,任一时刻,一种类型最多只会有一个待处理信号,如果一个进程此时有一个类型为k的处理信号,那么接下来发送到此进程的所有k类型信号都不会排队等待
,他们都会被丢弃,进程可以选择阻塞接收某种信号,当一个信号被阻塞时,它仍然可以被发送,但是不会被接收,所有产生了待处理信号,直到进程取消对该进程的阻塞。一个待处理信号最多被
接收一次,在内核中有一个pending位向量维护着待处理信号集合,在blocked位向量中维护着被阻塞的信号集合,只要传送一个k类型信号,内核就会设置pending的第k位,接收一个k信号就会清楚
pending的k位。
4)阻塞信号
Linux提供阻塞信号的隐式和显式机制
隐式阻塞机制:内核默认阻塞任何当前处理程序正在处理信号类型的待处理信号
显式阻塞机制:应用程序可以使用sigprocmask函数和它的辅助函数,明确地阻塞和解除阻塞选定的信号
5)不可靠的信号
不可靠指的是信号可能会丢失,一个信号发生了,但你是进程却不知道。
6)可靠信号术语和语义
未决:信号产生和递送之间的时间间隔内,称信号是未决的,调用sigpending函数可以查看哪些信号被设置为阻塞并且是未决的。
信号屏蔽字:每个信号都有,它规定了当前阻塞递送到该进程的信号集,每种信号对应屏蔽字中的一位,使用sigprocmask函数来查看、设置、修改。
7)作业控制信号
SIGCHLD 子进程已停止或终止
SIGCONT 如果进程停止则继续运行
SIGSTOP 停止信号
SIGTSTP 交互式停止信号
SIGTTIN 后台进程组成员读控制终端
SIGTTOU 后台进程组成员写控制终端
除了SIGCHLD之外,大多数应用程序不处理这些信号,交互式shell通常会处理这些信号。
8)信号集
一个可以表示多个信号的数据类型

3.编写信号处理函数基本规则
处理程序和主程序并发执行,他们共享全局变量,因此可能与主程序和其他处理程序相互干扰,所以需要编写安全、正确、可移植的信号处理程序。
1)安全的信号处理
a.处理程序尽可能简单,
b.在处理程序中只调用异步信号安全的函数
c.保存和恢复,在处理程序时把errno保存在一个局部变量中,返回时恢复。
d.阻塞所有信号,保护对共享全局数据结构的访问。
e.用volatile声明全局变量,
f.用sig_atomic_t声明标志,保证读写不可中断

二、信号调用函数

1. signal函数#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);功能:设置某一信号对应动作参数:signum:信号名handler:信号处理函数,当信号发生时调用此函数。返回值:成功返回处理函数的指针,失败返回SIG_ERR。2. 发送信号函数(kill函数和raise函数)#include <sys/types.h>#include <signal.h>2.1 int kill(pid_t pid, int sig);功能:将信号发送给进程或者进程组参数:pid > 0:发送给进程的进程IDpid = 0: 将信号发送给发送进程所属进程组的所有进程pid < 0: 发送给pid绝对值的进程pid = -1:发送给可发送的所有进程sig:信号名返回值:成功 0, 失败 -1.2.2 int raise(int sig);功能:允许进程 向自己发送信号参数:sig:信号名返回值:成功 0, 失败 -1.3. 定时函数(alarm函数和pause函数)#include <unistd.h>3.1 unsigned int alarm(unsigned int seconds);功能:设置一个定时器,当超时之后产生SIGALRM信号,如果忽略此信号,默认动作是终止此进程参数:seconds:时间,单位 秒返回值:0或者一起设置闹钟时间剩余的秒数注释:每个进程只能设置一个闹钟,如果调用alarm函数时,进程已经调用过了此函数则返回剩余时间数,时间被新值替换。3.2 int pause(void);功能:进程挂起直到捕捉到一个信号参数:无返回值:-1, errno 设置为 EINTR.4. 信号集函数#include <signal.h>4.1   int sigemptyset(sigset_t *set);功能:初始化set指向的信号集,清除其中所有信号。所有应用程序在使用信号集前必须调用sigfillset或者sigemptyset参数:set;信号集返回值:成功 0, 失败 -1.4.2 int sigfillset(sigset_t *set);功能:初始化set指向的信号集,使其包括所有信号。所有应用程序在使用信号集前必须调用sigfillset或者sigemptyset参数:set;信号集返回值:成功 0, 失败 -1.4.3  int sigaddset(sigset_t *set, int signum);功能:添加一个信号参数:set;信号集signum:信号返回值:成功 0, 失败 -1.4.4  int sigdelset(sigset_t *set, int signum);功能:删除一个信号参数:set;信号集signum:信号返回值:成功 0, 失败 -1.4.5  int sigismember(const sigset_t *set, int signum);功能:测试一个指定位,因为信号没有编号为0,所有从信号编号中减去1得到要处理的位编号。参数:set;信号集signum:信号返回值:成功 0, 失败 -1.5.检测和修改信号屏蔽字#include <signal.h>int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);功能:可以检测和修改进程的信号屏蔽字参数:how: SIG_BLOCK:该进程新的信号屏蔽字是set指向的信号集和当前信号屏蔽字的并集,阻塞信号SIG_UNBLOCK:该进程新的信号屏蔽字是set指向的信号集和当前信号屏蔽字的补集的交集,解除阻塞SIG_SETMASK:该进程新的信号屏蔽字是set指向的值set:非空指针,则how修改当前信号屏蔽字空指针:则how无意义6.返回信号集函数:sigpending  #include <signal.h>int sigpending(sigset_t *set);功能:返回一信号集参数:set:信号集返回值:成功 0,失败 -1.7.检测或修改以及指定信号相关联的处理动作#include <signal.h>int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);功能:检测或修改以及指定信号相关联的处理动作参数:signum:要修改或检测的信号act:非空指针:则要修改动作为空:  则由oldact指针返回信号上一个动作。oldact:指针   返回值:成功 0,失败 -1.struct sigaction {void     (*sa_handler)(int);void     (*sa_sigaction)(int, siginfo_t *, void *);sigset_t   sa_mask;int        sa_flags;void     (*sa_restorer)(void);};当更改信号动作时,sa_handler是信号处理函数,sa_sigaction是替代的信号处理程序,sa_mask是一个信号集,调用信号处理函数之前新将信号集加入到信号屏蔽字中,这样当正在处理信号时候,再来这种信号就会被阻塞,sa_flags指对信号进程处理的各个选项,有以下选项。SA_NOCLDSTOP:若signo是SIGCHLD,当子进程终止产生此信号。SA_NOCLDWAIT:若signo是SIGCHLD,当子进程终止不创建僵尸进程,若调用wait则阻塞到所有子进程都终止SA_NODEFER:当捕捉到信号时,在执行其信号处理函数时,系统不自动阻塞此信号SA_ONSTACK:此信号递送给替换栈上的进程。SA_RESETHAND:此信号捕捉函数入口处,将此信号处理方式重置为SIG_DFL,清除SA_SIGINFO标准SA_RESTART:此信号中断的系统调用自动重启SA_SIGINFO:提供了一个指向siginfo结构的指针和指向进程上下文的标识符指针。8.非局部转移函数 sigsetjmp函数 和 siglongjmp函数      同setjmp函数longjmp函数功能一样,在 信号处理程序中调用siglongjmp跳回到主程序。不同之处是多了一个参数,如果savemask非0,则sigsetjmp在env中保存进程的当前信号屏蔽字。调用siglongjmp时,如果带非0 savemask的sigsetjmp调用已经保存env,则siglongjmp从其中恢复保存的信号屏蔽字。#include <setjmp.h>int sigsetjmp(sigjmp_buf env,int savemask);功能:可以保存当前执行线索状态参数:    env:存放调用siglongjmp时可以恢复栈状态的所有信息,通常为全局变量savemask:非0:env中保存当前进程信号屏蔽字返回值:直接调用返回 0,若从siglongjmp调用返回0.int siglongjmp(sigjmp_buf env, int val);功能:跳转函数参数:env:sigsetjmp调用的envval:非0值9.恢复信号屏蔽字的值#include <signal.h>int sigsuspend(const sigset_t *mask);功能:如果捕捉到一个信号而且信号处理函数返回,则sigsuspend返回,并且该信号屏蔽字设置为调用sigsuspend之前的值参数:由sigmask指向的值返回值:此函数没有成功返回值,如果返回到调用者则总是-1.10.程序异常终止函数#include <stdlib.h>void abort(void);功能:此函数将SIGABRT信号发送给调用进程
11.信号名和信号编号     #include <signal.h>11. void psignal(int sig, const char *s);void psiginfo(const siginfo_t *pinfo, const char *s);功能:打印与信号编号对应的字符串参数:sig:信号名s:  对应字符串11.2 #include <string.h>char *strsignal(int sig);功能:给定信号编号,返回信号字符串

Linux操作系统下信号处理函数相关推荐

  1. Linux操作系统下进程讲解(史上最强总结)

    Linux操作系统下进程讲解 一.进程的基本概念: 1. 什么是进程 在传统的操作系统中,程序不可以独立的运行,作为资源分配和独立运行的基本单位都是进程.进程的定义是一个可执行中程序的实例,系统中每一 ...

  2. linux操作系统下 c语言编程入门

    linux操作系统下 c语言编程入门 (一)目录介绍 1)Linux程序设计入门--基础知识 2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门 ...

  3. linux操作系统下c语言编程入门

    linux操作系统下c语言编程入门  整理编写:007xiong  原文:Hoyt等 (一)目录介绍 1)Linux程序设计入门--基础知识  2)Linux程序设计入门--进程介绍  3)Linux ...

  4. 【转贴】linux操作系统下c语言编程入门

    [转贴]linux操作系统下c语言编程入门 发信人: Lerry (驴是的念来过倒·杏红等头墙上爬), 信区: Linux 标 题: linux操作系统下c语言编程入门 发信站: 哈工大紫丁香 (Fr ...

  5. Linux操作系统下 NAND FLASH驱动程序框架

    当我们需要在操作系统上读写普通文件的时候,总是需要一层层往下,最终到达硬件相关操作,当然底层设备大多数都是块设备 NAND FLASH就作为一个最底层的块设备. 而我们写驱动,就是要构建硬件与操作系统 ...

  6. linux c语言 ppt,linux操作系统下c语言编程入门.ppt

    linux操作系统下c语言编程入门.ppt Linux操作系统下C语言编程入门 CNT Linux操作系统简介基础知识进程介绍文件操作时间概念消息管理线程操作网络编程Linux下C开发工具介绍 一 L ...

  7. 怎么利用linux来操作手机,Linux_在Linux操作系统下操作蓝牙手机的方法,所谓操作,到现在只是通过蓝 - phpStudy...

    在Linux操作系统下操作蓝牙手机的方法 所谓操作,到现在只是通过蓝牙做了二件事: 一.通过虚拟串口连接上手机,执行AT命令操作手机(发短信而已) 二.手机和电脑互传文件 如果使用redhat 9.0 ...

  8. Linux操作系统下软件的安装与卸载

    在Windows下安装软件时,只需运行软件的安装程序(setup.install等)或者用zip等解压缩软件解开即可安装,运行反安装程序(uninstall.unware."卸载" ...

  9. Linux操作系统下SSH默认22端口修改方法

    NO 1: 01假如要改SSH的默认端口(22),那么你只要修改:/etc/ssh/sshd_config中Port 22,这里把22改成自己要设的端口就行了,不过千万别设和现已有的端口相同哦,以防造 ...

最新文章

  1. 恩布企业IM,协同办公平台发布V1.24.2版本
  2. 系列文章|OKR与敏捷(二):实现全栈敏捷
  3. 灰度图像的对数变换原理及OpenCV代码实现
  4. linux网络编程二:基础socket, bind, listen, accept, connect
  5. 把tensor转为numpy_如何在TensorFlow中将张量转换为numpy数组?
  6. JVM内存区域:递归JVM指令分析
  7. CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash
  8. 形容等待时间长的句子_雅思听力该如何准确辨别句子结构?学会结构精听,雅思8分轻松get!...
  9. 高效率Oracle SQL语句
  10. 知乎上已获千赞,持续更新中
  11. virtual析构函数(作用)
  12. java图形界面 关闭_用 java编写的图形用户界面运行后怎么关不掉
  13. 做好产品经理,需要具备哪些技能?
  14. 名校计算机课程百度云,浙江大学计算机类专业视频课程百度云网盘
  15. 某新闻App sign签名算法解析(一)
  16. 音频转换成mp3,音频转mp3格式
  17. 数据库并发抢红包_微信高并发抢红包秒杀实战案例
  18. girl_noise.jpg恢复去噪
  19. selenium爬取拉勾网
  20. MyBatis 入门级配置文件

热门文章

  1. JDK8新特性(十三)之Optional
  2. python将excel导入生成矩阵_Python导入数值型Excel数据并生成矩阵操作
  3. 自建latex服务器,通过在线服务器编译LaTeX
  4. 测试linux mongodb数据库开启,安装配置MongoDB数据库
  5. 蓝宝石显卡bios_狼神矿卡烤机89°C!强刷蓝宝石RX570超白金显卡BIOS降温75°教程...
  6. jsp中用java写标签id_jsp中自定义标签用法实例分析
  7. CyclicBarrier底层实现和原理
  8. HWPFDocument读取doc,wps文档(含图片读取)
  9. Zookeeper 3.6.0启动时 8080端口被占用
  10. Android开发笔记(六十二)HTTP数据格式的解析