多线程编程指南

生成方和使用者问题示例

示例 4–17 说明了位于不同进程中的生成方和使用者的问题。主例程将与其子进程共享的全零内存段映射到其地址空间。

创建子进程是为了运行使用者,父进程则运行生成方。

本示例还说明了生成方和使用者的驱动程序。producer_driver() 可从 stdin 读取字符并调用 producer()consumer_driver() 通过调用 consumer() 来获取字符并将这些字符写入 stdout 中。

示例 4–17 中的数据结构与示例 4–4 中所示用于条件变量示例的结构类似。两个信号分别空缓冲区和满缓冲区的数量,通过这些信号可确保生成方等待缓冲区变空,使用者等待缓冲区变满为止。


示例 4–17 跨进程边界同步

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);

    }

}