1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 多进程ipc之共享内存

多进程ipc之共享内存

时间:2019-01-26 11:39:51

相关推荐

多进程ipc之共享内存

进程间通讯(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;}

运行结果:

(1)因为共享内存使用的是同一块内存,因此使用时不需要任何操作即可读取到其他进程写入到共享内存的数据
(2)正因为使用同一块内存,也导致了在数据读取时不存在阻塞等待,就需要我们人为地去解决这个问题,一般而言常用地是与posix,system V等信号量一起使用(在本代码中因为未使用信号量,我加了个判断的防止在没写入数据的时候一直循环打印替代信号量)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。