例 4–17 は、「生産者 / 消費者」問題の生産者と消費者をそれぞれ別のプロセスで表現したものです。メインルーチンは、子プロセスと共有されているメモリーを 0 で初期化し、それを自分のアドレス空間にマッピングします。
子プロセスが 1 つ生成され、消費者の処理が実行されます。親プロセスは生産者の処理を実行します。
この例では、生産者と消費者を呼び出す各駆動ルーチンも示しています。producer_driver() は stdin から文字を読み込み、producer() を呼び出します。consumer_driver() は consumer() を呼び出して文字を受け取り、stdout に書き出します。
例 4–17 のデータ構造は、条件変数による「生産者 / 消費者」の例のデータ構造 (例 4–4 を参照) と同じです。2 つのセマフォーは、いっぱいになったバッファー数と空のバッファー数をそれぞれ表します。これらのセマフォーは、バッファーが空になるまで生産者を待たせ、バッファーがいっぱいになるまで消費者を待たせます。
main() {
int zfd;
buffer_t *buffer;
pthread_mutexattr_t mattr;
pthread_condattr_t cvattr_less, cvattr_more;
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;
pthread_mutex_attr_init(&mattr);
pthread_mutexattr_setpshared(&mattr,
PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&buffer->lock, &mattr);
pthread_condattr_init(&cvattr_less);
pthread_condattr_setpshared(&cvattr_less, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&buffer->less, &cvattr_less);
pthread_condattr_init(&cvattr_more);
pthread_condattr_setpshared(&cvattr_more,
PTHREAD_PROCESS_SHARED);
pthread_cond_init(&buffer->more, &cvattr_more);
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);
}
}