Linux 系统下的进程间通信 IPC 入门 「下」

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/IvPHnEsC6ZdIHaFL8Deazg

共享内存

我们在进程间传输比较大的数据块时,通常选用共享内存的方式。共享内存大小也是有限制的,系统范围内能申请到的最大共享内存数量是 4096 个,每个最大空间为 18014398509465599 kbytes,所有共享内存最多占用空间为 18014398509481980 kbytes,当然每个共享内存最小限制为 1 字节。

如果需要查看修改限制值,可以按顺序分别参考下面的几个内核文件:

/proc/sys/kernel/shmmni
/proc/sys/kernel/shmmax
/proc/sys/kernel/shmall

通过 shmget() 申请共享内存资源,参数 key 指定 IPC key,size 是分配的共享内存大小(创建时有效,必须为 PAGE_SIZE 的倍数大小),参数 shmflg 指定标志类似消息队列和信号量。

int shmid = shmget(key, PAGE_SIZE, IPC_CREAT | 0666);
if (shmid == -1) {
    printf("shmget %s", strerror(errno));
}

一般 PAGE_SIZE 默认 4096,如果你需要查看当前系统下的配置值,可以:

$ pagesize

通过共享内存传输数据,其实就是在进程同步的情况下读写指定的内存空间,一般的进程同步采用信号量。读写前,被指定的进程内存空间必须先和共享内存绑定,绑定通过函数 shmat(),解绑通过函数 shmdt()。

#include <sys/shm.h>
void *shmat(int shmid, const void *_Nullable shmaddr, int shmflg);
int shmdt(const void *shmaddr);

绑定和解绑无须在每次发送接收共享内存的数据时都执行,如果是用户自己分配内存空间再绑定会增加内存泄漏的安全风险。

所以最佳实践是,在发送最开始时向系统申请自动绑定并返回被绑定的进程内部地址空间即可,接收同理,但是接收端在进程退出前应该负责解绑操作。

如何向系统申请自动绑定?在调用 shmat() 时,参数 shmaddr 用于指定被绑定的进程内部地址空间的地址,设为 NULL 即可。

发送数据

static char *pshm = NULL;
if (!pshm) {
    ...

    // 向系统申请自动绑定进程内部地址空间
    // 并保存返回的地址
    pshm = (char*)shmat(shmid, 0, 0);
    if ((char*)-1 == pshm) {
        printf("shmat %s", strerror(errno));
        return; // 退出
    }
}

... // 请求信号量

// 将长度为 len 的数据 data 写入被绑定的进程内部地址空间
memcpy(pshm, data, len);

... // 释放信号量

上面这段代码通常会封装成一个发送函数,pshm 被声明为 static 的变量就为了不用每次进入函数都重新绑定进程内部地址空间。实际写入数据时,需要利用信号量同步。

接收数据

接收数据不需要手动调用接收函数,一般通过创建子线程,在子线程内部循环地读取被绑定的进程内部地址空间的数据即可,当然,读取同样需要利用信号量同步。

char *data = NULL;
...

// 向系统申请自动绑定进程内部地址空间
// 并保存返回的地址
data = (uint8_t*)shmat(shmid, 0, 0);
if ((uint8_t*)-1 == data) {
    printf("shmat %s", strerror(errno));
    return; // 退出
}

while (1) {
    ... // 请求信号量

    // 将被绑定的进程内部地址空间 data 的数据
    // 另存到大小为 size 的缓冲区 buf
    memcpy(buf, data, size);

    ... // 释放信号量
}

// 退出前解绑
int ret = shmdt(data);
if (-1 == ret) {
    printf("shmdt %s", strerror(errno));
}

查看当前 IPC 状态

Linux 系统提供了 ipcs 指令用于查看 IPC 资源的状态信息

$ ipcs -a

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x0f050002 0          user         666        0            0           
0x0e050002 1          user         666        0            0           

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 131072     user         600        40960      2          dest         
0x00000000 131074     user         600        40960      2          dest         
0x00000000 131075     user         600        16384      2          dest         
...        

------ Semaphore Arrays --------
key        semid      owner      perms      nsems     
0x09050002 0          user         666        2         
0x0c050002 1          user         666        2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值