共享内存

来源:互联网 发布:天使之城淘宝店不在了 编辑:程序博客网 时间:2024/06/06 08:57

linux下进程间通信的几种主要方式的简介:  

1、 管道(Pipe)

   管道分为有名管道(named pipe)和无名管道。管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许没有亲缘关系进程间的通信; 

 2、 信号(Signal)

    信号是⽐比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本⾝身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接⼜口,用 sigaction函数重新实现了signal函数);

3 、消息(Message)队列

   消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载 无格式字节流以及缓冲区大小受限等缺点。 
 4 、共享内存

   使得多个进程可以访问同一块内存空间,是最快的可⽤用IPC形式。是针对通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。  

5、 信号量(semaphore)

   主要作为进程间以及同一进程不同线程之间的同步手段。           

6、 套接口(Socket)

   更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字

今天我们来主要看看共享内存!


一、概念:
  
     共享内存顾名思义就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。

二、特点:

共享内存分为两种
1、二者是用同一种机制完成的,不同的是用户接口不同:
        一种是POSIX的共享内存,通过用户空间挂载的tmpfs文件系统实现的。(上层不会在意你是内核还是用户空间来实现的)
        二种是system V的共享内存是由内核本身的tmpfs实现的。(严格由操作系统内核提供接口和实现。)
2、posix的共享内存机制实际上在库过程中以及用户空间的其他部分被展示为完全的文件系统的调用过程,在调用完shm_open之后,需要调用mmap来将tmpfs的文件映射到地址空间,接着就可以操作这个文件了,需要注意的是,别的进程也可以操作这个文件,因此这个文件其实就是共享内存。
     反观system v的共享内存,内核直接实现了shmget/at系统调用,虽然最终也是靠tmpfs来实现的,但是接口设计上和posix完全不同,posix旨在提供所有系统都一致的接口,而system v只在于实现自己的逻辑,共享内存其实只是sysv中ipc的一部分,最终的管理数据结构也是ipc的而不是共享内存的。
其次,共享内存是所有进程间通信速度最快的,而且它的生命周期随内核。
三、代码实现:

先来介绍几个需要调用的函数
1.创建一个共享内存  shmget()
#include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key,size_t size,int shmflg>;key(非0整数):为共享内存段命名,shmget成功时返回一个与key相关的内存标识符shm_id(非负整数),失败时返回-1size:以字节为单位指定需要共享的内存容量shmflg:权限标志,与open函数的mode参数一样,创建共享内存时此参数位可写成 IPC_CREAT | 0666

2.关联共享内存(映射) shmat()
#include<sys/types.h>#include <sys/shm.h>void *shmat(int shm_id, const void *shm_addr, int shmflg);shm_id: 是由shmget 函数返回的共享内存标识。shm_addr:指定共享内存连接到当前进程的地址位置,通常为空,表示让系统来选择共享内存的地址。shm_flg:是一组标志位,通常为0。
 调用成功后返回一个指向共享内存第一个字节的指针,调用失败返回-1。
3.取关联(解除映射) shmdt()
#include <sys/types.h>#include <sys/shm.h>int shmdt(const void *shmaddr);shmaddr:是shmat函数返回的地址指针
调用成功返回0,失败返回-1.
4.销毁共享内存 shmctl()
#include <sys/ipc.h>#include <sys/shm.h>int shmctl(int shm_id, int command, struct shmid_ds *buf);shm_id:是shmget函数返回的共享内存标识符command: 控制共享内存要采取的操作,可以取以下三个值:IPC_STAT : 把shmid_ds结构体中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值IPC_SET : 如果进程有足够的权限,就把共享内存当前的关联值设置为shmid_ds结构体中给出的值IPC_RMID : 删除共享内存段buf : 是一个结构体指针,指向共享内存模式和访问权限的结构体shmid_ds结构体的成员至少包括:struct shmid_ds{   uid_t shm_perm.uid;   uid_t shm_perm.gid;   mode_t shm_perm.mode;
接下来看看具体代码:
1.shm.h

2.shm.c








原创粉丝点击