共享内存 消费生产者-线程

使用线程的属性来实现消费者生产者


关于线程的属性, 需要的就是进程间内能够使用的shared属性, 也就是线程的共享.

互斥量属性的数据类型是 pthread_mutexattr_t. 下面两个函数分别用于互斥量属性的初始化与回收。

int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
// 成功, 返回 0; 失败返回 -1并将错误存放在 errno中
1. /* 获取互斥量属性对象在进程间共享与否的标志 */  
2. int pthread_mutexattr_getpshared (const pthread_mutexattr_t *restrict __attr, int *restrict pshared);  
1. /* 设置互斥量属性对象,标识在进程间共享与否 */  
2. int pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared);  

pshared的值

  • PTHREAD_PROCESS_PRIVATE: 这种是默认的情况,表示互斥量只能在本进程内部使
  • PTHREAD_PROCESS_SHARED:表示互斥量可以在不同进程间使用。

首先要初始化一个共享内存, 并且存入数据

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <pthread.h>

const int addr = 0x8888;

struct Produce_Consume
{
    int food;
    pthread_mutex_t mutex;
};

int main(int argc, char *argv[])
{
    int id;
    // 创建一个共享空间
    if(argv[1][0] == 'i')
        id = shmget(addr, sizeof(Produce_Consume), IPC_CREAT | IPC_EXCL | 0664);
    else 
        id = shmget(addr, 0, 0);

    // 设置一个线程属性
    pthread_mutexattr_t mutexattr;
    // 初始化属性
    pthread_mutexattr_init(&mutexattr);
    // 将线程属性设置为设置为在不同进程间进行同步
    pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);

    //  连接到共享内存
    struct Produce_Consume *pro_con = (struct Produce_Consume *)shmat(id, NULL, 0);

    // 先初始化生产的数量
    pro_con->food = 2;
    // 初始化结构体中的互斥锁属性
    pthread_mutex_init(&pro_con->mutex, &mutexattr);
    // 删除不用的属性了
    pthread_mutexattr_destroy(&mutexattr);

    // 将内存进行映射
    shmdt((void *)pro_con);

    // 删除共享内存
    if(argv[1][0] == 'd')
        shmctl(id, IPC_RMID, NULL);

    exit(EXIT_SUCCESS);
}

在图片中, 可以看到 IPCS 指令打印了共享信息, 0x8888的地址申请成功了(忽略其他没有回收的内存…)

这里写图片描述

建立其他进程访问共享空间

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <pthread.h>

struct Produce_Consume
{
    int food;
    pthread_mutex_t mutex;
} * pro_con;

const int addr = 0x8888;

// 生产者
void *Pro(void *)
{
    while (1)
    {
        pthread_mutex_lock(&pro_con->mutex);
        if(pro_con->food < 5)
            pro_con->food++;
        printf("Produce food %d\n", pro_con->food);
        pthread_mutex_unlock(&pro_con->mutex);
        usleep(1000 * 500);
    }

    return ((void *)0);
}

// 消费者
void *Con(void *)
{
    while (1)
    {
        pthread_mutex_lock(&pro_con->mutex);
        if(pro_con->food > 0)
            pro_con->food--;
        printf("Consume food %d\n", pro_con->food);
        pthread_mutex_unlock(&pro_con->mutex);
        usleep(1000 * 500);
    }
    return ((void *)0);
}

int main(int argc, char *argv[])
{
    int id = shmget(addr, 0, 0);
    // 获取共享内存数据
    pro_con = (struct Produce_Consume *)shmat(id, NULL, 0);

    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, Pro, NULL);
    pthread_create(&thread2, NULL, Con, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    exit(EXIT_SUCCESS);
}

这里写图片描述

这样就实现了线程在不同进程间的共享了. 明白了基本函数, 理解起来也就不难了, 我就是将复杂的都省去了, 错误判断都没写, 也变代码简洁, 容易理解, 希望做的朋友自己还是加上错误的处理, 增强代码健壮性.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值