Linux初学第十天<进程间通信三、共享内存>

一、共享内存的概念

       内核中有一块公共的内存空间,两个不相关的进程都可以使用公共内存。独立于任何进程空间的一块共享空间,我们普通的内存操作来操作共享内存。它们都存在于<sys/ipc.h>、<sys/shm.h>两个头文件中。

二、相关的API介绍

1. int shmget (key_t key,size_t size,int shmflg)

       创建/获取一个共享内存。

参数说明:
              1. key和昨天的消息队列中的key 是一样的,这里它是内存的索引,同样可以用ftok来转换键值;
              2. size 为共享内存的空间,以Mb 为单位来申请。在创建一段共享内存时,必须指定size 的大小,若共享内存的已存在,size应该为0
              3. flag 可以赋值 IPC_CREAT 来实现创建共享内存,若为0,即会以默认的方式来获取共享内存。
返回值: 成功返回共享内存的ID(shmid),失败返回 -1
用法:

key_t key;
shmget(key,1024*2,IPC_CREAT|0600);//创建一个 2M 的可读可写的共享内存

2. void *shmat (int shm_id,cont void *addr,int shmflg)

       把共享内存连接到当前进程。
参数说明:
              1. shm_id 是共享内存的ID,可以通过它找到想要的共享内存;
              2. *addr 指定共享内存连接到当前进程中的地址,通常为0,标识由系统来选择共享内存的地址。
              3. shmflg 标志位,通常为0,表示可读可写;
       这个函数就是把共享内存的某个地址连接到当前进程的空间,所以需要一个指针来表示这个内存地址。
用法:

char *shmaddr;
shmaddr=shmat(shmid,0,0);//使用默认方式来连接

3. int shmdt ( void *addr)

       断开共享内存的连接。
参数说明: *addr 需要断开的地址;
用法:

char *shmaddr;
shmaddr=shmat(shmid,0,0);//使用默认方式来连接
shmdt(shmaddr);

4. int shmctl ( int shm_id,int cmd,struct shmid_ds *buf)

       控制内存函数。
参数说明:
              1. shm_id 共享内存的ID号;
              2. cmd 控制命令,赋值IPC_RMID 表示移除共享内存;
              3. *buf 为指令执时的信息结构体,比如执行的时间就存放在这个结构体当中,通常为0NULL
返回值: 成功返回0,失败返回 -1
用法: 以移除命令为例

shmctl(shmid,IPC_RMID,NULL);

       熟悉了这些API之后,我们可以做个实验来深入学习一下编程时的具体用法。

三、小实验

        编写两个程序,一个负责往共享内存写入数据,暂且命名为:SHM_demo1.c,另一负责读取共享内容,命名为:SHM_semo2.c

编程思路

Created with Raphaël 2.2.0 开始 创建共享内存 映射(连接)到进程空间 数据交换 释放内存,移除内存 结束

SHM_demo1.c 代码

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

        shmid=shmget(key,1024*2,IPC_CREAT|0600);//创建共享内存
        if(shmid==-1){
                printf("Shm creat failuer!\n");
                exit(-1);
        }
        shmaddr=shmat(shmid,0,0);//连接到进空间
        printf("shmat OK!\n");
        strcpy(shmaddr,"This Send!\n");//直接往共享内存的地址写入数据
        sleep(10);
        shmdt(shmaddr);//断开连接,
        shmctl(shmid,IPC_RMID,NULL);//移除共享内存
        printf("shm over!\n");
        return 0;
}

        开始写入后,等待10秒钟,给足够的时间让另一个进程读取数据,然后断开连接后移除共享内存。

SHM_demo2.c 代码

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

      shmid=shmget(key,1024*2,0);//获取共享ID,不用创建了,因为上面那个程序已经创建
        if(shmid==-1){
                printf("Shm creat failuer!\n");
                exit(-1);
        }
        shmaddr=shmat(shmid,0,0); //连接到当前进程空间
        printf("shmat OK!\n");

        printf("shm data:%s\n",shmaddr);//直接读取显示
        return 0;
}

两个程序配合的运行结果

        SHM_demo1.c 编译为 write;SHM_demo2.c编译为read
在这里插入图片描述
如果读取第二次会怎么样呢?
在这里插入图片描述
可以看到,读取第二次,就显示共享内存创建错误了,因为我们在SHM_demo1.c 中移除了共享内存,SHM_demo2.c 必须在10秒以内读取,不然就会出现错误。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值