乱读天书, 不求甚解
周祎骏的个人云笔记
Toggle navigation
乱读天书, 不求甚解
主页
Linux:系统配置
Linux:用户管理
Linux:优化排错
Linux:进程调度
Linux:文件系统
Linux:网络
Linux:系统服务
Linux:安全
Linux:内核
容器:Docker
容器:containerd
容器编排:Kubernetes
IAC:Terraform
大数据:Hadoop
大数据:Zookeeper
大数据:Hbase
消息队列:rsyslog
消息队列:kafka
数据库:MySQL
数据库:MongoDB
搜索引擎:Elasticsearch
时序数据库:OpenTSDB
网站服务:Nginx
编程:Bash
编程:Perl
编程:Python
编程:C
编程:JAVA
编程:Rust
版本控制:gitlab
知识管理:docusaurus
常用小工具
关于我
标签
C 2.12 函数库signal.h
2018-06-17 08:23:04
52
0
0
admin
> 进程间信号处理 #常用信号列表: **SIGABRT** 调用abort函数时产生此信号。进程异常终止。 **SIGALRM** 超过用alarm函数设置的时间时产生此信号。 **SIGBUS** 指示一个实现定义的硬件故障。 **SIGCHLD** 在一个进程终止或停止时,SIGCHLD信号被送给其父进程。按系统默认,将 忽略此信号。如果父进程希望了解其子进程的这种状态改变,则应捕捉此信号。信号捕捉函数中通常要调用wait函数以取得子进程ID和其终止状态。 **SIGCONT** 此作业控制信号送给需要继续运行的处于停止状态的进程。如果接收到此信。 号的进程处于停止状态,则系统默认动作是使该进程继续运行,否则默认动作是忽略此信号。 **SIGEMT** 指示一个实现定义的硬件故障。 **SIGFPE** 此信号表示一个算术运算异常,例如除以0,浮点溢出等。 **SIGHUP** 如果终端界面检测到一个连接断开,则将此信号送给与该终端相关的控制进程 **SIGILL** 此信号指示进程已执行一条非法硬件指令。 **SIGINT** 当用户按中断键(Ctrl-C)时,终端驱动程序产生此信号并送至前台进程组中的每一个进程 **SIGIO** 此信号指示一个异步I/O事件。 **SIGIOT** 这指示一个实现定义的硬件故障。 **SIGKILL** 内核杀 **SIGPIPE** 在reader中止之后写Pipe的时候发送 **SIGPOLL** 当在一个可轮询设备上发生一特定事件时产生此信号。 **SIGPROF** Setitimer指定的Profiling Interval Timer所产生。 **SIGSEGV** 指示进程进行了一次无效的存储访问。 **SIGSTOP** 这是一个作业控制信号,它停止一个进程。不能被捕捉或忽略。 **SIGSYS** 指示一个无效的系统调用。 **SIGTERM** 这是由kill命令发送的系统默认终止信号。 **SIGTRAP** 指示一个实现定义的硬件故障。 **SIGTSTP** 交互停止信号,当用户按挂起键(Ctrl-Z)时,终端驱动程序产生此信号。 **SIGTTIN** 当一个后台进程组进程试图读其控制终端时,终端驱动程序产生此信号。 **SIGTTOU** 当一个后台进程组进程试图写其控制终端时产生此信号。 **SIGURG** 此信号通知进程已经发生一个紧急情况。 **SIGUSR1** 这是一个用户定义的信号,可用于应用程序。 **SIGUSR2** 这是一个用户定义的信号,可用于应用程序。 **SIGVTALRM** 当一个由setitimer(2)函数设置的虚拟间隔时间已经超过时产生此信号。 **SIGXCPU** 如果进程超过了其软CPU时间限制,则产生此信号。 **SIGXFSZ** 如果进程超过了其软文件长度限制,则产生此信号。 *** #函数 ##接收处理信号 **void (*signal (int signo, void (*func)(int))) (int)**: 第一个参数是信号编号,第二个参数是一个函数的指针(该函数参数是一个int ,返回为空)或者SIG_IGN(表示忽略此信号)或者SIG_DFL(接到信号后执行系统默认操作),signal函数返回的是一个函数指针,该指针指的函数参数是一个int ,返回为空。该函数成功的话返回以前信号处理的配置,出错的话返回SIG_ERR *因为该函数太复杂,所以我们用typedef把它包装一下* ``` #include <stdio.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> typedef void (*sigfunc)(int); sigfunc signal(int, sigfunc); void sig_handle(int signo) { if ( signo == SIGTERM ) printf("I catch 15 signal but i do not exit!\n"); else printf("Catch other signal and do nothing!\n"); } main() { if (signal(SIGTERM,sig_handle) == SIG_ERR) { printf("Catch SIGTERM failed\n"); exit(1); } if (signal(SIGUSR1,sig_handle) == SIG_ERR) { printf("Catch SIGUSR1 failed\n"); exit(1); } while (1==1) sleep(10); } ``` *** ##发信号 **int raise(int signo)**: 给进程自身发送信号,成功返回0,失败返回-1 **int kill(pid_t pid, int signo)**:向进程发送信号,pid=0表示向该进程进程组成员发送,pid<0表示向进程组id与pid绝对值相等的进程组成员发送。 > alarm 和pause 函数属于unistd.h abort函数属于stdlib.h *** ##信号集 信号集(屏蔽字)是一个数据结构,配置了一个程序想要阻塞哪些发给它的信号,然后改进程可以主动去检查是否有发给自己的对应信号被block了。相当于程序获得主动权,减少了信号中断带来的麻烦。这对一些原子性的设计非常重要。 **int sigemptyset(sigset_t *set)**: 初始化信号集,排除所有信号,成功返回0,失败返回-1 **int sigfillset(sigset_t *set)**:初始化信号集,包括所有信号,成功返回0,失败返回-1 **int sigaddset(sigset_t *set, int signo)**:向字符集中增加某一信号,成功返回0,失败返回-1 **int sigdelset(sigset_t *set, int signo)**:在字符集中删除某一信号,成功返回0,失败返回-1 **int sigismember(const sigset_t *set, int signo)**: 真返回1,假返回0 **int sigprocmask(int flag, const sigset_t *new_set, *sigset_t *old_set)**:将new_set设置为新的信号集,之前的信号集会被保存在old_set,成功返回0,出错返回-1 >flag 的选项 SIGBLOCK 该该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。set包含了希望阻塞的信号 SIGUNBLOCK 该该进程新的信号屏蔽字是其当前信号屏蔽字和set所指向信号集的交集。set包含了希望解除阻塞的信号 SIGSETMASK 该进程新的信号屏蔽是set指向的值 **int sigpending(sigset_t *set)**: 获得被信号集阻塞的信号,成功返回0,失败返回-1 ``` #include <stdio.h> #include <signal.h> void sig_handle(int signo) { if ( signo == SIGTERM ) printf("I catch 15 signal but i do not exit!\n"); } main() { signal(SIGTERM,sig_handle); sigset_t set_1,set_2,catch_set; sigprocmask(0,NULL,&set_1); if( ! sigismember(&set_1,SIGTERM)) printf("not block SIGTERM now\n"); sleep(100); sigaddset(&set_1,SIGTERM); if (sigprocmask(SIG_SETMASK,&set_1,&set_2)==0) printf("block SIGTERM now\n"); sleep(100); sigpending(&catch_set); if(sigismember(&catch_set,SIGTERM)) printf("found blocked SIGTERM\n"); sigprocmask(SIG_SETMASK,&set_2,NULL); sleep(100); } ``` **int sigsuspend(const sigset_t *sigmask)**:原子性的做到修改当前的信号屏蔽字,并且pause(),永远返回-1, errno设置为EINTR ##做到原子性的sigaction函数 * sigaction在接受到一个信号并运行对应函数的时候,会把这个信号加入屏蔽字的信号集,直到处理完再把这个信号从信号集中移除,这样我们就不会丢失这个信号。 * 现在很多机器上signal 其实就是用sigaction实现的。 * 如果在运行信号对应的函数时,发送来了多个同一信号,他们并不会排队,会按照一个信号处理。 **int sigaction(int signo, const struct sigaction *new_act, struct sigaction *old_act)**:指定接受到某信号后的行为,如果new_act非NULL,就设置成new_act,如果old_act非空,就把之前的配置写入old_act,成功返回0,失败返回-1 ``` struct sigaction { void (*sa_handler)(); //一个函数的指针或者SIG_IGN(表示忽略此信号)或者SIG_DFL(接到信号后执行系统默认操作) sigset_t sa_mask; //函数运行时屏蔽的信号集 int sa_flags; /* SA_NOCLDSTOP 如果信号是SIGCHLD,如果子进程停止,不产生信号,如果是子进程终止,仍旧产生信号 SA_RESTART 由此信号中断的系统调用自动再启动 SA_ONSTACK 如果用sigaltstack声明了替换栈,则此信号递送给替换栈上的进程(检查段错误时用,因为段错误的时候进程自己的段已经不能用了,所以会给信号处理函数准备独立的栈空间,高级技巧) SA_NOCLDWAIT 如果信号是SIGCHLD,则当调用进程的子进程终止时,不创建僵死进程。若调用进程在后面调用wait,则阻塞到它所有子进程都终止,此时返回-1,errno设置为ECHILD SA_NODEFER 当捕捉到此信号时,在执行其信号捕捉函数时,系统不自动阻塞此信号 SA_RESETHAND 对此信号的处理方式在此信号捕捉函数的入口处重置为SIG_DFL SA_SIGINFO 获取信号详细信息,高级技巧 */ } ```
上一篇:
C 2.11 Linux函数库utime.h
下一篇:
C 2.13 函数库setjmp.h
文档导航