C 实现生产者/消费者沟通

C 实现生产者/消费者沟通,c,unix,pthreads,buffer,producer-consumer,C,Unix,Pthreads,Buffer,Producer Consumer,我正试图通过一个有界缓冲区来实现生产者/消费者通信,该缓冲区使用我已经在C中实现的信号量和锁。我需要生产者将“hello world”放在一个5字节的缓冲区中,每次一个字符。如果缓冲区已满,生产者需要阻止。我正在努力找出如何将字符串放在缓冲区上。以下是我到目前为止的情况: #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define

我正试图通过一个有界缓冲区来实现生产者/消费者通信,该缓冲区使用我已经在C中实现的信号量和锁。我需要生产者将“hello world”放在一个5字节的缓冲区中,每次一个字符。如果缓冲区已满,生产者需要阻止。我正在努力找出如何将字符串放在缓冲区上。以下是我到目前为止的情况:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define BUF_SIZE 5

// the buffer works like a stack for
// the sake of simplicity, if needed
// we may implement a queue
 typedef struct {
    int buf[BUF_SIZE]; // the buffer
    size_t len; // number of items in the buffer
    pthread_mutex_t mutex; // needed to add/remove data from the buffer
    pthread_cond_t can_produce; // signaled when items are removed
    pthread_cond_t can_consume; // signaled when items are added
 } buffer_t;

// produce random numbers
void* producer(void *arg) {
    buffer_t *buffer = (buffer_t*)arg;

while(1) {
 #ifdef UNDERFLOW
    // used to show that if the producer is somewhat "slow"
    // the consumer will not fail (i.e. it'll just wait
    // for new items to consume)
    sleep(rand() % 3);
 #endif

    pthread_mutex_lock(&buffer->mutex);

    if(buffer->len == BUF_SIZE) { // full
        // wait until some elements are consumed
        pthread_cond_wait(&buffer->can_produce, &buffer->mutex);
    }

    // in real life it may be some data fetched from
    // sensors, the web, or just some I/O
    int t = rand();
    printf("Produced: %d\n", t);

    // append data to the buffer
    buffer->buf[buffer->len] = t;
    ++buffer->len;

    // signal the fact that new items may be consumed
    pthread_cond_signal(&buffer->can_consume);
    pthread_mutex_unlock(&buffer->mutex);
}

// never reached
return NULL;
}

// consume random numbers
void* consumer(void *arg) {
buffer_t *buffer = (buffer_t*)arg;

while(1) {
#ifdef OVERFLOW
    // show that the buffer won't overflow if the consumer
    // is slow (i.e. the producer will wait)
    sleep(rand() % 3);
 #endif
    pthread_mutex_lock(&buffer->mutex);

    if(buffer->len == 0) { // empty
        // wait for new items to be appended to the buffer
        pthread_cond_wait(&buffer->can_consume, &buffer->mutex);
    }

    // grab data
    --buffer->len;
    printf("Consumed: %d\n", buffer->buf[buffer->len]);

    // signal the fact that new items may be produced
    pthread_cond_signal(&buffer->can_produce);
    pthread_mutex_unlock(&buffer->mutex);
}

// never reached
return NULL;
}

int main(int argc, char *argv[]) {
buffer_t buffer = {
    .len = 0,
    .mutex = PTHREAD_MUTEX_INITIALIZER,
    .can_produce = PTHREAD_COND_INITIALIZER,
    .can_consume = PTHREAD_COND_INITIALIZER
};

pthread_t prod, cons;
pthread_create(&prod, NULL, producer, (void*)&buffer);
pthread_create(&cons, NULL, consumer, (void*)&buffer);

pthread_join(prod, NULL); // will wait forever
pthread_join(cons, NULL);

return 0;
}
#包括
#包括
#包括
#包括
#定义BUF_尺寸5
//缓冲区的工作方式类似于一个堆栈
//为了简单起见,如果需要的话
//我们可以实现一个队列
类型定义结构{
int buf[buf_SIZE];//缓冲区
size\u t len;//缓冲区中的项目数
pthread_mutex_t mutex;//需要从缓冲区添加/删除数据
pthread_cond_t can_product;//删除项时发出信号
pthread_cond_t can_consum;//添加项时发出信号
}缓冲区;
//产生随机数
无效*生产者(无效*参数){
buffer_t*buffer=(buffer_t*)arg;
而(1){
#ifdef底流
//用于表示如果制作人有点“慢”
//消费者不会失败(即,它只是等待
//用于新项目消费)
睡眠(rand()%3);
#恩迪夫
pthread_mutex_lock(&buffer->mutex);
如果(buffer->len==BUF_SIZE){//full
//等待某些元素被消耗
pthread_cond_wait(&buffer->can_product,&buffer->mutex);
}
//在现实生活中,它可能是从
//传感器、网络或只是一些I/O
int t=rand();
printf(“生成:%d\n”,t);
//将数据追加到缓冲区
buffer->buf[buffer->len]=t;
++缓冲->透镜;
//发出新物品可能被消费的信号
pthread_cond_信号(&buffer->can_consum);
pthread_mutex_unlock(&buffer->mutex);
}
//从未达到
返回NULL;
}
//消费随机数
无效*使用者(无效*参数){
buffer_t*buffer=(buffer_t*)arg;
而(1){
#ifdef溢出
//表明如果使用者
//速度慢(即制作人将等待)
睡眠(rand()%3);
#恩迪夫
pthread_mutex_lock(&buffer->mutex);
如果(buffer->len==0){//empty
//等待将新项目追加到缓冲区
pthread_cond_wait(&buffer->can_consume,&buffer->mutex);
}
//抓取数据
--缓冲->透镜;
printf(“已消耗:%d\n”,缓冲区->缓冲区->len]);
//表明可能会生产新产品
pthread_cond_信号(&buffer->can_product);
pthread_mutex_unlock(&buffer->mutex);
}
//从未达到
返回NULL;
}
int main(int argc,char*argv[]){
缓冲区\u t缓冲区={
.len=0,
.mutex=PTHREAD\u mutex\u初始值设定项,
.can\u product=PTHREAD\u COND\u初始值设定项,
.can\u consume=PTHREAD\u COND\u初始值设定项
};
pthread_t prod,cons;
pthread_创建(&prod,NULL,producer,(void*)&buffer);
pthread_创建(&cons,NULL,consumer,(void*)&buffer);
pthread_join(prod,NULL);//将永远等待
pthread_join(cons,NULL);
返回0;
}

堆栈是后进先出的。不是你想要的

我将强烈地实现一个带有头和尾指针的循环缓冲区

然后使用互斥锁(不需要信号量)锁定关键代码

(生产者的关键代码是添加/尝试添加字符的位置)

(消费者的关键代码是删除/尝试删除字符的位置)

互斥锁的作用是使两个关键变量“head”和“tail”保持稳定
当任何一个进程正在访问循环队列时。

看起来很不错。您可以让使用者从缓冲区[0]中吃东西,然后像这样移动任何剩余的字节:memmove(buffer->buf,buffer->buf+1,sizeof(int)*buffer->len);此外,您通常希望将if(!condition_true)更改为while(!condition_true),以处理信号中断,以及当您有更多线程时(这很常见)。