赞
踩
信号是进程之间事件异步通知的一种方式,属于软中断
告诉有这样一个信号,但是这个信号的具体处理方式以及什么时候处理由进程决定,所以是软中断。
kill —l
可以罗列出所有信号(总共定义了62个信号)
没有32,33号信号
非实时信号(又称非可靠信号)
特点:信号可能会丢失 1~31
实时信号(又称可靠信号)
特点:信号不会丢失 33~64
kill命令向进程发送信号
kill -[信号值] [pid]
ctrl +c
:2号信号 SIGINT
ctrl +c
结束一个进程的时候,其实是进程收到了2号信号。2号信号导致进程的退出ctrl +z
:20号信号SIGTSTP
ctrl +z
会使一个程序进入暂停状态T;ctrl +|
kill函数int kill(pid_t pid,int sig);
pid:进程号,要给哪个进程发送信号,则填写哪个进程的进程号
sig:要发送信号的值
raiseint raise(int sig);
谁调用则给谁发送信号。该函数的实现也是调用kill函数
int raise(int sig){
return kill(gitpid(),sig);
}
我们在C/C++当中除零,内存越界等异常,在系统层面上,是被当成信号处理的。
man 7 signal 查看
SIG_DFL:操作系统当中已经定义信号的处理方式了
2–>终止程序
11—>终止程序,并且产生核心转储文件
SIG_IGN:该信号为忽略处理
进程收到忽略处理信号后,不进行处理
SIGCHLD 17号信号
子进程先于父进程退出,子进程退出的时候会给父进程发送SIGCHLD,而父进程接收到这个信号后,是忽略处理的,导致父进程没有回收到子进程的退出状态信息,从而子进程变成僵尸进程。
程序员也可以更改信号的处理方式,定义一个函数,当进程收到该信号的时候,调用自己写的函数
一个信号收一个信号的过程叫做信号的注册
信号的注册和信号的注销不是一个过程,是两个独立的过程
内核当中信号注册位图和sigqueue 队列的了解
操作系统内部并没有将sig[] 当做数组使用,而是当做位图使用
总结:
两种信号注册的区别
非实时信号
将信号对应的sig位图当中的比特位由1改为0
将对应信号的sigqueue节点进行出队操作
实时信号
将对应的信号的sigqueue节点进行出队操作
判断sigqueue队列当中是否还有相同信号的sigqueue节点
有:则比特位不变 没有:比特位由1改为0
程序员自己定义某一个信号的处理方式
函数sighandler_t signal(int signum,sighandler_t handler);
typedef void(*sighandler_t)(int);
函数int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
#include<stdio.h> #include<unistd.h> #include<signal.h> struct sigaction oldact; void sigcallback(int sig) { printf("sig num is %d\n",sig); sigaction(2,&oldact,NULL); } int main(){ //调用sigaction函数,自定义2号信号的处理方式 //定义struct sigaction 机构体对象 struct sigaction act; act.sa_handler=sigcallback; //将act.sa_mask内部清0,防止后续误导进程收到某些信号 sigemptyset(&act.sa_mask); sigaction(2,&act,&oldact); while(1){ sleep(1); } return 0; }
主函数中调用sigaction
将2号信号的处理方式改为调用sigcallback
,在sigcallback
函数中重新将2号信号处理方式改回来
现象:运行程序第一次按下crrl+c
运行sigcallback
函数内部代码,第二次按下结束进程
当从内核态切换回用户态的时候,会调用do_signal
函数处理信号
do_signal
:判断当前信号是否被阻塞
有:处理该信号(信号的处理方式:默认,忽略,自定义)
没有:直接返回用户态
默认,忽略:直接在内核中就结束处理
自定义处理:
sigreturn()
再次回到操作系统内核(内核空间)do_signal
函数处理信号sys_sigreturn
函数回到用户态,继续执行代码信号的阻塞并不会影响信号的注册,而是在进程收到信号的时候,由于阻塞,暂时不处理该信号
struct task_struct{
.........
sigset_t blocked;(位图)
........
}
当需要阻塞一个信号的时候,将信号对应的比特位设置为1
0:不阻塞
1:阻塞
当加上信号阻塞后,理解信号的处理
函数int sigprocmask(int how,sigset_t *set, sigset_t *oldset);
sigprocmas
k做什么事情原理解析:
block(new)=block(old) | set
block(new)=block(old) & ~set
block(new)=set
9号信号和19号信号不能被阻塞
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。