SIGURG と SIGIO の場合、各ソケットにはプロセス番号とプロセスグループ ID があります。これらの値はゼロに初期化されますが、先の例で示しているように、F_SETOWN fcntl(2) を使用してあとから定義し直すことができます。fcntl(2) の 3 番目の引数が正の場合、ソケットのプロセス ID を設定します。fcntl(2) の 3 番目の引数が負の場合、ソケットのプロセスグループ ID を設定します。SIGURG シグナルと SIGIO シグナルの受信側として許可されるのは、呼び出し側のプロセスだけです。同様に、fcntl(2)、F_GETOWN は、ソケットのプロセス番号を返します。
SIGURG と SIGIO の受信は、ioctl(2) を使用してソケットをユーザーのプロセスグループに割り当てることによっても有効にできます。
/* oobdata はルーチンを処理する帯域外データ */
sigset(SIGURG, oobdata);
int pid = -getpid();
if (ioctl(client, SIOCSPGRP, (char *) &pid) < 0) {
perror("ioctl: SIOCSPGRP");
}
サーバープロセスで便利なシグナルとして、ほかに SIGCHLD が挙げられます。このシグナルは、任意の子プロセスがその状態を変更した場合にプロセスに配信されます。通常、サーバーはこのシグナルを使用して、明示的に終了を待機せずに、あるいは終了ステータスを周期的にポーリングせずに、終了した子プロセスの「リープ (刈り取り)」を行います。たとえば、先に示したリモートログインサーバーループは、例 2-16 に示すように拡大できます。
int reaper();
...
sigset(SIGCHLD, reaper);
listen(f, 5);
while (1) {
int g, len = sizeof from;
g = accept(f, (struct sockaddr *) &from, &len);
if (g < 0) {
if (errno != EINTR)
syslog(LOG_ERR, "rlogind: accept: %m");
continue;
}
...
}
#include <wait.h>
reaper()
{
int options;
int error;
siginfo_t info;
options = WNOHANG | WEXITED;
bzero((char *) &info, sizeof(info));
error = waitid(P_ALL, 0, &info, options);
}
親サーバープロセスがその子のリープに失敗する場合、ゾンビプロセスが生じます。