进程间通讯(ipc)之共享内存:
(1)进程间通讯比较快速的一种,常与信号量一起操作
(2)本质是进程间使用同一块内存
(3)因为进程间使用的是同一块内存,因此在一个进程间改变了共享内存里的数据,其他进程中的同一块共享内存的数据也会随之被改变
这是关于ipc的一些操作,点击跳转
我们换个通俗点的说法:现在有小红和小绿,他们是合租室友;但是呢,他们租的房子里面只有一间浴室,然后约定浴室里面地洗发水一起买来用,为了防止别人来他们房子用他们的浴室(就当为了省买洗发水的钱和水费),然后他们就给浴室上了锁,只有他们两个有钥匙,如果有其他人还想来一起合租用浴室就需要他自己再去配一把钥匙,有钥匙的小红和小绿因为有钥匙于是他们就能一起使用浴室,并且里面的东西是共用的;小红和小绿就相当于进程,浴室就是共享内存
相关函数API:
//创建键值函数//函数头文件#include <sys/types.h>#include <sys/ipc.h>//函数原型key_t ftok(const char *pathname, int proj_id);//函数介绍:/********************************************************函数作用:用于创建一个键值,键值作用 :用于进程间通讯(ipc)时的一个标识符,不会因进程退出而消失形参:pathname:路径名-->通过哪一个路径来获得键值proj_id( project identifier):项目id:即我们指定给它一个8位(一个字节,最大256)的整数,同一路径下不能由两个相同的键值注:其实可以看成路径下的消息队名为给它的数返回值:成功:新生成且未被使用的键值失败:-1********************************************************///创建共享内存//函数头文件#include <sys/ipc.h>#include <sys/shm.h>//函数原型int shmget(key_t key, size_t size, int shmflg);//函数介绍:/********************************************************函数作用:用于创建一个共享内存形参:key:通过ftok函数创建成功返回的键值size:共享内存的大小字节数shmflg:IPC_CREAT:当共享内存不存在时就创建一个共享内存(当创建共享内存时需要位或上创建共享内存后它的操作权限)IPC_EXCL:当共享内存已经存在时就报错返回值:成功:共享内存的id号(标识符)失败:-1********************************************************/
测试代码:
/**创建共享内存*/#include <stdio.h>#include <sys/ipc.h>#include <sys/shm.h>#include <string.h>int main(){//产生键值key_t key = ftok(".",1);if(key == -1){perror("ftok failed");return -1;}//创建或打开共享内存int shmid = shmget(key,50,IPC_CREAT | 0600);if(shmid == -1){perror("shmget failed");return -1;}return 0;}
(1)创建共享内存给的权限可以为0666或0777,0600这些都行,一般在所在用户组成员或其他组要用到时才会有影响
(2)共享内存创建后需要删掉,否则将会一直占用系统资源
关于共享内存映射与解除映射及删除函数:
//映射共享内存及解除共享内存函数//函数头文件#include <sys/types.h>#include <sys/shm.h>//映射共享内存void *shmat(int shmid, const void *shmaddr, int shmflg);//解除共享内存映射int shmdt(const void *shmaddr);//函数介绍:/********************************************************函数作用:shmat:为共享内存映射出一块对应大小的内存shmdt:解除共享内存的映射形参:shmid:共享内存的id号,使用创建共享内存函数shmget获得shmaddr:在shmat中表示需要指定映射的起始地址(一般为NULL)在shmdt中表示需要解除映射的共享内存的起始地址shmflg:0:该共享内存设置为可读可写SHM_RDONLY:共享内存设置为只读返回值:成功:共享内存的id号(标识符)失败:-1********************************************************/
//共享内存操作函数//函数头文件#include <sys/ipc.h>#include <sys/shm.h>//函数原型int shmctl(int shmid, int cmd, struct shmid_ds *buf);//函数介绍:/********************************************************函数作用:用于获取共享内存的属性和设置属性以及删除共享内存形参:shmid:共享内存的id号,使用创建共享内存函数shmget获得cmd:IPC_STAT:获取属性到buf中,需要后面的buf不能为NULLIPC_SET:把共享内存中的属性设置为buf中的值IPC_RMID:删除共享内存返回值:成功:0失败:-1********************************************************/
测试代码:
(需要两个进程,测试两个进程的创建共享内存后,是否使用的是同一块内存)
写入端:
#include <stdio.h>#include <sys/ipc.h>#include <sys/shm.h>#include <string.h>int main(){//产生键值key_t key = ftok(".",1);if(key == -1){perror("ftok failed");return -1;}//创建或打开共享内存int shmid = shmget(key,50,IPC_CREAT | 0600);if(shmid == -1){perror("shmget failed");return -1;}//映射内存char *addr = shmat(shmid,NULL,0);if(addr == (void *)-1){perror("chmat failed");return -1;}while(1){//从标准输入缓冲缓冲区获取数据printf("请输入需要往共享内存发送的数据:");fgets(addr,50,stdin);//当输入quit时就退出if(!strcmp(addr,"quit\n"))break;}//解除映射shmdt(addr);//删除共享内存shmctl(shmid,IPC_RMID,NULL);return 0;}
读取端:
#include <stdio.h>#include <sys/ipc.h>#include <sys/shm.h>#include <string.h>int main(){//产生键值key_t key = ftok(".",1);if(key == -1){perror("ftok failed");return -1;}//创建或打开共享内存int shmid = shmget(key,50,IPC_CREAT | 0600);if(shmid == -1){perror("shmget failed");return -1;}//映射内存char *addr = shmat(shmid,NULL,0);if(addr == (void *)-1){perror("chmat failed");return -1;}while(1){//阻塞等待数据写入,因为本身不具有阻塞等待,需要自己解决if(strlen(addr)==0){continue;}else{//打印共享内存的数据printf("读取到的数据为:%s",addr);//当输入quit就退出循环if(!strcmp(addr,"quit\n"))break;//每次清空一下共享内存bzero(addr,50);}}//解除映射shmdt(addr);//删除共享内存shmctl(shmid,IPC_RMID,NULL);return 0;}