-
一 SIGNAL
-
信号(signal),又称为软中断信号,用来通知进程发生了异步事件。进程之间可以互
相发送软中断信号。 内核也可以因为内部事件而给进程发送信号, 通知进程发生了某个事件。
注意,信号只是用来通知进程发生了什么事件,并不给该进程传递任何数据。
进程对各种信号处理方法可以分为三类:- 1 类似中断的处理程序, 对于需要处理的信号, 进程可以指定处理函数,由该函数来处理;
- 2 忽略某个信号,对该信号不做任何处理,就像未发生过一样
- 3 对该信号的处理保留系统的默认值, 这种缺省操作, 对大部分的信号的缺省操作是使得进程终止
二 常用信号
- 可以输入命令
kill -l
查询系统支持的所有信号,在头文件<signal.h>
中被定义,以‘SIG’为开头。 系统中两个不能捕捉、忽略的信号是:SIGKILL,SIGSTOP
向某一进程发送信号使用命令,默认发送SIGTERM信号
kill [ -signal | -s signal ] pid ...
三 常用函数
3.1 kill 函数
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
3.2 sigaction函数
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
- sigaction()函数成功返回 0,否则返回-1。
- signum :指出需要改变处理方法的信号,如 SIGINT 信号,但 SIGKILL 和 SIGSTOP这两个信号是不可捕捉的。
- act 和 oldact : sigaction 结构体的指针, act 为要设置的对信号的新处理方式,而 oldact 为原来对信号的处理方式。
struct sigaction
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
- sa_handler:一个函数指针,用来指定信号发生时调用的信号处理函数,默认使用此,
- sa_sigaction:同上,另一个信号处理函数,区别在于它可以提供更多的信息,但只有当 sa_flags 包含了SA_SIGINFO标志时才调用它,否则调用上边的那个sa_handler
- sa_mask :指定在信号处理函数执行期间需要被屏蔽的信号,特别是当某个信号被处理时, 它自身会被自动放入进程的信号掩码, 因此在信号处理函数执行期间这个信号不会再度发生
- sa_flags:指定信号处理的行为,如SA_SIGINFO,使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数
3.3 siginfo_t
主要是为上一篇串口中断的区分收发信号而写的。siginfo_t参考
typedef struct {
int si_signo; /*Signal number being delivered,eg: SIGIO */
int si_code; /*Signal code.eg: POLL_IN,POLL_OUT就是它了,区分SIGIO 是输入还是输出*/
union sigval si_value; /Signal value.. */
int si_errno; /**/
pid_t si_pid; /*Process ID of sending process.*/
uid_t si_uid; /*Real user ID of sending process.*/
void *si_addr; /**/
int si_status; /**/
int si_band; /**/
} siginfo_t;
Signal | Code | Reason Additional | Fields |
---|---|---|---|
SIGIO/SIGPOLL | POLL_IN | Data input available. | si_band |
POLL_OUT | Output buffers available. | ||
POLL_MSG | Input message available. | ||
POLL_ERR | I/O error. | ||
POLL_PRI | High priority input available. | ||
POLL_HUP | Device disconnected. |
因此上一讲中的串口信号安装更改下就可以了。
...
struct sigaction sact;
sigemptyset(&sact.sa_mask); //一般都先清空关注的信号集
sact.sa_flags=SA_SIGINFO;
sact.sa_sigaction=signal_action; //信号处理函数,由于利用了信号附加信息
...
...
void signal_action(int signum,siginfo_t *info,void *myact){
if(info.si_code == POLL_IN)
...
else if(info.si_code == POLL_OUT)
...
}
...
但实践起来接收到的si_code 根本就不是POLL_IN,POLL_OUT,不知道怎么回事。它的值居然是128,查了下定义POLL_IN=1,POLL_OUT=2,醉了