ipc通信三—共享内存

共享内存简介

共享内存是进程间通信一种方式,多个进程共享一段内存,“ 共享内存 ”。由于多个进程共享了同一段内存,这个段内存既是你的也是我的。也就是你往这个内存里面写入数据,实际上就相当于往我的内存里面写入数据。
比起其他 IPC 方式( pipe fifo message… )少拷贝操作,相对而言共享内存的效率高于其他的。

**共享内存的生存期:**随内核持续性

实现方式:
在内核中开辟一块共享内存,其他的进程通过 “ 映射 ” 方式,获取这个共享内存的引用(指针)
进程 P1 可以映射这段内存,同时其他的进程(如: P2…Pn )也可以映射这段内存, P1 往内存里面写入数据,实际就是往 P2…Pn 进程中写入数据,反之亦然

System V共享内存的API

创建或者是打开一个IPC 设施

FTOK(3)        Linux Programmer's Manual
NAME **ftok** - convert a pathname and a project identifier to a System V IPC key
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
/*
@描述
创建或者是打开一个IPC设施(msg/shm/sem)也就是一个System V IPC对象的"钥
匙"(KEY
@pathname:
一个在文件系统中路径名(这个路径必须要存在)
@proj_id:
int类型整数,一般用工程的代号。
@return:
成功生成一个唯一的System V的IPC设施的KEY
失败返回-1,同时errno被设置
*/

创建或打开System V 共享内存

shmget :通过 ftok 获取到的 IPC 设施的钥匙来创建或打开一个 System V 共享内存

SHMGET(2)    Linux Programmer's Manual      SHMGET(2)
NAME        shmget - allocates a System V shared memory segment
SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
/*
@描述:
shmget 用来在内核中创建或打开一个SystemV的共享内存
@key:
System V的IPC设施的KEY,一般由ftok返回
@size:
字节单位,指定共享内存区域的字节大小
@shmflg:
标志位:
1)创建:IPC_CREAT | 权限位
2)打开:0
@return:
成功返回共享内存区域的ID号,这个ID就唯一标识了这个共享内存
失败返回-1,同时errno被设置
*/

映射/解映射

映射:把内核或者设备的文件中的一段内存映射到进程的地址空间去,用进程的一个指针,去访问这段 内存。

SHMOP(2)
Linux Programmer's Manual
SHMOP(2)
NAME
shmat, shmdt - System V shared memory operations
SYNOPSIS
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
/*
@描述:
用来映射一段System V的共享内存
@shmid:
要映射的那个共享内存的id号,一般由shmget返回
其他操作
shmctl :对于共享内存的操作的。
信号量
@shmaddr:
指定要映射到的进程的哪个地址上去
一般为NULL,由系统自个决定。
@shmflg:
标志位:
SHM_RDONLY 只读
读写:0
@return:
成功返回映射成功的首地址
失败返回NULL,同时errno被设置。
*/
int shmdt(const void *shmaddr);
/*
@描述:
解除一段共享内存的映射
@shmaddr:
需要解除映射的内存首地址。
@return:
成功返回0,失败返回-1,同时errno被设置
*/

代码示例—可直接运行

#include <iostream>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>

// 通过宏定义来指定IPC设施的路径和工程ID
#define IPC_SHM_PATH ("./")
#define IPC_SHM_CODE (20240710)

// 共享内存区域的大小
#define IPC_SHM_SIZE (sizeof(int))

int main()
{
    // 第一步:获取钥匙
    key_t key = ftok(IPC_SHM_PATH, IPC_SHM_CODE);

    // 第二步:创建共享内存
    int shm_id = shmget(key, IPC_SHM_SIZE, IPC_CREAT | 0666);
    if (shm_id < 0) {
        perror("shmget");
        return 1;
    }

    // 第三步:映射共享内存到用户内存空间
    int *point = (int *)shmat(shm_id, NULL, 0);
    if (point == (int *)-1) {
        perror("shmat");
        return 1;
    }

    pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        return 1;
    }

    if (pid == 0) {
        // 子进程:读取共享内存
        while (true) {
            if (*point > 10) {
                std::cout << "Child process detected value > 10, exiting." << std::endl;
                break;
            }
            std::cout << "Child process read: " << *point << std::endl;
            sleep(1);  // 等待1秒以避免过快读取
        }
    } else {
        // 父进程:写入共享内存
        int value = 0;
        while (true) {
            *point = value++;
            if (*point > 10) {
                std::cout << "Parent process set value > 10, exiting." << std::endl;
                break;
            }
            sleep(1);  // 等待1秒以避免过快写入
        }
        wait(NULL);  // 等待子进程结束

        // 清理共享内存
        shmdt(point);
        shmctl(shm_id, IPC_RMID, NULL);  // 删除共享内存
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值