Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_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  Set the O_NONBLOCK file status  flag  on  the  open  file  description  (see
                     open(2))   referred  to  by  the new file descriptor.  Using this flag saves
                     extra calls to fcntl(2)  to achieve the same result.

       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 {
               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;     /* シグナルを生成したアドレス
                                         (ハードウェアが生成したシグナルの場合) */
               uint16_t ssi_addr_lsb; /* アドレスの最下位ビット (LSB)
                                         (SIGBUS; Linux 2.6.37 以降) */
               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)  を行うと、子プロセスに対するキューに
       入っているシグナルに関する 情報が返される。

   Semantics of file descriptor passing
       As with other file descriptors, signalfd file descriptors can be passed to another process
       via a UNIX domain socket (see unix(7)).  In the receiving process,  a  read(2)   from  the
       received file descriptor will return information about signals queued to that process.

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

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

   epoll(7) semantics
       If a process adds (via epoll_ctl(2))  a signalfd file descriptor to an epoll(7)  instance,
       then  epoll_wait(2)  returns events only for signals sent to that process.  In particular,
       if the process then uses fork(2)  to create a child process, then the child will  be  able
       to  read(2)   signals  that  are  sent  to  it  using  the  signalfd  file descriptor, but
       epoll_wait(2)  will not indicate that the signalfd file  descriptor  is  ready.   In  this
       scenario, a possible workaround is that after the fork(2), the child process can close the
       signalfd file descriptor that it inherited from the parent process and then create another
       signalfd  file descriptor and add it to the epoll instance.  Alternatively, the parent and
       the child could delay creating their (separate) signalfd file descriptors and adding  them
       to the epoll instance until after the call to fork(2).

返り値

       成功すると、 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 固有である。

注意

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

       Attempts to include SIGKILL and SIGSTOP in mask are silently ignored.

       The signal mask employed by a signalfd file descriptor can be viewed via the entry for the
       corresponding  file descriptor in the process's /proc/[pid]/fdinfo directory.  See proc(5)
       for further details.

   Limitations
       The signalfd mechanism can't be used to receive signals that are synchronously  generated,
       such  as  the  SIGSEGV signal that results from accessing an invalid memory address or the
       SIGFPE signal that results from an arithmetic error.  Such signals can be caught only  via
       signal handler.

       As  described  above,  in  normal  usage  one blocks the signals that will be accepted via
       signalfd().  If spawning a child process to execute a helper program (that does  not  need
       the  signalfd file descriptor), then, after the call to fork(2), you will normally want to
       unblock those signals before calling execve(2), so that the helper  program  can  see  any
       signals  that  it  expects  to see.  Be aware, however, that this won't be possible in the
       case of a helper program spawned behind the  scenes  by  any  library  function  that  the
       program may call.  In such cases, one must fall back to using a traditional signal handler
       that writes to a file descriptor monitored by select(2), poll(2), or epoll(7).

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

       下層にある 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(fdsi));
               if (s != sizeof(fdsi))
                   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 プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。