14-4-进程间通信-共享内存

文章详细介绍了Linux系统中共享内存的概念、应用场景、使用步骤以及相关API,包括shmget、shmat、shmdt和shmctl等,并提供了编程实现共享内存的示例代码,讨论了实际应用中可能的数据紊乱问题,暗示后续会通过信号来解决此类问题。
摘要由CSDN通过智能技术生成

之前学习了无名管道,命名管道,消息队列。

还剩下:共享内存,信号,信号量。

本章讨论的是共享内存。

一、共享内存的应用场景

A进程有自己的存储空间;

B进程也有自己的存储空间;

A进程和B进程不能进行数据交流;

但是在系统的内存中有1块公共内存;

此时,A进程和B进程依赖该公共内存可实现数据交流;

二、使用共享内存的思路

1.创建/打开 共享内存

2.映射

3.数据交换

4.释放共享内存

三、相关API

注意:共享内存的大小必须以MB对齐

https://editor.csdn.net/md/?articleId=129099839

1.创建1个共享内存

作用:创建一个共享内存 

参数:

        key:为共享内存的名字,一般是ftok的返回值。

        size:共享内存的大小,以page为单位,大小为4096的整数倍。

        shmflg:权限标志,常用两个IPC_CREAT和IPC_EXCL,一般后面还加一个权限,相当于文件的权限。

                                IPC_CREAT:创建一个共享内存返回,已存在打开返回

                                IPC_EXCL:配合着IPC_CREAT使用,共享内存已存在出错返回。

                                使用:IPC_CREAT | IPC_EXCL | 0666

返回值:

        成功返回一个非负整数,即共享内存的标识码,失败返回-1。

        为什么已经有一个key来标识共享内存,还需要一个返回值来标识共享内存?因为key是内核级别的,供内核标识,shmget返回值是用户级别的,供用户使用的。

 2.映射

作用:使创建的共享内存与调用该函数进程的进程地址空间参数关联。

参数:

        shmid:共享内存的标识,shmget的返回值。

        shmaddr:指定进程地址空间连接的地址。如果设置为null,默认让系统定要关联的地址。

        shmflg: 权限,常见有两个SHM_RDONLY(只读)和SHM_REMAP(重新映射一个进程地址空间没这样shmaddr不能为空)。设为0,系统默认。

 返回值:

        返回映射到进程地址空间共享区的开始地址。
————————————————
版权声明:本文为CSDN博主「两片空白」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_57023347/article/details/120307395

3.删除映射关系,释放地址空间

 作用:删除共享内存与进程地址空间的映射关系,将页表映射关系删除,释放进程地址空间。

参数:

        shmaddr:共享内存映射到进程地址空间的地址。shmat返回值。

返回值:

        成功返回0,失败返回-1

 4.控制共享内存

作用:用于控制共享内存

参数:        shmid:共享内存的标识

                   cmd:以什么方式来控制共享内存。IPC_RMID是释放共享内存

                   buf:指向一个共享内存的数据结构 。struct shmid_ds

返回值:成功返回0,失败返回-1。
————————————————
版权声明:本文为CSDN博主「两片空白」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_57023347/article/details/120307395

 5.shell指令查看共享内存

ipcs -m

 

四、编程实现共享内存

1.步骤

(1)生成键值;

(2)shmget();//创建共享内存,共享内存的大小是以MB为对齐单位的

(3)shmat();//映射

(4)在共享内存里做数据处理;比如进程A向共享内存写数据,过5秒进程B从共享内存读数据;

(5)shmdt();//卸载,,删除 映射关系

(6)shnctl();//关闭共享内存

2..代码实现

功能:进程A创建共享内存,映射,向共享内存里写入数据,几秒后删除映射关系,关闭共享内存;

进程B打开共享内存,从共享内存读取数据,关闭映射关系;

A.c

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
        int shmid;
        char *shmaddr;
        key_t key;
        key = ftok(".",1);

        shmid = shmget(key,1024*4,IPC_CREAT|0666);
        if(shmid == -1)
        {
                printf("shget failed\n");
                exit(-1);
        }

        shmaddr = shmat(shmid,0,0);
        printf("shmat ok\n");

        strcpy(shmaddr,"12345");
        sleep(3);
        shmdt(shmaddr);
        shmctl(shmid,IPC_RMID,0);
        printf("quit\n");

        return 0;
}

B.c

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
        int shmid;
        char *shmaddr;
        key_t key;
        key = ftok(".",1);

        shmid = shmget(key,1024*4,0);

        if(shmid == -1)
        {
                printf("shget failed\n");
                exit(-1);
        }

        shmaddr = shmat(shmid,0,0);
        printf("shmat ok\n");
        printf("data:%s\n",shmaddr);

        shmdt(shmaddr);
        printf("quit\n");

        return 0;
}
~   

运行结果:

 

 五,如何利用shell指令删除共享内存?

ipcrm -m xxxxxx(xxxxxx指共享内存的shmid)

六、实际应用中可能遇到的问题

如果有两个进程,进程A向共享内存写入数据后,进程B才从共享内存 读数据。那么不会出问题;

但是,如果进程A和进程B同时向共享内存写入数据,则会导致共享内存中的数据紊乱。

后面讲解“信号”时,会提出解决方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值