Provided by: manpages-ja-dev_0.5.0.0.20140515+dfsg-2_all bug

名前

       signalfd - シグナル受け付け用のファイルディスクリプタを生成する

書式

       #include <sys/signalfd.h>

       int signalfd(int fd, const sigset_t *mask, int flags);

説明

       signalfd()   は、呼び出し元宛てのシグナルを受け付けるために使用されるファイル ディスクリプ
       タを生成する。 この方法はシグナルハンドラや sigwaitinfo(2)  を用いる方法の代わりとなるもの
       であり、このファイルディスクリプタを  select(2), poll(2), epoll(7)  で監視できるという利点
       がある。

       mask 引き数には、呼び出し元がこのファイルディスクリプタ経由で受け付けたい シグナル集合を指
       定する。この引き数で指定するシグナル集合の内容は、  sigsetops(3)  で説明されているマクロを
       使って初期化することができる。  通常、ファイルディスクリプタ経由で受信するシグナル集合は、
       そのシグナルがデフォルトの配送方法に基いて処理されるのを防ぐために、   sigprocmask(2)   を
       使ってブロックしておくべきである。 シグナル SIGKILLSIGSTOP を signalfd  ファイルディス
       クリプタ経由で受信することはできない。  これらのシグナルが mask で指定された場合には黙って
       無視される。

       fd 引き数が -1 の場合、 signalfd()  は新しいファイルディスクリプタを生成し、 mask で指定さ
       れたシグナル集合をそのファイルディスクリプタに関連付ける。  fd 引き数が -1 以外の場合、 fd
       には有効な既存の signalfd ファイルディスクリプタを指定しなければならず、  そのディスクリプ
       タに関連付けられているシグナル集合は mask を使って置き換えられる。

       Linux  2.6.27  以降では、  以下の値のいくつかをビット単位の論理和  (OR) で指定することで、
       signalfd() の振舞いを変更することができる。

       SFD_NONBLOCK  新しく生成されるオープンファイル記述 (open file description)  の  O_NONBLOCK
                     ファイルステータスフラグをセットする。  このフラグを使うことで、  O_NONBLOCK
                     をセットするために fcntl(2) を追加で呼び出す必要がなくなる。

       SFD_CLOEXEC   新しいファイルディスクリプタに対して  close-on-exec  (FD_CLOEXEC)   フラグを
                     セットする。 このフラグが役に立つ理由については、 open(2)  の O_CLOEXEC フラ
                     グの説明を参照のこと。

       バージョン 2.6.26 以前の Linux では、 flags 引き数は未使用であり、0 を指定しなければならな
       い。

       signalfd()  が返すファイルディスクリプタは以下の操作をサポートしている。

       read(2)
              mask      に指定されているシグナルのうち一つ以上がそのプロセスに対して     処理待ち
              (pending) であれば、それらのシグナルの情報が read(2)   に渡されたバッファを使って、
              signalfd_siginfo  構造体に格納されて返される。 read(2) は、バッファに格納可能な範囲
              でできるだけ多くの処理待ちのシグナルに   ついての情報を返す。    バッファは最低でも
              sizeof(struct  signalfd_siginfo) バイトの大きさがなければならない。 read(2)  の返り
              値は読み出されたトータルのバイト数である。

              read(2)  が行われた結果、シグナルは消費され、  これらのシグナルはそのプロセスに対し
              ては処理待ちではなくなる          (つまり、シグナルハンドラで捕捉されることもなく、
              sigwaitinfo(2)  を使って受け取ることもできなくなる)。

              mask       に指定されているシグナルがそのプロセスに対して一つも処理待ちでなければ、
              read(2)  は、 mask で指定されたシグナルのうちいずれか一つがそのプロセスに対して発生
              するまで 停止  (block)  する、もしくはファイルディスクリプタが非停止  (nonblocking)
              に設定されている場合はエラー EAGAIN で失敗する。

       poll(2), select(2) (と同様の操作)
              mask     に指定されたシグナルのうち一つ以上がそのプロセスに対して処理待ちであれば、
              ファイルディスクリプタは読み出し可能となる (select(2)  の readfds 引き数や  poll(2)
              の POLLIN フラグ)。

              signalfd ファイルディスクリプタは、これ以外のファイルディスクリプタ 多重 API である
              pselect(2), ppoll(2), epoll(7)  もサポートしている。

       close(2)
              ファイルディスクリプタがそれ以降は必要なくなった際には、クローズすべきである。 同じ
              signalfd   オブジェクトに関連付けられたファイルディスクリプタが全て  クローズされる
              と、そのオブジェクト用の資源がカーネルにより解放される。

   signalfd_siginfo 構造体
       signalfd ファイルディスクリプタからの read(2)  で返される signalfd_siginfo  構造体のフォー
       マットは以下の通りである。

           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(3) から送られた整数 */
               uint64_t ssi_ptr;     /* sigqueue(3) から送られたポインタ */
               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_tsi_code フィールドと同様である。詳細は sigaction(2)  を参照。

   fork(2) での扱い
       fork(2)   が行われると、子プロセスは  signalfd ファイルディスクリプタのコピーを 継承する。
       子プロセスでこのファイルディスクリプタから  read(2)   を行うと、子プロセスに対するキューに
       入っているシグナルに関する 情報が返される。

   execve(2) での扱い
       他のファイルディスクリプタと全く同様に、  signalfd ファイルディスクリプタも execve(2) の前
       後でオープンされたままとなる。但し、そのファイルディスクリプタに  close-on-exec   のマーク
       (fcntl(2)   参照) が付いている場合はクローズされる。 execve(2)  の前に読み出し可能となって
       いた全てのシグナルは新しく起動されたプログラム でも引き続き読み出し可能である  (これは伝統
       的なシグナルの扱いと同じであり、 処理待ちのブロックされたシグナルは execve(2) の前後で処理
       待ちのままとなる)。

   スレッドでの扱い
       マルチスレッドプログラムにおける signalfd ファイルディスクリプタの扱いは  シグナルの標準的
       な扱いと全く同じである。  言い換えると、あるスレッドが signalfd ファイルディスクリプタから
       読み出しを行うと、そのスレッド自身宛てのシグナルとプロセス (すなわち スレッドグループ全体)
       宛てのシグナルが読み出される。 (スレッドは同じプロセスの他のスレッド宛てのシグナルを読み出
       すことはできない。)

返り値

       成功すると、 signalfd()  は signalfd ファイルディスクリプタを返す。 返されるファイルディス
       クリプタは、  fd  が  -1 の場合は新規のファイルディスクリプタであり、 fd が有効な signalfd
       ファイルディスクリプタだった場合は fd 自身である。 エラーの場合、-1  を返し、  errno  にエ
       ラーを示す値を設定する。

エラー

       EBADF  ファイルディスクリプタ fd が有効なファイルディスクリプタでない。

       EINVAL fd が有効な signalfd ファイルディスクリプタではない。

       EINVAL flags が無効である。もしくは、Linux 2.6.26 以前の場合には flags が 0 以外である。

       EMFILE オープン済みのファイルディスクリプタの数がプロセスあたりの上限に 達していた。

       ENFILE オープン済みのファイル総数がシステム全体の上限に達していた。

       ENODEV (カーネル内の) 無名 inode デバイスをマウントできなかった。

       ENOMEM 新しい signalfd ファイルディスクリプタを生成するのに十分なメモリがなかった。

バージョン

       signalfd()   はカーネル 2.6.22 以降の Linux で利用可能である。 正しく動作する glibc 側のサ
       ポートはバージョン 2.8 以降で提供されている。 signalfd4()   システムコール  (「注意」参照)
       は カーネル 2.6.27 以降の Linux で利用可能である。

準拠

       signalfd()  と signalfd4()  は Linux 固有である。

注意

       実際の Linux のシステムコールでは size_t sizemask という引き数が追加で必要である。この引き
       数で mask のサイズを指定する。 glibc の signalfd()  ラッパー関数にはこの引き数は含まれず、
       ラッパー関数が必要な値を計算して内部で呼び出すシステムコールに提供する。

       一つのプロセスは複数の  signalfd  ファイルディスクリプタを生成することができる。  これによ
       り、異なるファイルディスクリプタで異なるシグナルを受け取ることが    できる     (この機能は
       select(2), poll(2), epoll(7)  を使ってファイルディスクリプタを監視する場合に有用かもしれな
       い。 異なるシグナルが到着すると、異なるファイルディスクリプタが利用可能に なるからだ)。 一
       つのシグナルが二つ以上のファイルディスクリプタの mask に含まれている場合、そのシグナルの発
       生はそのシグナルを mask に含むファイルディスクリプタのうちいずれか一つから読み出すことがで
       きる。

   下層にある Linux のシステムコール
       下層にある Linux システムコールは二種類あり、 signalfd()  と、もっと新しい signalfd4()  で
       ある。 signalfd()  は flags 引き数を実装していない。 signalfd4()  では上記の値の flags  が
       実装されている。  glibc 2.9 以降では、 signalfd()  のラッパー関数は、 signalfd4() が利用可
       能であれば、これを使用する。

バグ

       カーネル 2.6.25 より前では、 sigqueue(3)  により送信されたシグナルと一緒に渡されるデータで
       は、フィールド ssi_ptrssi_int は設定されない。

       下記のプログラムは、シグナル  SIGINTSIGQUIT を signalfd ファイルディスクリプタ経由で受
       信する。 シグナル SIGQUIT 受信後にプログラムは終了する。  以下に示すシェルセッションにこの
       プログラムの使い方を示す。

           $ ./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 aren't 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");
               }
           }
       }

関連項目

       eventfd(2),  poll(2),  read(2),  select(2),  sigaction(2), sigprocmask(2), sigwaitinfo(2),
       timerfd_create(2), sigsetops(3), sigwait(3), epoll(7), signal(7)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部である。  プロジェクト
       の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。