IPC - 共享内存

共享内存

在这里插入图片描述

  • 共享内存是进程间通信的最快方式。
  • 在物理内存上开辟一块内存空间,多个进程可以将同一块物理内存空间映射到自己的虚拟空间中,再通过自己的虚拟地址直接访问此空间,通过此方式实现数据的共享。
  • 不会随着进程的退出而释放,需要开发人员手动释放。

共享内存的操作流程:

  1. 创建共享内存空间 ---- 在物理内存上开辟空间。
  2. 进程将共享内存映射到自己的虚拟地址空间。
  3. 对共享内存进行操作。
  4. 不使用则解除进程虚拟内存和共享内存的联系。
  5. 释放共享内存。

查看共享内存

在这里插入图片描述

删除共享内存

ipcrm -m <shmid>

示例

write.cpp

/*
 * write a random number between 0 and 999 to the shm
*/
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <error.h>
#include <sys/sem.h>

using namespace std;

int main()
{
    int shm_id;
    int write_sem_id;
    int read_sem_id;
    int *share = nullptr;
    int num;
    int key = 0x123456;
    int write_key = 0x111;
    int read_key = 0x222;

    srand(time(nullptr)); // 初始化随机数的发生器

    // 创建并打开信号量
    write_sem_id = semget(write_key, 1, IPC_CREAT | 0666);
    read_sem_id = semget(read_key, 1, IPC_CREAT | 0666);

    // 设置信号量初始值为0
    semctl(write_sem_id, 0, SETVAL, 0);
    semctl(read_sem_id, 0, SETVAL, 0);

    // 创建共享内存 需要指定读写权限
    cout << "page size: " << getpagesize() << endl;
    shm_id = shmget (key, getpagesize(), IPC_CREAT | 0666);
    if(shm_id == -1)
    {
        perror("shmget error!");
        return -1;
    }

    // 添加对共享内存的映射 attch
    share = (int *)shmat(shm_id, nullptr, 0);
    int cnt = 5;
    struct sembuf v = {0, 1, SEM_UNDO};
    struct sembuf p = {0, -1, SEM_UNDO};
    while(cnt--)
    {
        num = random() % 1000;

        *share = num;
        printf("write a random number %d\n", num);

        // V(signal())生产者完成生产 
        semop(write_sem_id, &v, 1);

        // P(wait())等待消费者消费
        cout << "等待消费者完成消费" << endl;
        auto ret = semop(read_sem_id, &p, 1);
        if(ret != 0)
        {
            perror("semop read_sem_id error!");
        }
        cout << "消费者已完成消费" << endl;
    }

    // 删除对共享内存的映射 detach
    if(0 != shmdt(share))
    {
        cout << "detach share mem fail!" << endl;
    }
    return 0;
}

read.cpp

/*
 * read from the shm every 2 second
*/
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <error.h>
#include <sys/sem.h>

using namespace std;

int main()
{
    int shm_id;
    int *share;
    int key = 0x123456;

    int write_key = 0x111;
    int read_key = 0x222;
    int write_sem_id;
    int read_sem_id;

    // 创建并打开信号量
    write_sem_id = semget(write_key, 1, IPC_CREAT | 0666);
    read_sem_id = semget(read_key, 1, IPC_CREAT | 0666);

    // 设置信号量初始值为0
    semctl(write_sem_id, 0, SETVAL, 0);
    semctl(read_sem_id, 0, SETVAL, 0);

    shm_id = shmget (key, getpagesize(), IPC_CREAT | 0666);
    if(shm_id == -1)
    {
        perror("shmget()");
        return -1;
    }
    share = (int *)shmat(shm_id, 0, 0);

    int cnt = 5;
    struct sembuf sops;
    while(cnt--)
    {
        // P(wait())等待生产者完成生产
        cout << "等待生产者完成生产" << endl;
        sops.sem_num = 0;
        sops.sem_op = -1; // -1
        semop(write_sem_id, &sops, 1);
        cout << "生产者已完成生产" << endl;

        printf("%d\n", *share);

        // V(signal())消费者完成消费 
        sops.sem_num = 0;
        sops.sem_op = 1; // +1
        semop(read_sem_id, &sops, 1);

        sleep(2);
    }

    // 删除对共享内存的映射 detach
    if(0 != shmdt(share))
    {
        cout << "detach share mem fail!" << endl;
    }

    // 删除共享内存
    if(0 != shmctl(shm_id, IPC_RMID, nullptr))
    {
        perror("shmctl RMID fail!");
    }

    // 删除信号量
    if(0 != semctl(write_sem_id, 0, IPC_RMID))
    {
        perror("semctl rm write_sem_id fail!");
    }

    if(0 != semctl(read_sem_id, 0, IPC_RMID))
    {
        perror("semctl rm read_sem_id fail!");
    }
    return 0;
}

运行结果:
在这里插入图片描述
源码获取

参考

共享内存与内存映射(mmap)
IPC–共享内存操作详解
IPC之共享内存

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值