Linux-信号
来源:互联网 发布:2g网络速度 编辑:程序博客网 时间:2024/06/05 01:03
信号
信号概念
信号是为了操作系统能控制进程正确的运行而产生的一种机制。它分为俩种类型,第一种是普通信号(标准信号),第二种是实时信号。通常进程产生普通信号有四种方式:
1 由键盘特殊的组合按键产生,该方式产生的信号发送给一个控制终端的前台作业。
2 由系统调用接口或者命令发出一个信号。(列如kill 命令,abort—异常终止信号)
3 由进程自身错误操作产生的异常导致的信号
4 软件条件产生的信号(列如 alarm , 还有管道中的SIGPIPE)
普通信号(Standard Signals)
Linux下普通信号为1~32。它由pending表/block表/handler表来管理。当有多个非同类型的普通信号产生时,信号抵达顺序是未定义的。有多个同类型的信号产生的时候,pending表只记录一个。还有一个就是Linux下的普通信号都是可靠信号。(这个意思就是多个同种类型信号产生的时候,系统会阻塞该信号,最终产生完毕后,接触阻塞最终只有一个信号产生)
实时信号(Run-time)
实时信号都是未定义的信号,在用户定义之前。它的抵达是有序抵达,以数字小的为最高优先级。当有多个同类型的信号产生时,按顺序抵达。使用应配合宏来一起使用SIGRTMIN+n ,但是不能超过 SIGRTMAX 。它的范围是64-33,刚好32个。使用宏的原因是,Linuxthreads线程库使用了3个实时信号,posix线程库使用了2个。我们用宏编译器会自动转换的。
当实时信号和普通信号同时产生时,Linux以先处理普通信号。
被信号中止的系统调用和库函数
epoll类的系统调用,system v 的系统调用,select poll epoll,已经设置了超时的网络系统调用的函数等系统调用被中止后返回 ENTER 错误。
read, readv, write, writev, ioctl,wait,waitpid等函数被中断后,如果由signal函数注册的自定义函数/sigaction函数设置了 SA_RESTART 标志的话,这些被中断的系统调用会自动重启。
信号的处理方式
信号一般由产生到未决再到递达。产生:系统在该进程pcb的信号字段修改该进程的pending表中相应的有效位。未决:pending表中有未处理的信号,该进程还没有对相应的信号进行处理。递达:已经处理了相应的信号。递达有三种方式,忽略SIG_DFL,默认动作SIG_IGN,自定义handler的一个函数指针。忽略也是递达的一种方式,如果信号被阻塞永远不会被递达。
下图是我另一篇博客中关于task_struct的信号字段的截图
进程中保存信号的数据结构
信号在pcb中的三个数据结构。
block表:它又称信号屏蔽字,这个表中的有效位表示,即使信号处于未决状态也不能递达,该信号处于屏蔽状态
pending表:它又称未决表,该表记录了进程未处理的信号。它的有效位表示该信号进程已收到但还未处理。
handler表:表示信号的处理方式。
代码验证pending表与block表
#include <stdio.h>#include <signal.h>void handler(int signum){ printf("ctrl-c ----> SIGINT\n");}void printsigset(sigset_t * set){ size_t idx=0; for(idx=0;idx<32;idx++) { if(0==sigismember(set,idx)) putchar('0'); else putchar('1'); } putchar('\n');}int main(){ struct sigaction act,oact; sigset_t mask,oldmask,pending; act.sa_handler=handler; act.sa_flags=0; sigemptyset(&act.sa_mask); sigemptyset(&mask); sigemptyset(&oldmask); sigemptyset(&pending); sigaddset(&mask,SIGINT); sigprocmask(SIG_BLOCK,&mask,&oldmask); sigaction(SIGINT,&act,&oact); int second=0; while(second++<5) { sigpending(&pending); printf("pending table:\n"); printsigset(&pending); sleep(1); printf("block table:\n"); printsigset(&mask); } sigsuspend(&oldmask); printf("ok.. Now recovered block table\n"); sigprocmask(SIG_SETMASK,&oldmask,NULL); sigpending(&pending); printf("Now pending table\n"); printsigset(&pending); sigaction(SIGINT,&oact,NULL); return 0;}
特殊的三个信号
SIGKILL
不能被阻塞、忽略、捕捉。
SIGSTOP
不能被阻塞、忽略、捕捉。
SIGABRT
不能被阻塞、忽略,但是可以被捕捉,虽然可以捕捉,但是在执行完自定义函数后进程还是会被终止。唯一的区别,如果捕捉,会自动在自定义函数中调用 fclose(NULL)然后关闭所有I/O流的同时刷新I/O流缓冲区。
- linux 信号&信号处理
- linux 信号&信号处理
- linux 信号&信号处理
- linux 信号 信号集
- linux信号--阻塞信号
- Linux信号
- linux信号
- Linux信号
- linux 信号
- linux 信号
- linux 信号
- Linux 信号
- linux信号
- linux 信号
- linux 信号
- linux信号
- Linux信号
- Linux 信号
- Django Channels教程(一)
- Hibernate的CRUD
- 适配iphoneX要更改的内容
- mysql or语句的优化
- DAY1,2017.10.26
- Linux-信号
- 10月24日云栖精选夜读:2017杭州·云栖大会完美收官 虚拟化平台精彩回顾
- 《Java编程思想》学习之对象入门1.7输入和输出
- 11.1 用户识别机制
- hibernate检索方式
- 系统级性能分析工具 — Perf
- TCP/IP 协议 三次握手四次挥手
- js实时获取当前时间
- 如何在AS中把项目上传 到oschina(码云)