基于Linux sharememory的一种多进程生产者消费者工作模式实现

该博客介绍了如何在Linux系统中实现多进程间的生产者消费者模式,通过RingBuffer和共享内存进行数据通信。文中详细讲解了server(生产者)和client(消费者)的工作原理,以及如何使用shm_open和mmap进行内存映射。同时,提到了使用信号量进行同步的注意事项,并探讨了这种实现方式相对于二值资源锁的优势。最后,区分了posix和sysv共享内存API的区别。
摘要由CSDN通过智能技术生成

程序原理:

此程序可以用来模拟异构多核的处理器之间的相互通信以及Linux系统下多进程之间的数据直接共享,原理如下图所示:

1.Server端(生产者端)

#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include "ringbuffer.h"

union semun
{
    int val; //信号量初始值
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;
};

int main()
{
    struct ringbuffer *rb;
    int shm_key = ftok(".",0x5a);
    //第二个参数(创建共享内存的大小)
    int shm_id = shmget(shm_key, 1024*1024 + sizeof(struct ringbuffer), IPC_CREAT|IPC_EXCL|0755);
    if(shm_id == -1)
    {
        perror("shmget.");
        exit(1);
    }
    printf("%s line %d, shm_id=%d ,shm_key=0x%x.\n", __func__, __LINE__, shm_id,shm_key);
    char *address = (char*)shmat(shm_id, NULL, 0);
    if((void*)address == (void*)-1)
    {
        perror("shmat.");
        shmctl(shm_id, IPC_RMID, 0);
        exit(1);
    }

    rb = (struct ringbuffer*)address;

    ringbuffer_init(rb, (void*)sizeof(struct ringbuffer), 1024);

    key_t sem_key = ftok(".", 0x6b);
    int sem_id = semget(sem_key, 2, IPC_CREAT|IPC_EXCL|0755);
    union semun info;
    info.val = 0;
    semctl(sem_id,0, SETALL, info);
    struct sembuf p ={0, -1, 0}, v = {1, 1,0};
    unsigned char w = 0;
    while(1)
    {
	if(ringbuffer_put(rb, &w, 1) == 1)
	{
	    w ++;
	    printf("server: %s line %d.r %d, w %d.\n", __func__, __LINE__, rb->read_index, rb->write_index);
	}
	semop(sem_id, &v, 1);
	semop(sem_id, &p, 1);
    }
    shmdt(address);
    shmctl(shm_id, IPC_RMID, 0);
    shmctl(sem_id, 0, IPC_RMID);
    return 0;
}

2.Client端(消费者端)

#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include "ringbuffer.h"

union semun
{
    int val; //信号量初始值
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;
};

 
int main()
{
    struct ringbuffer *rb;
    int shm_key = ftok(".",0x5a);
    int shm_id = shmget(shm_key, 0, 0);
    if(shm_id == -1)
    {
        perror("shmget.");
        exit(1);
    }
    printf("%s line %d, shm_id=%d ,shm_key=0x%x.\n", __func__, __LINE__, shm_id,shm_key);
    char *address = (char*)shmat(shm_id, NULL, 0);//NULL连接的地址由系统自动分配
    if((void*)address == (void*)-1)
    {
        perror("shmat.");
        exit(1);
    }

    rb = (struct ringbuffer *)address;

    printf("address = %p\n", address);
    rb = (struct ringbuffer*)address;
    //ringbuffer_init(rb, address + sizeof(struct ringbuffer), 1024);

    key_t sem_key = ftok(".",0x6b);
    int sem_id = semget(sem_key, 0, 0);
    struct sembuf p = {
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值