int signalfd(int fd, const sigset_t *mask, int flags);
mask 引き数には、呼び出し元がこのファイルディスクリプタ経由で受け付けたい シグナル集合を指定する。この引き数で指定するシグナル集合の内容は、 sigsetops(3) で説明されているマクロを使って初期化することができる。 通常、ファイルディスクリプタ経由で受信するシグナル集合は、 そのシグナルがデフォルトの配送方法に基いて処理されるのを防ぐために、 sigprocmask(2) を使ってブロックしておくべきである。 シグナル SIGKILL と SIGSTOP を signalfd ファイルディスクリプタ経由で受信することはできない。 これらのシグナルが mask で指定された場合には黙って無視される。
fd 引き数が -1 の場合、 signalfd() は新しいファイルディスクリプタを生成し、 mask で指定されたシグナル集合をそのファイルディスクリプタに関連付ける。 fd 引き数が -1 以外の場合、 fd には有効な既存の signalfd ファイルディスクリプタを指定しなければならず、 そのディスクリプタに関連付けられているシグナル集合は mask を使って置き換えられる。
Linux 2.6.27 以降では、 以下の値のいくつかをビット単位の論理和 (OR) で指定することで、 signalfd() の振舞いを変更することができる。
バージョン 2.6.26 以前の Linux では、 flags 引き数は未使用であり、0 を指定しなければならない。
signalfd() が返すファイルディスクリプタは以下の操作をサポートしている。
struct signalfd_siginfo {
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; /* 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]; /* pad の大きさは 128 バイト
(将来のフィールド追加用の場所の確保) */
};
signalfd_siginfo
構造体の各フィールドは、
siginfo_t
構造体の同じような名前のフィールドと同様である。
siginfo_t
構造体については
sigaction(2)
に説明がある。
返された
signalfd_siginfo
構造体の全てのフィールドがあるシグナルに対して有効なわけではない。
どのフィールドが有効かは、
ssi_code
フィールドで返される値から判定することができる。
このフィールドは
siginfo_t
の
si_code
フィールドと同様である。詳細は
sigaction(2)
を参照。
一つのプロセスは複数の signalfd ファイルディスクリプタを生成することができる。 これにより、異なるファイルディスクリプタで異なるシグナルを受け取ることが できる (この機能は select(2), poll(2), epoll(7) を使ってファイルディスクリプタを監視する場合に有用かもしれない。 異なるシグナルが到着すると、異なるファイルディスクリプタが利用可能に なるからだ)。 一つのシグナルが二つ以上のファイルディスクリプタの mask に含まれている場合、そのシグナルの発生はそのシグナルを 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);
/* Block signals so that they arenaqt handled
according to their default dispositions */
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");
}
}
}