进程间通信(四)—共享内存

我会用几篇博客总结一下在Linux中进程之间通信的几种方法,我会把这个开头的摘要部分在这个系列的每篇博客中都打出来

进程之间通信的方式

  • 管道
  • 消息队列
  • 信号
  • 信号量
  • 共享存储区
  • 套接字(socket)

进程间通信(三)—信号量传送门:http://www.cnblogs.com/lenomirei/p/5649792.html

进程间通信(二)—消息队列传送门:http://www.cnblogs.com/lenomirei/p/5642575.html

进程间通信(一)—管道传送门:http://www.cnblogs.com/lenomirei/p/5636339.html

这篇主要记录的是共享存储区的相关操作,说是共享存储区,其实就是共享内存,进程拥有的能互相通信存储区也就有内存了吧

为什么用共享存储区进行通信?因为快!管道是文件,操作慢,消息队列创建操作都有消耗所以慢,共享内存是要创建好两个进程都可以直接对这块内存进行操作,互相都是可见的。

为什么用共享存储区编写程序?因为接口简单!操作绝对比消息队列简单好多。

  • 创建共享存储区

虽然感觉很简单的事情,但是还是要创建开辟一下,不然每个进程都用自己的地址空间映射到不同的物理地址,哪怕虚拟地址是一样的,也是各自独立的,互相不可见,声明了这个共享存储区之后,才可以往这个公共的区域映射(这样才有用不是么)。

  • 函数原型:int shmget(key_t key, size_t size, int shmflg);
  • 头文件:#include <sys/ipc.h> #include <sys/shm.h>
  • 参数解析
    • key参数通过ftok函数的返回值取得,或者传入IPC_PRIVATE由操作系统自动分配
    • size表示你要开辟多大的共享存储空间,PS:分配空间最终会变成分配物理空间,是通过分配整页的方式实现的,Linux系统下一页大小是4KB=4096B,小于4096B则分配一页,size传入4097则分配两页
    • shmflg有IPC_CREAT 和 IPC_EXCL

调用这个函数就可以开辟一个共享存储区了,可以通过ipcs -m查看当前共享存储区状态

第一个键值就是传入的key,shmid标识唯一共享内存段,拥有者权限字节就不多说了额,这个nattch是指当前有多少个进程连接到该共享存储区

nattch:只创建共享存储区是不够的,你需要把它和进程链接,才能让进程的地址空间中的一段地址映射到共享内存段上。

  • 共享存储区的连接

这就讲一下用什么函数链接共享存储区,需要注意的是,两个进程都需要链接才可以,创建共享存储区的进程不会自动连接,也需要调用链接函数

  • 函数原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
  • 头文件:#include <sys/types.h> #include <sys.shm.h>
  • 参数解析
    • shmid表示共享存储区的标识
    • 第二个参数表示共享存储区的开始地址,如果不是对内存十分了解建议交给操作系统去做,设置为0
    • shmflg可以设置当前进程的读写权限,SEM_RDONLY之类的,默认0为读写均可,测试程序我给了0

每有一个进程调用这个函数,就会使nattch增加1,返回值因为是个空类型的指针常常需要强制转换

  • 共享存储区的链接的断开

链接使用完之后就断开是个好习惯,而且对销毁共享存储空间也好

  • 函数原型:int shmdt(const void *shmaddr);
  • 头文件:#include <sys/types.h> #include <sys.shm.h>
  • 参数解析删除共享存储区
    • 就是要删除的共享存储区的起始地址,因为是空类型的指针,没必要转换,直接给来都能删除
  • 删除共享存储区

最后还是要用到shmctl函数来删除共享存储区

  • 函数原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 头文件:#include <sys/ipc.h> #include <sys/shm.h>
  • 参数解析
    • shmid表示共享存储区的标识
    • cmd给出IPC_RMID表示删除
    • 因为第二个参数设置为IPC_RMID表示删除,第三个参数没用了,第三个参数直接给NULL(0)

事已至此,基本操作就说完了,废话少说,show me the code

我的程序分为comm.h(公共头文件)  comm.c(封装基本函数) server.c(简易服务器端) 一共3个文件

功能主要实现了简单的字符串共享?父进程写入,子进程打印,就这么简单

结果图并看不出什么鬼

comm.h

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <string.h>
 4 #include <sys/ipc.h>
 5 #include <unistd.h>
 6 #include <sys/shm.h>
 7 #include <errno.h>
 8 #include <stdlib.h>
 9
10
11 #define _PATH_NAME_ "/tmp"
12 #define _PROJ_ID_ 0x6666
13
14
15
16 static int comm_create_ssm(int flags,size_t size);
17 int create_shm(size_t size);
18 int get_shm();
19 char *shm_at(int shm_id);
20 void destory_shm(int shm_id);
21 int shm_dt(char *addr);

comm.c

 1 #include "comm.h"
 2
 3
 4 static int comm_create_shm(int flags,size_t size)
 5 {
 6   key_t _key=ftok(_PATH_NAME_,_PROJ_ID_);
 7   if(_key<0)
 8   {
 9     printf("%d:%s",errno,strerror(errno));
10   }
11   int shm_id;
12   if((shm_id=shmget(_key,size,flags))<0)
13   {
14     printf("shmget error,%d:%s",errno,strerror(errno));
15   }
16   return shm_id;
17 }
18
19
20 int create_shm(size_t size)
21 {
22   int flags=IPC_CREAT |IPC_EXCL;
23   return comm_create_shm(flags,size);
24 }
25
26 int get_shm()
27 {
28   int flags=IPC_CREAT;
29   return comm_create_shm(flags,0);
30 }
31
32 char *shm_at(int shm_id)
33 {
34   return (char *)shmat(shm_id,NULL,0);
35 }
36 int shm_dt(char *addr)
37 {
38   return shmdt(addr);
39 }
40
41 void destory_shm(int shm_id)
42 {
43   shmctl(shm_id,IPC_RMID,0);
44 }

server.c

 1 #include "comm.h"
 2
 3
 4
 5 int main()
 6 {
 7   int pid=fork();
 8   if(pid>0)
 9   {
10     //father
11     int shm_id=create_shm(4096);
12     char *buf=shm_at(shm_id);
13     int i=0;
14     while(i<4096)
15     {
16       sleep(1);
17       buf[i]=‘A‘;
18       i++;
19       buf[i]=‘\0‘;
20     }
21   }
22   else
23   {
24     //child
25     int shm_id=get_shm();
26     char *buf=shm_at(shm_id);
27     while(1)
28     {
29       sleep(1);
30       printf("%s\n",buf);
31     }
32   }
33   return 0;
34 }
时间: 2024-10-19 19:34:47

进程间通信(四)—共享内存的相关文章

Linux进程间通信—使用共享内存

Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像

进程间通信(8) - 共享内存(posix)

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.共享内存介绍 前面所讲述的Linux下面的各种进程间通信方式,例如:pipe(管道),FIFO(命名管道),message queue(消息队列),它们的共同点都是通过内核来进行通信(假设posix消息队列也是在内核中实现的,因为posix标准没有规定它的具体实现方式).向pipe,fifo,message queue写入数据时,需要把数据从用户空间(用户进程)复制到

Linux进程IPC浅析[进程间通信SystemV共享内存]

Linux进程IPC浅析[进程间通信SystemV共享内存] 共享内存概念,概述 共享内存的相关函数 共享内存概念,概述: 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到自己的虚拟内存空间,所有用户空间的进程若要操作共享内存,都要将其映射到自己的虚拟内存空间中,通过映射的虚拟内存空间地址去操作共享内存,从而达到进程间的数据通信 共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容 本身不提供同

Linux环境进程间通信:共享内存

共享内存简介 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC.共享内存的方式有两种:mmap()系统调用和系统V共享内存. mmap()系统调用 mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存.普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作. 注:实际上,mmap()系统调用并不是完全为了用于共享内存而设计的.它本身提供了不同于一般对普

Linux进程间通信——使用共享内存

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

Linux进程间通信--mmap共享内存(一)

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入

Linux进程间通信--shmget()共享内存(二)

共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.这块共享虚拟内存的页面,出现在每一个共享该页面的进程的页表中.但是它不需要在所有进程的虚拟内存中都有相同的虚拟地址. 图 共享内存映射图 象所有的 System V IPC对象一样,对于共享内存对象的获取

深入理解进程间通信之共享内存

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.是针对其他通信机制运行效率较低而设计的.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共

进程间通信方式——共享内存

1.什么是共享内存? 共享内存就是允许两个或多个进程共享一定的存储区.就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改.因为数据不需要在客户机和服务器端之间复制,数据直接写到内存,不用若干次数据拷贝,所以这是最快的一种IPC. 注:共享内存没有任何的同步与互斥机制,所以要使用信号量来实现对共享内存的存取的同步. 共享内存特点和优势 当中共享内存的大致原理相信我们可以看明白了,就是让两个进程地址通过页表映

Linux系统编程——进程间通信:共享内存

概述 共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改. 共享内存的特点: 1)共享内存是进程间共享数据的一种最快的方法. 一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容. 2)使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥. 若一个进程正在向共享内存区写数据,则在它做