1、什么是共享内存ide
顾名思义,共享内存就是容许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种很是有效的方式。不一样进程之间共享的内存一般安排为同一段物理内存。进程能够将同一段共享内存链接到它们本身的地址空间中,全部进程均可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存同样。若是某个进程向共享内存写入数据,所作的改动将当即影响到能够访问同一段共享内存的任何其余进程。函数
特别提醒:测试
共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操做以前,并没有自动机制能够阻止第二个进程开始对它进行读取。因此咱们一般须要用其余的机制来同步对共享内存的访问,如信号量。spa
2、共享内存的使用,在Linux中提供了一组函数接口用于使用共享内存。指针
一、共享内存的建立函数orm
函数原型:int shmget(key_t key,size_t size,int shmflg);对象
参数:blog
(1)key:与信号量的semget函数同样,程序须要提供一个参数(非0整数),有效的为共享内存段名,返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1。继承
不相关的进程能够经过该函数的返回值访问同一共享内存,它表明程序可能要使用的某个资源,程序对全部共享内存的访问都是间接的,程序先经过调用shmget函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget函数的返回值),只有shmget函数才直接使用信号量键,全部其余的信号量函数使用由semget函数返回的信号量标识符。接口
(2)Size:以字节为单位指定须要共享的内存容量。
(3)Shmflg:权限标志,它的做用与open函数的mode参数同样,若是要想在key标识的共享内存不存在时,建立它的话,能够与IPC_CREAT作或操做。共享内存的权限标志与文件的读写权限同样,举例来讲,0644,它表示容许一个进程建立的共享内存被内存建立者所拥有的进程向共享内存读取和写入数据,同时其余用户建立的进程只能读取共享内存。
二、启动对该共享内存的访问,并把共享内存链接到当前进程的地址空间。
函数原型:void *shmat(int shm_id,const void *shm_addr,int shmflg)
参数;
(1)shm_id :由shmget函数返回的共享内存标识,
(2)shm_addr:指定共享内存链接到当前进程中的地址位置,一般为空,表示让系统选择共享内存的地址,
(3)shm_flg:标志位,一般为0。
调用成功返回指向共享内存第一个字节的指针,失败返回-1。
三、用于将共享内存从当前进程中分离。
函数原型:int shmdt(const void *shmaddr);
参数:为shmat函数返回的地址空间,调用成功返回0,失败时返回-1.
四、控制共享内存函数
函数原型:int shmctl(int shm_id,int command,struct shmid_ds *buf)
参数:
(1)shm_id:共享内存标识符
(2)Command:采起的操做:
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:若是进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
(3)buf:结构指针,指向共享内存模式和访问权限的结构。
shmid_ds结构以下:
测试代码:
shm.h
shm.c
test.c
共享内存mmap
一、特色:
(1)进程相关的
(2)与XSI共享内存同样,须要与同步原语一块儿使用
(3)只能是有共同祖先的进程才能使用
二、系统调用mmap()用于共享内存的方式:
(1)使用普通文件提供的内存映像:
适用于任何进程之间。此时,须要打开或建立一个文件,而后再调用mmap()
典型调用代码以下:
fd=open(name, flag, mode); if(fd<0) ...
ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0);
(2)使用特殊文件提供匿名内存映像:
适用于具备亲缘关系的进程之间:
适用于具备亲缘关系的进程之间。因为父子进程特殊的亲缘关系,在父进程中先调用mmap(),而后调用fork()。那么在调用fork()以后,子进程继承父进程匿名映射后的地址空间,一样也继承mmap()返回的地址,这样,父子进程就能够经过映射区域进行通讯了。通常来讲,子进程单独维护从父进程继承下来的一些变量。而mmap()返回的地址,却由父子进程共同维护。对于具备亲缘关系的进程实现共享内存最好的方式应该是采用匿名内存映射的方式。
函数原型:void *mmap(void *addr,size_t len,int prot,int flag,int fd,off_t offset)
参数:
一、addr:映射区的开始地址,设置为0时表示系统决定映射区的起始地址
二、len:映射区的长度,单位为字节
三、prot:指望的内存保护标志,取一下几个值:
PORT_EXEC:页内容能够被执行 PROT_READ:页内容可被读
PROT_WRITE:页内容可被写 PROT_NONE:页内容不可访问
四、fd:文件描述符。
五、offset:被映射对象内容的起点。
六、Flags(必需要有MAP_CHARED标志):指定映射对象的类型,映射选项是否能够和映射页共存。
MAP_SHARED:与其余全部映射这个对象的进程共享映射空间;
MAP_PRIVATE:创建一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。
MAP_FIXED:使用指定的映射起始地址。
测试代码:
mmap.c
运行结果: