マルチスレッドのプログラミング

「生産者 / 消費者」問題の例

例 6–2 に、「生産者 / 消費者」問題の生産者と消費者をそれぞれ別のプロセスで示します。メインルーチンは、子プロセスと共有されているメモリーを 0 で初期化し、それを自分のアドレス空間にマッピングします。mutex_init()cond_init() を呼び出さなければならないのは、それらの同期変数のタイプが USYNC_PROCESS だからです。

子プロセスが 1 つ生成され、消費者の処理が実行されます。親プロセスは生産者の処理を実行します。

この例では、生産者と消費者を呼び出す各駆動ルーチンも示しています。producer_driver は、stdin から文字を読み込み、producer を呼び出します。consumer_driver は、consumer を呼び出して文字を受け取り、stdout に書き出します。

例 6–2 のデータ構造は、条件変数によるソリューションで使用したものと同じです。「片方向リンクリストの入れ子のロック」を参照してください。


例 6–2 USYNC_PROCESS を使用した「生産者 / 消費者」問題

main() {
    int zfd;
    buffer_t *buffer;

    zfd = open(“/dev/zero”, O_RDWR);
    buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
        PROT_READ|PROT_WRITE, MAP_SHARED, zfd, 0);
    buffer->occupied = buffer->nextin = buffer->nextout = 0;

    mutex_init(&buffer->lock, USYNC_PROCESS, 0);
    cond_init(&buffer->less, USYNC_PROCESS, 0);
    cond_init(&buffer->more, USYNC_PROCESS, 0);
    if (fork() == 0)
        consumer_driver(buffer);
    else
        producer_driver(buffer);
}

void producer_driver(buffer_t *b) {
    int item;

    while (1) {
        item = getchar();
        if (item == EOF) {
            producer(b, `\0');
            break;
        } else
            producer(b, (char)item);
    }
}

void consumer_driver(buffer_t *b) {
    char item;

    while (1) {
        if ((item = consumer(b)) == '\0')
            break;
        putchar(item);
    }
}

子プロセスが 1 つ生成され、消費者の処理が実行されます。親プロセスは生産者の処理を実行します。