Linux之信号

Linux之信号

信号:信号和信号量不是同一个东西,信号是通知进程发生了某个事件,用来打断进程当前正在进行的操作,去处理这个事件,是一个软件终中断,功能是事件通知。

== 信号的分类==
信号分为可靠信号和非可靠信号,利用kill -l命令查看信号

非可靠信号:1---31号(可能会发生信号丢失)
可靠信号:34---64号(不会丢失)

信号的生命周期

产生—>在进程中注册---->在进程中注销—>处理; 阻塞

 信号的产生:
 		硬件产生:ctrl+c中断  ctrl+z停止  ctrl+\退出
 		软件产生:kill命令  kill -signum pid  示例:kill 9 pid;
 		int kill((pid_t pid,int signum);给指定的进程发送指定的信号
 		int raise(int signum);给进程自身发送指定的信号
 		void abort() 给进程自身发送SIGARBT信号(异常信号)
 		int alarm(int sec)定时器---sec秒之后给进程自身发送SIGALRM信号
 		(注意!!!alarm信号是一个定时器,他会取消之前的计时器,如果写在循环里面,
 		会导致没有产生定时功能)

在进程中注册:

在进程pcb中有个表 位图—>未决(未被处理的)信号的集合,进程运行中通过这张表的数据能够获知自己收到了哪个信号。
信号在进程中注册,说白了就是修改位图中的标志位,将对应的信号位置置为1,位图只能看出信号收没收到,不能看出收到了多少次

在pcb中还有一个sigqueue双向链表,链表中有多少个相同的信号
信息节点,就表示信号注册了多少次

非可靠信号的注册:如果信号已经被注册(没有被执行),那么不作任何操作,否则进行注册。
可靠信号的注册:不管信号注册没有,都要进行一次注册(添加一个信号节点)

== 可靠信号,相同的信号在链表中可能有多个节点,但是非可靠信号最多只能有一个==

   信号的注销:消除信号在pcb中的痕迹,删除一个信号的sigqueue节点,没有相同的节点了则位图置为0.

信号的处理:
处理一个时间,就是执行一个功能,信号的处理,就是调用处理信号的函数,执行这个函数,信号处理的时间,由进程自己察觉到自己受到某个信号才进行处理。

信号的处理方式有多种的,并且是可修改的。
默认处理方式:(系统中既定义的 SIG_DFL)
忽略处理方式:针对这个事件,处理方式就是什么都不做(SIG_IGN忽略处理方式 ),9号信号和19号信号不可被忽略

自定义处理函数:程序员自定义一个信号处理函数—作为指定的信号处理函数

回调函数 typedef void(*sighander_t)(int)

sighander_t signal(int signum–信号值 , sighander_t hander–函数指针);----->signum:指定要修改哪个信号处理方式的信号值 hander—>指定signum新的信号的信号处理函数

返回值:返回signum信号原有的信号处理函数的地址

用户态与内核态

用户态:程序运行的是我们自己写的或者是库函数,在用户态运行
内核态:运行内核中的某个代码来执行内核上的功能

如何从用户态------>>内核态:

1.系统调用
2.中断
3.异常

== 信号的处理:是在内核态返回用户态之前完成的,默认和忽略处理方式是在内核态完成的,自定义处理方式是在用户态完成的,完毕后,依然会返回内核态,直到没有待处理信号,才会返回主控流程==

信号的阻塞:说白了就是信号到来的时候不去处理,直达解除了阻塞之后才去处理,在pcb中有一个阻塞信号的集合(位图),一个信号阻塞就表示将这个信号添加到阻塞信号的位图中去,起始就是做个标记,一个信号解除阻塞就是将这个信号从阻塞的集合中拿出来,说白了就是解除标记。

	int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
	how:表示要对阻塞集合进行的操作
	SIG_BLOCK/SIG_UNBLOCK/SIG_SETMASK
	set:
	SIG_BLOCK将set集合中的信号添加到阻塞队列中去,将原来的阻塞信号集合中的信号放到old中去
	SIG_UNBLOCK:将set集合中的信号从阻塞队列中移除,说白了就是解除set中的信号阻塞
	SIG_SETMASK:直接将阻塞集合的值修改为set
	oldset:用于保存修改前原有阻塞信号的集合(便于还原),可以置NULL
	sigset_t:是一个信号位图的结构体
	返回值:成功返回0,失败返回-1;



int sigemptyset(sigset_t *set);清空set集合
int sigfillset(sigset_t *set); 将所有的信号添加到set集合当中去
int sigaddset(sigset_t *set,int signum);将指定的signum信号添加到set集合中去
int sigdelset(sigset_t *set,int signum);将指定的signum信号从set集合中移除
int sigismember(const sigset_t*set,int signum);判断signum信号是否在set集合中

再所有信号中,9号信号和19号信号比较特殊,9号—强杀,19—停止,这两个信号不会被阻塞,不会被自定义,不会被忽略

kill杀死进程的原理:给进程发送一个信号,进程受到信号处理事件,而大部分的信号处理的 方式最终都是退出进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值