int signalfd(int fd, const sigset_t*mask, intflags);
mask 参数指出想要通过这个文件描述符接受的信号集。这个参数是信号集,它可以使用在 sigsetops(3)说明的宏来初始化。通常情况下,通过这个文件描述符接受的信号应该使用sigprocmask(2)阻塞,这样可以避免触发这些信号的默认处理方式。不可能通过文件描述符接受到信号SIGKILL 或SIGSTOP;如果这两个信号在mask 里指定则会被默默地忽略。
如果 fd 参数是 -1,那么调用创建一个新的文件描述符并且把 mask 指定的信号集与其关联。如果fd 不是 -1,它必须是一个有效的并已经存在的文件描述符,而mask用于替换之前与这个文件描述符关联的信号集。
从 Linux 2.6.27 开始,下面值可以经过位或运算放置在 flags 里以来改变signalfd() 的行为:
在包括 2.6.26 之前的版本里,flags 参数没有使用,并且必须指定为零。
signalfd() 返回的文件描述符支持如下操作:
struct signalfd_siginfo {
uint32_t ssi_signo; /* 信号编号 */
int32_t ssi_errno; /* 错误码 (未使用) */
int32_t ssi_code; /* 信号码 */
uint32_t ssi_pid; /* 发送都的 PID */
uint32_t ssi_uid; /* 发送都的真实UID */
int32_t ssi_fd; /* 文件描述符 (SIGIO) */
uint32_t ssi_tid; /* 内核定时器 ID (POSIX 定时器)
uint32_t ssi_band; /* 波动事件 (SIGIO) */
uint32_t ssi_overrun; /* POSIX 定时器超过次数 */
uint32_t ssi_trapno; /* 导致信号的陷阱号 */
int32_t ssi_status; /* 退出状态或信号 (SIGCHLD) */
int32_t ssi_int; /* sigqueue(2) 发送的整数 */
uint64_t ssi_ptr; /* sigqueue(2) 发送的指针 */
uint64_t ssi_utime; /* 用户CPU时消耗 (SIGCHLD) */
uint64_t ssi_stime; /* 系统CPU时消耗 (SIGCHLD) */
uint64_t ssi_addr; /* 产生信号的地址(对硬件信号) */
uint8_t pad[X]; /*填充到 128 字节 (允许将来添加字段) */
};
这个结构中的字段与 siginfo_t 结构中的同名字段有相同含意。siginfo_t 结构在sigaction(2) 里有描述。对于特定的信号并不是signalfd_siginfo 结构中的所有字段都有意义;有效的字段集可以通过其ssi_code域来判定。这个字段与siginfo_t 中的
si_code 字段相同;参考 sigaction(2) 了解细节。
一个进程可以创建多个 signalfd 文件描述符。这使得可以在不同的文件描述符上接受不同的信号。(这可能是有用的,如果使用select(2)、poll(2) 或epoll(7)来监视这个文件描述符;当不现的信号抵达时会有不同的文件描述符准备好了。)如果一个信号出现多个文件描述符的mask里,那么这个信号的出现会导致这些文件描述符中的某一个且只有一个可读。
$ ./signalfd_demo ^C # Control-C generates SIGINT Got SIGINT ^C Got SIGINT ^\ # Control-\ generates SIGQUIT Got SIGQUIT $
#include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
sigset_t mask;
int sfd;
struct signalfd_siginfo fdsi;
ssize_t s;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
/* 阻塞信号以使得它们不被默认的处理试方式处理 */
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
handle_error("sigprocmask");
sfd = signalfd(-1, &mask, 0);
if (sfd == -1)
handle_error("signalfd");
for (;;) {
s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
if (s != sizeof(struct signalfd_siginfo))
handle_error("read");
if (fdsi.ssi_signo == SIGINT) {
printf("Got SIGINT\n");
} else if (fdsi.ssi_signo == SIGQUIT) {
printf("Got SIGQUIT\n");
exit(EXIT_SUCCESS);
} else {
printf("Read unexpected signal\n");
}
}
}
/*这个例子只是很简单的说明了使用signalfd的方法,并没有真正发挥它的作用,有了这个API,就可以将信号处理作为IO看待,
每一个信号集合(或者某一个对应的信号)就会有对应的文件描述符,这样将信号处理的流程大大简化,将应用程序中的业务作为文件来操作,也体现了linux下的一切皆文件
的说法,非常好,假如有很多种信号等待着处理,每一个信号描述符对待一种信号的处理,那么就可以将信号文件描述符设置为非阻塞,同时结合epoll使用,对信号的
处理转化为IO复用,和这个有相似之处的API还有timerfd*/
linux新API---signalfd的使用方法,布布扣,bubuko.com
原文:http://blog.csdn.net/yusiguyuan/article/details/22934743