Linux下的简单生产、消费模型的实现(下)

生产消费模型中生产者与消费者是互相独立进程,而各个进程的内存空间是相互独立的,因为我们需要为生产者与消费者建立一块共享内存区,用于保存生产出的“产品”。
本文使用循环队列保存“产品”,队列为空时有head=tail=0
struct sharebuf
{
    int buffer[MAX_BUFFER_SIZE];
    int head;
    int tail;
};

共享内存的命名与信号量的命名相同,我们一般使用宏定义
#define KEY_MEM ((key_t)103040914)
Linux提供的库函数为

#include < sys/ipc.h>
#include < sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

此函数将建立一块大小为size字节的共享内存。
需要注意的是,shmget建立的一块共享内存必须使用shmat()才能得到这块内存的地址,库函数如下:

void *shmat(int shmid, const void * shmaddr, int shmflg);

其中shmaddr,shmflg参数使用0即可。返回值得到的地址,就可以像普通指针一样操作了。还需要注意的是这个指针应该进行相应的强制类型转换。
一段建立并初始化共享内存的代码如下:

struct sharebuf * ptr;
int id = shmget(KEY_MEM, sizeof(struct sharebuf), IPC_CREAT);
buf.head = buf.tail = 0;
ptr = (struct sharebuf *)shmat(id, 0, 0);
ptr->tail = ptr->head = 0;


综合上文信号量和共享内存的操作方法,我们将所有相关的操作编写成share.h和share.c


//share.h
#define KEY_MEM ((key_t)103040914)
#define KEY_FULL ((key_t)203040914)
#define KEY_EMPTY ((key_t)303040914)
#define KEY_MUTEX ((key_t)403040914)

#define MAX_BUFFER_SIZE 10

struct sharebuf
{
    int buffer[MAX_BUFFER_SIZE];
    int head;
    int tail;
};

union semun
{
    int val;                  /* value for SETVAL */
        struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
        unsigned short *array;    /* array for GETALL, SETALL */
                                  /* Linux specific part: */
        struct seminfo *__buf;    /* buffer for IPC_INFO */
};

int create(int * id_mem, int * id_full, int * id_empty, int * id_mutex);
void init(int id_mem, int id_full, int id_empty, int id_mutex);
void wait(int id);
void release(int id);
void * getmem(int id);


//share.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "share.h"

int create(int * id_mem, int * id_full, int * id_empty, int * id_mutex)
{
    *id_mem = shmget(KEY_MEM, sizeof(struct sharebuf), IPC_CREAT);
    *id_full = semget(KEY_FULL, 1, IPC_CREAT|0660);
    *id_empty = semget(KEY_EMPTY, 1, IPC_CREAT|0660);
    *id_mutex = semget(KEY_MUTEX, 1, IPC_CREAT|0660);
    return (*id_mem != -1 && *id_full != -1 &&
        *id_empty != -1 && *id_mutex != -1);
}

void init(int id_mem, int id_full, int id_empty, int id_mutex)
{
    union semun un;
    struct sharebuf * ptr;
    un.val = MAX_BUFFER_SIZE;
    semctl(id_empty, 0, SETVAL, un);
    un.val = 0;
    semctl(id_full, 0, SETVAL, un);
    un.val = 1;
    semctl(id_mutex, 0, SETVAL, un);
    ptr = getmem(id);
    ptr->tail = ptr->head = 0;
}

void wait(int id)
{
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = -1;
    buf.sem_flg = SEM_UNDO;
    semop(id, &buf, 1);
}

void release(int id)
{
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = 1;
    buf.sem_flg = SEM_UNDO;
    semop(id, &buf, 1);
}

void * getmem(int id)
{
    return shmat(id_mem, 0, 0);
}


生产者的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "share.h"

int main(int argc, char ** args)
{
    int count = 0;
    int id_mem, id_full, id_empty, id_mutex;    
    struct sharebuf * ptr;

    create(&id_mem, &id_full, &id_empty, &id_mutex);
    init(id_mem, id_full, id_empty, id_mutex);
    ptr = (struct sharebuf *)getmem(id_mem);
    
    while (1)
    {
        wait(id_empty);
        wait(id_mutex);
        ptr->buffer[ptr->tail] = count++;
        ptr->tail = (ptr->tail+1)%MAX_BUFFER_SIZE;
        printf("producer:%d/n", count);
        release(id_mutex);
        release(id_full);
    }
    return 0;
}


消费者代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "share.h"

int main(int argc, char ** args)
{
    int n = 0;
    int id_mem, id_full, id_empty, id_mutex;    
    struct sharebuf * ptr;

    create(&id_mem, &id_full, &id_empty, &id_mutex);
    ptr = (struct sharebuf *)getmem(id_mem);
    
    while (1)
    {
        wait(id_full);
        wait(id_mutex);
        n = ptr->buffer[ptr->head];
        ptr->head = (ptr->head+1)%MAX_BUFFER_SIZE;
        printf("customer:%d/n", n);
        release(id_mutex);
        release(id_empty);
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux下的生产消费模型可以使用pthread库中的互斥锁和条件变量来实现同步。下面是一个简单生产消费模型的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int in = 0, out = 0; int count = 0; pthread_mutex_t mutex; pthread_cond_t not_full; pthread_cond_t not_empty; void *producer(void *arg); void *consumer(void *arg); int main() { pthread_t tid_producer, tid_consumer; // 初始化互斥锁和条件变量 pthread_mutex_init(&mutex, NULL); pthread_cond_init(&not_full, NULL); pthread_cond_init(&not_empty, NULL); // 创建生产者和消费者线程 pthread_create(&tid_producer, NULL, producer, NULL); pthread_create(&tid_consumer, NULL, consumer, NULL); // 等待线程结束 pthread_join(tid_producer, NULL); pthread_join(tid_consumer, NULL); // 销毁互斥锁和条件变量 pthread_mutex_destroy(&mutex); pthread_cond_destroy(&not_full); pthread_cond_destroy(&not_empty); return 0; } void *producer(void *arg) { while (1) { pthread_mutex_lock(&mutex); if (count == BUFFER_SIZE) { // 缓冲区已满,等待消费消费 pthread_cond_wait(&not_full, &mutex); } // 生产生产一个数据,并将其放入缓冲区 int item = rand() % 100; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; count++; printf("producer: produce item %d, buffer count = %d\n", item, count); // 通知消费者可以消费了 pthread_cond_signal(&not_empty); pthread_mutex_unlock(&mutex); } } void *consumer(void *arg) { while (1) { pthread_mutex_lock(&mutex); if (count == 0) { // 缓冲区为空,等待生产生产 pthread_cond_wait(&not_empty, &mutex); } // 消费消费一个数据,并从缓冲区中删除 int item = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; printf("consumer: consume item %d, buffer count = %d\n", item, count); // 通知生产者可以生产了 pthread_cond_signal(&not_full); pthread_mutex_unlock(&mutex); } } ``` 在上述代码中,生产者线程每次生产一个数据并将其放入缓冲区,如果缓冲区已满,则等待消费消费消费者线程每次从缓冲区中取出一个数据并将其消费,如果缓冲区为空,则等待生产生产。使用互斥锁保证在访问共享资源时不会出现竞争条件,使用条件变量实现生产者和消费者之间的同步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值