企业网站建设的方法,平顶山集团网站建设,小语种外贸网站建设,北京seo代理计费1. 信号什么时候被处理 当进程从内核态返回到用户态的时候#xff0c;进行信号的检测和处理
什么内核态#xff0c;什么又是用户态呢#xff1f; 当进程在CPU上运行时#xff0c;内核态#xff1a;允许进程访问操作系统的代码和数据#xff0c;用户态#xff1a;进程只…1. 信号什么时候被处理 当进程从内核态返回到用户态的时候进行信号的检测和处理
什么内核态什么又是用户态呢 当进程在CPU上运行时内核态允许进程访问操作系统的代码和数据用户态进程只能访问用户自己的代码和数据
为什么要有用户态和内核态呢 因为进程需要访问系统内的资源以及调用系统函数接口例如IO就是系统调用一个进程只有在内核态通过系统调用才能访问操作系统的资源这样可以保证系统的安全性
从用户态切换到内核态的方式
系统调用int 80异常外围设备中断 CPU内部有一个ecs寄存器它的后两位标识进程属于内核态还是用户态00标识内核态11标识用户态。int 80 汇编语句可以让ecs从11变成00从用户态切换到内核态
内核态和用户态分离是如何实现的 操作系统的代码和数据在物理内存中只有一份在计算机刚刚启动的时候就是在加载OS内核级页表在操作系统中也是只有一份它映射整个操作系统的代码和数据而且每个进程的虚拟内存的内核空间的内容都是一样的都是通过内核级页表映射来的。每个进程共享内核空间而用户空间是进程独有的所以用户级页表有很多个每个进程独有一份。 每个进程需要访问系统资源调用系统接口就会从用户态切换到内核态代码从用户区的代码跳转到内核区执行当内核区的代码执行完就会返回用户区也就会从内核态切回用户态也就是这个时候检测进程的pending信号集。
2. 信号如何被处理
处理流程 如果信号的处理动作不是自定义的那么就会在第三步处理信号处理完毕后如果进程还活着就返回用户模式并继续执行 sighandler和main是两个独立的控制流使用的是不同的栈空间
在上一篇博客留下了一个问题
如果调用sigprocmask解除了对当前若干个未决信号的阻塞则在函数返回前至少将其中一个信号递达在下一篇博客中解答为什么 因为当调用sigprocmask也就是系统调用就会从用户态切换到内核态在函数返回前也就是从内核态切回到用户态前会进行信号检测也就会信号递达至少一个是为啥呢 这是因为可能在自定义信号处理的过程中发生状态切换可能是系统调用也可能是中断都有可能。自定义信号处理是上面图的第四步处于用户态如果切换成内核态再切回的过程中就会再一次处理信号。甚至可以一直这样。 但是这种情况有时候并不是我们想要的例如一个进程一直再给另一个进程发送某个信号这就可能会出现当前自定义的信号还没处理完接着又去处理下一个信号。特别是同一个信号最容易出现这种情况会死循环。 但是其实操作系统提供了对应的接口设置操作系统的设计者已经想到了 函数功能 自定义信号的处理方法设置信号屏蔽字当处理该信号时内核会提前把sa_mask加入到block位图中默认会把当前信号加入确保在自定义函数处理过程中不会再处理不想处理的信号信号处理函数返回时自动恢复原来的信号屏蔽字 参数 signum信号编码 act设置信号处理方法输入型参数 oldact旧的信号处理方法会通过oldact传出输出型参数 返回值 0标识成功-1标识失败 在Linux下当子进程退出或者暂停时会向父进程发送SIGCHLD信号父进程对于SIGCHLD信号的默认处理动作是忽略但是我们知道如果父进程不等待回收子进程子进程会一直保持僵尸状态进程PCB会保持下来。 但是如果我们想要子进程自己处理完就退出并且释放自己的资源父进程不关心子进程的退出结果要怎么办呢 可以通过sigaction或者signal修改信号的默认处理动作为SIG_IGN这样就可以可见Linux下系统的默认处理动作为忽略和自定义处理动作忽略还是有区别的。 当然这里我们也可以当父进程修改信号自定义处理动作为非阻塞等待来获取子进程退出的结果代码如下
#include iostream
#include signal.h
#include unistd.h
#include sys/types.h
#include wait.husing namespace std;void handler(int sig)
{cout 捕捉到 sig endl;int status 0;pid_t pid 0;while((pid waitpid(-1, status, WNOHANG)) 0){cout child pid pid endl;cout !!!!!!!!!!!! endl;if(WIFEXITED(status))cout 退出码为 WEXITSTATUS(status) endl;else if(WIFSIGNALED(status))cout 终止信号 WTERMSIG(status) endl;}
}// 回收子进程通过信号
int main()
{struct sigaction act;act.sa_handler handler;sigaction(SIGCHLD, act, nullptr);// 4. 自定义SIG_IGNsignal(SIGCHLD, SIG_IGN);if(fork() 0){cout child pid getpid() endl;sleep(5);exit(0);}while(true) sleep(1);return 0;
}完。