Linux进程间通信:共享内存

来源:互联网 发布:淘宝时尚潘多拉代购点 编辑:程序博客网 时间:2024/06/05 16:32

    之前提到了进程间通信的管道,消息队列,信号量,然后其中信号量是PV操作,操控的是一个共享资源。在我们提到的IPC模块中,消息队列针对的是数据单元的信息传送,管道不属于system V IPC的部分,所以按照一个操作系统的整体来说,他应该也有着一个关于字节流的消息传输,并且要比之前都要快,还要跟我们之前所说的信号量利用起来,所以就出现了共享内存的概念。

  什么是共享内存?

    共享内存是多个进程之间共享内存区域的一种进程间的通信方式,他是在多个进程之间对内存段进行映射的方式实现内存共享的,这是IPC最快捷的方式,因为共享内存的方式的通信没有中间过程,二管道,消息队列等方式则是需要将数据通过中间机制进行转换。

   共享内存方式直接将某段内存段进行映射,多个进程间的共享内存是统一快的物理空间,仅仅阿是地址不同而已,因此不需要进行复制,可以直接使用此段空间。

 下面我们就来了解Linux下的共享内存相关的函数:

    1.创建共享内存函数:      

#include<sys/ipc.h>#include<sys/shm.h>int shmget(key_t key,size_t size,int shmflg);

  第一个参数是关键字的值,然后,这个值将与内核中现有德1其他共享内存段的关键字值相比较,比较之后,依赖第3个参数,跟前面消息队列的一样。

     2.获取共享内存地址函数shmat()

       函数shmat()用来获取共享内存的地址,获取共享内存成功后,可以像使用通用内存一样对其进行读写操作,

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

    如果shmaddr参数值等于0,则内科将试着查找一个未映射的区域,用户可以指定一个地址,但通常改地址只用于访问所拥有的硬件,或者解决与其他应用程序的冲突。SHM_RND标志可以与标志参数进行OR操作,结果在置为标志参数。SHM_RDONLY标志参数进行OR操作,结果在置为标志参数,这样映射的共享内存端智能标记为只读方式。

    shmdt()用于删除一段共享内存,这个函数之中,成功完成了断开连接操作以后,相关的shmid_ds结构的shm_nattch成员的值将减去1。如果这个值减到0.则内核将真正删除这个共享内存。

4.共享内存控制函数shmctl()

#include<sys/ipc.h>#include<sys/shm.h>int shmctl(int shmid,int cmd,struct shmid_ds*buf);

    第二个参数为:IPC_SET,获取内存短的shmid_ds结构。并把它存储在buf参数所指定的地址中。设置内存段shmid_ds结构的ipc_pern成员的值,此命令是从buf参数中获得该值。

        IPC_RMID:标记某内存段,以被删除。并不是真正的把内存段从内存中删除,相反,它只是标记上该内存段,以备将来删除,最后一个断开,删除操作才会发生。


下面看看实际代码:

//shm.h#pragma once#include <stdlib.h>#include <stdio.h>#include <sys/shm.h>#include <sys/ipc.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#define _PATH_ "."#define _PROJECT_ 0x777#define _SHM_SIZE_ 4*1024int get_shm();void* at_shn();int delete_shm();int rm_shm();//shm.c#include "shm.h"int get_shm(){key_t key = ftok(_PATH_,_PROJECT_);if(key < 0){perror("ftok");return -1;}int flag =IPC_EXCL| IPC_CREAT |0666;int shm_id = shmget(key,_SHM_SIZE_,flag);if(shm_id < 0){printf("shmid error");}else{printf("shmid success");}return shm_id;}     void* at_shm(int shm_id){return shmat(shm_id,NULL,0);}int delete_shm(char *addr){return shmdt(addr);}int rm_shmctl(int shm_id){return shmctl(shm_id,IPC_RMID,NULL);}//shm_test.c#include "shm.h"int main(){int shm_id = get_shm();if(shm_id < 0){printf("HHH");}pid_t id = fork();if(id <0){printf("fork error\n");return 1;}else if(id == 0){char *buf = (char *)at_shm(shm_id);printf("child");int i = 0;while(i < 4095){buf[i] = 'A';++i;buf[i] = '\0';sleep(1);}buf[4095] = '\0';delete_shm(buf);}else{int i = 0;char *buf  = (char *)at_shm(shm_id);printf("father");while(i<4095){printf("%s\n",buf);++i;sleep(1);}delete_shm(buf);waitpid(id,NULL,0);rm_shmctl(shm_id);}return 0;}

运行结果:

wKioL1cXPpSRu_kZAAAhoVKHEKY607.png


总结:

 其实共享内存是在IPC进程间通信最快的一种方式,因为他是直接针对物理地址进行的操作,而且对于他的资源控制,我们需要配合信号量进行操作,来防止死锁的产生。

本文出自 “剩蛋君” 博客,请务必保留此出处http://memory73.blog.51cto.com/10530560/1765844

0 0