共享内存及在进程通信当中的运用

  共享内存是三个IPC机制中的一个,它是两个或多个进程进行通信的一种非常有效的方式。  共享内存的实现,主要是在内核中找一段内存作为共享内存,这个共享内存通过映射的方法可以被其他进程所共同使用。当一个进程改变了共享内存的内容的时候,其他进程也会感知到这块内存中的内容发生了改变。因为数据不需要在C/S端复制,然后再把数据写到每个进程的物理内存,消除了多次拷贝带来的性能和时间的损耗,所以这也是最快的一种IPC。

  共享内存的生命周期由内核决定,即由内核中申请共享内存,释放也是由内核执行的动作,其余进程和共享内存之间只是映射关系,即使进程被挂起或者kill掉,只要内核不发起释放内存的动作,他就是一直存在的,也是可以一直被访问的。

  共享内存并未提供同步机制,一种是多个进程对内存同一个地址写时存在问题,另一种是一个进程在写,同时另一个进程在读。想要达到多个进程对共享内存的同步访问,还需要信号量来进行控制。

  共享内存中运用到的函数

  1、shmget

  int shmget(key_t key, size_t size, int shmflg);

  [参数key]:由ftok生成的key标识,标识系统的唯一IPC资源。

  [参数size]:需要申请共享内存的大小。在操作系统中,申请内存的最小单位为页,一页是4k字节,为了避免内存碎片,我们一般申请的内存大小为页的整数倍。

  [参数shmflg]:如果要创建新的共享内存,需要使用IPC_CREAT,IPC_EXCL,如果是已经存在的,可以使用IPC_CREAT或直接传0。 通常是IPC_CREAT | IPC_EXCL | 0666

  [返回值]:成功时返回一个新建或已经存在的的共享内存标识符,取决于shmflg的参数。失败返回-1并设置错误码。

  用法:通过ftok函数可以生成唯一的key标识,唯一的key标志通过shmget函数生成size大小的共享内存,函数的返回值是shmID,一个唯一的key对应唯一的shmID。

             其他进程想要和生成的这段共享内存映射的时候就需要这个shmID,可以通过shmget(key,0,0)进行生成

  2、shmat ( ):挂接共享内存(attach)

  void *shmat(int shmid, const void *shmaddr, int shmflg);

  [参数shmid]:共享存储段的标识符。

  [参数*shmaddr]:shmaddr = 0,则存储段连接到由内核选择的第一个可以地址上(推荐使用)。

  [参数shmflg]:若指定了SHM_RDONLY位,则以只读方式连接此段,否则以读写方式连接此段。

  [返回值]:成功返回共享存储段的指针(虚拟地址),并且内核将使其与该共享存储段相关的shmid_ds结构中的shm_nattch计数器加1(类似于引用计数);出错返回-13、

  3、shmdt ( ):去关联共享内存(datach)

  int shmdt(const void *shmaddr);

  [参数*shmaddr]:连接以后返回的地址。

  [返回值]:成功返回0,并将shmid_ds结构体中的 shm_nattch计数器减1;出错返回-1

  4、shmctl ( ):销毁共享内存

  int shmctl(int shmid, int cmd, struct shmid_ds *buf);

  [参数shmid]:共享存储段标识符。

  [参数cmd]:指定的执行操作,设置为IPC_RMID时表示可以删除共享内存。

  [参数*buf]:设置为NULL即可。

  [返回值]:成功返回0,失败返回-1。

  linux中的共享内存管理指令(可视化共享内存的情况)

  1、显示所有的IPC设施

# ipcs -a

  2、显示所有的消息队列Message Queue

# ipcs -q

  3、显示所有的信号量

# ipcs -s

  4、显示所有的共享内存

# ipcs -m

  5、显示IPC设施的详细信息

# ipcs -q -i id  

  id 对应shmid、semid、msgid等。-q对应设施的类型(队列),查看信号量详细情况使用-s,查看共享内存使用-m。

  6、删除共享内存IPC

ipcrm -m| -q| -s shm_id
上一篇:HDFS写文件异常


下一篇:Linux中的消息队列、共享内存