信号浅析(二)

来源:互联网 发布:农业国家数据库查询 编辑:程序博客网 时间:2024/05/19 18:38

之前简要地学了一些信号的基础知识,我们知道,没有前后冲突等bug的话,信号的作用非常棒,通过信号处理函数,可以实现许多异步操作。然而当有多个信号或同步或异步进入的时候,如果默认操作,则会有很多问题出现。要解决多个信号如何处理,必须要了解信号的处理机制。

有哪些信号处理机制?
假设内核正在做某件事,这时信号A过来了,内核立刻将这件事挂起并赶忙去处理信号A;然而这时,当内核正在处理信号A的时候,信号B又过来了,这时内核有4种选择:1、直接忽略信号B;2、将信号B阻塞,等处理完A再处理B;3、立刻挂起信号A的操作,先去处理B,再回来处理A;4、立刻中断信号A的操作,转而去处理B。
这四种模式都有各自的应用情况,分别简单介绍一下:1、这一种情况显然最为简单,在处理信号A时完全屏蔽信号B可以使程序主体逻辑更清晰,可以保障程序重要的部分完整可靠,但是忽略了信号之后可能会导致程序出现一些死循环等bug。一般可以用在信号A非常重要而信号B不那么重要的场景2、阻塞信号对于重要性相同的信号来说很好用,先来后到,排排队,一个一个处理,可以保证每个信号都能被处理到。3、这种情况类似于递归调用,虽然不是递归,但是其性质同递归类似。4、在经典模式下,经常采用这种信号处理机制。比如在read时,键盘输入hel的时候进来一个信号,并继续输入lo,这时程序转而处理信号B,待信号B处理完时程序会直接从read返回,并置error为EINTR,不再read。而我在mac上测试时,当处理完B后,程序会重新开始read,这时将缓冲区的内容打印,会打印出”lo”,而没有”hel”。
信号处理机制并没有好差之分,且信号处理机制需要设置的内容非常多,不可能为每种信号都设置,我们要做的就是为我们需要应对的信号设置好合适的处理方式即可。

那么如何设置信号处理机制呢?
如何设置信号处理机制有非常多方式,这里介绍其中一种:sigaction。

int sigaction(int signum, const struct sigaction *action, struct sigaction prevaction);struct sigaction{     void (* sa_handler)();                                     /*SIG_DFL, SIG_IGN, or function*/     void (* sa_sigaction)(int, siginfo_t *, void *);     /*new handler*/     sigset_t sa_mask;           /*signals to block while handling*/     int sa_flags;                    /*enable various behaviors*/}

结构体中sa_handler和sa_sigaction只能够二选一,如果采用旧的信号处理机制,则定义action.sa_handler = old_handler, 其中的那三种处理方式我们都很熟悉(忽略、中断和交函数处理); 如果采用新的处理方式,则定义action.sa_sigaction = new_handler。如果选择后一种信号处理机制则设置sa_flags的SA_SIGINFO位即可。
sa_sigaction由sa_mask和sa_flags控制,sa_flags设置信号处理模式,有四种模式,对是否阻塞是否重新开始是否传递信号产生原因等定义;而sa_mask则指定信号中有哪些是需要被阻塞的,可以用来防止数据损毁,通过sigpromask(修改整个信号集)及sigsetops(添加或删除信号集中的信号)两个函数来控制。

0 0
原创粉丝点击