select(2) のサンプル

以下のプログラムを実行すると stdin の入力待ちになり、 改行を入力するとメッセージを出して終了する。 Ctrl-C (SIGINT) を送ると「detected exception; retry」と 出て継続。また一秒ごとに「timed out; retry」と 出力して select をやりなおす。

sigaction を使っているので微妙に移植性が低いかもしれない。

このディレクトリの select.c がプレーンテキスト版なので コンパイルにでも使ってほしい。

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>

static void
noop(int signo)
{
    return;
}

#define BUFSIZE 1024

int
main(int argc, char **argv)
{
    char *buf[BUFSIZE];
    struct sigaction act;

    act.sa_handler = noop;
    sigemptyset(&act.sa_mask);
#ifdef SA_RESTART
    act.sa_flags = SA_RESTART;
#endif
    if (sigaction(SIGINT, &act, NULL) < 0) {  /* SIGINTをマスク */
        fputs("sigaction errror\n", stderr);
        exit(3);
    }

    for (;;) {
        int n;
        fd_set readset;
        struct timeval time;

        /* fd_setの準備 */
        FD_ZERO(&readset);
        FD_SET(STDIN_FILENO, &readset);
        /* timeの準備 */
        time.tv_sec = 1;
        time.tv_usec = 0;
        /* selectする */
        n = select(STDIN_FILENO + 1, &readset, NULL, NULL, &time);
        if (n > 0)
            break;
        /* 返り値が 0 ならタイムアウト */
        if (n == 0) puts("timed out; retry");
        /* 返り値が負の数なら例外 */
        else if (n < 0) puts("detect exception; retry");
    }
    read(STDIN_FILENO, buf, BUFSIZE);  /* 絶対にブロックしない */
    puts("read ok");
    exit(0);
}

Copyright (c) 2002 Minero Aoki <aamine@loveruby.net>