Linux进程间通信(二)——共享内存
目录
前言
一、什么是共享内存?
二、共享内存接口
1.shmget
2.shmat
3.使用共享内存
4.shmdt
5.shmctl
三、查看SYSTEM V资源
四、共享内存的优缺点
优点
缺点
总结
前言
在Linux进程间通信(一)中,讲解了Linux中的管道通信,本文将讲解Linux进程间通信的第二种方式——共享内存。
一、什么是共享内存?
我们知道进程间通信的一个特点就是先要让通信的两个进程看到同一块内存空间且这块空间不会在进程发生写操作时,出现写时拷贝,然后让一个进程向其中投放数据,另一方从其中拿取数据。对于管道通信来讲,我们类似于创建一个文件,而后向文件中进行数据的存取。在共享内存中,可以说是真正意义上的开辟了一块内存空间,来让进程通信的的两方使用。为了方便演示,我们这里使用两个独立的进程来进行通信演示。但在此之前我们需要先介绍一下相关的接口。
二、共享内存接口
①int shmget(key_t key , size_t size , int shmflg) //创建一段共享内存
②void * shmat(int shmid , const void* shmaddr , int shmflg)//将共享内存链接到地址空间
③int shmdt(const void* shmaddr) //将共享内存与地址空间去关联
④int shmctl(int shmid , int cmd , struct shmid_ds * buf) //控制共享内存
⑤key_t ftok(const char * pathname , int pro_id) //创建一个密钥值
1.shmget
接口说明:
int shmget(key_t key , size_t size , int shmflg)
key参数:
进程间通信的本质是让通信的进程间看到相同的内存空间,所以我们使用该接口在物理内存上开辟一块空间,供通信的进程使用,但是如何保证通信进程使用的是同一块空间呢?这就是shmget函数中key这一参数的作用,key是用来通信进程间的唯一凭证,拥有相同凭证的进程才可以进行进程间的通信,通常使用ftok函数来生成。
size参数:
表示共享内存的大小,建议大小为4KB的整数倍,该大小与文件系统最小数据块有关。
shmflg参数:
表示获取共享内存的权限标志,该标志通常由四位整数来表示,对于低三位,这三位数与创建文件时的文件权限分配原则相似,对于最高位有如下的定义。
IPC_CREAT:表示获取共享内存,若不存在则创建。
IPC_EXCL :表示共享内存已存在则出错返回,通常与IPC_CREAT一同使用
IPC_NOWAIT :表示阻塞等待资源时,直接错误返回。
函数返回值:
该函数执行成功返回一个整数值,指代共享内存编号,如果出错则返回-1。
我们使用一下相应的接口并查看一下创建好的共享内存
ipcs -m //查看内存中的共享内存
2.shmat
接口说明:
创建完共享内存之后,通信的进程间还不可以使用,因为进程只是创建的了共享内存却没有将创建的共享内存与要通信的进程相关连。
void * shmat(int shmid , const void* shmaddr , int shmflg)
shmid参数:
表示共享内存指代标志。
shmaddr参数:
表示要关联的共享内存地址,这里一般不需要我们进行设置,直接将该参数设置为NULL即可,我们使用系统默认分配的就可以完成相应的功能。
shmflg参数:
表示要如何关联共享内存,如果不对该值进行设置,则默认以读写方式关联,或者以SHM_RDONLY只读方式关联,还有一些关联方式很少使用,这里就不一一列举了。
函数返回值:
当函数运行正常时,返回一个地址指向共享内存空间第一个字节,如果失败则返回-1.
3.使用共享内存
在完成shmget、shmat之后的进程之间就可以相互通信了,这里我们使用一个简单的例子来进行演示,其中server程序向client程序发送“i am processA”,client程序接收该内容并进行打印。
4.shmdt
接口说明:
我们使用完成共享内存之后,不在进行通信的进程应该要与共享内存去关联,为后续的共享内存的删除作准备。
int shmdt(const void* shmaddr)
shmaddr参数:
将shmat返回值传入即可。
函数返回值:
成功返回0,失败返回-1。
5.shmctl
接口说明:
我们创建完成共享内存之后,还要有相应的接口来管理共享内存,如删除共享内存、获取共享内存的信息等操作。
int shmctl(int shmid , int cmd , struct shmid_ds * buf)
shmid参数:
想要操作的共享内存的标识。
cmd参数:
想要执行的操作。需要说明的是,一个共享内存不再被使用的时候需要进程将共享内存进行释放,如果不进行释放将会造成内存泄漏。
cmd操作表(部分) 命令 说明 IPC_STAT 获取共享内存的信息并,放入buf中 IPC_SET 将buf中的值设置进共享内存 IPC_RMID 删除共享内存 buf参数:
接收缓冲区,只有使用该接口获取或设置共享内存的信息时,才需要使用该参数,该参数是一个输入\输出型参数,如果不使用该参数设置为NULL即可。
函数返回值:
执行成功返回0,执行失败返回-1.
像共享内存中进行设置信息的的功能这里就不予以演示了,感兴趣的读者可以自行尝试创建一个shmid_ds的结构并对其字段进行填充设置进shmctl并将cmd参数设置为IPC_SET即可。
三、查看SYSTEM V资源
本文使用的共享内存是system V版本的,该版本中的IPC资源诸如消息队列、共享内存、信号量可以使用以下指令来查询:
ipcs -[选项] //查看ipc资源
ipcs -a //查看所有的ipc资源
ipcs -s //查看信号量资源
ipcs -m //查看共享内存资源
ipcs -q //查看消息队列资源
ipcrm -[选项] [shmid] //删除对应的ipc资源
四、共享内存的优缺点
-
优点
共享内存在单机条件、同级别的压力下是所有进程间通信手段中最快的一种方式,共享内存的读写操作不需要陷入内核,因而在使用时使用的系统调用更少。此外通信的进程间进行数据传输时在物理内存上进行数据交换,这也正是该通信手段较快的原因。
-
缺点
共享内存缺少使用共享内存的接口,与文件操作割裂,难以复用其它的接口,移植与管理不便。
总结
本文讲解了有关共享内存的创建、管理、使用实例,希望读者读完本文后可以回答以下几个问题:
- 共享内存开辟在哪里?
- 共享内存的效率如何?为什么?
- 共享内存中key的作用?