如果您无法下载资料,请参考说明:
1、部分资料下载需要金币,请确保您的账户上有足够的金币
2、已购买过的文档,再次下载不重复扣费
3、资料包下载后请先用软件解压,在使用对应软件打开
第六章共享内存共享内存是最快的IPC形式。一旦这样的内存区域映射到共享它的进程的地址空间,这些进程间数据的传递就不再涉及内核(即进程不是通过执行任何进入内核的系统调用来传递彼此数据的)。然而,往共享内存存放信息或者从中取走信息的进程间通常需要某种形式的同步,这用到我们前面提到的各种形式的同步:互斥锁、条件变量、读写锁、记录锁、信号量。客户服务器共享内存区客户地址空间服务器地址空间进程内核输入输入文件文件图6.1使用共享内存从服务器拷贝文件数据到客户上图是使用共享内存从服务器拷贝文件数据到客户的一个例子。图中数据只拷贝两次:一次从输入文件到共享内存,另一次从共享内存到输出文件。从图中的两个虚框可以看出,共享内存对象同时出现在客户进程和服务器进程的地址空间中。通常,有两种共享内存接口,一种是Posix接口,一种是SystemV接口。6.1几种共享内存机制6.1.1mmap有名/匿名内存映射mmap函数把一个文件或者一个Posix共享内存对象映射到调用进程的地址空间。使用mmap有三个目的:1、使用普通文件以提供内存映射:mmap函数隐含着一个内存映射文件。我们可以open一个文件,并调用mmap把它映射到内存,我们就不再使用read、write和lseek来访问该文件;相反,我们只是存取已由mmap映射到该文件的内存位置。把显示的文件I/O操作变换成存取内存单元往往能够简化我们的程序,并改善性能。1、在无亲缘关系的进程间的提供共享内存区域。当设置MAP_SHARED标志时,所映射文件的实际内容成了被共享的内存区的初始内容,而且这些进程对该共享内存区所作的任何变动都拷贝回所映射的文件。3、提供匿名内存映射。 4BSD提供匿名内存映射,它彻底避免了文件的创建和打开。其办法是把mmap的flags参数指定成MAP_SHARED|MAP_ANON,把fd参数指定成-1,offset参数被忽略。这样的内存区初始化成0。 SVR4提供/dev/zero设备文件,我们open它之后可在mmap调用中使用得到的描述字。从该设备读时返回的字节全部为0,写往该设备的任何字节则被丢弃。因而如果设置共享内存的目的是为了穿越某个后续的fork在父子进程间共享它,那么通过使用匿名内存映射可以简化其步骤,这样就不需要创建一个待映射的普通文件,这里或者涉及MAP_ANON这个新标志,或者涉及/dev/zero设备文件的映射。6.1.2Posix共享内存Posix共享内存建立在mmap函数之上。首先指定待打开共享内存的PosixIPC名字,调用shm_open,取得一个描述符后使用mmap把它映射到内存。其结果类似于内存映射文件,不过共享内存区对象不必作为一个文件来实现。因为共享内存区对象是由描述符来表示的,因此它们的大小使用ftruncate设置,有关某个已存在对象的信息由fstat返回。Posix提供了无亲缘关系进程间共享内存区的两种方法:1)存映射文件:由open函数打开,由mmap函数把得到的描述符映射到当前进程地址空间的一个文件。内存映射文件可以在有亲缘或者无亲缘关系的进程间共享。2)共享内存对象:由shm_open打开一个Posix.1IPC名字,所返回的描述符由mmap函数映射到当前进程的地址空间。posix内存映射文件posix内存映射区对象Fd=open(pathname,⋯);Fd=shmopen(name,⋯);Ptr=mmap(...,fd,⋯);Ptr=mmap(...,fd,⋯);Posix内存区对象图6.2posix内存区对象Posix共享内存涉及两个步骤:1、指定一个名字参数调用shm_open,以创建一个新的共享内存对象或者打开一个已存在的共享内存对象。2、调用mmap把这个共享内存区映射到调用进程的空间。Posix共享内存常用的库函数有:#include<sys/mman.h>intshm_open(constchar*name,intoflag,mode_tmode);intshm_unlink(constchar*name);返回:成功时为0,出错时为-1shm_open,以创建一个新的共享内存对象或者打开一个已存在的共享内存对象。注意:oflag参数必须含有O_RDONLY或者O_RDWR标志,还可以指定其他标志,O_CREAT、O_EXCL、O_TRUNC,如果随O_RDWR指定O_TRUNC标志,而且所需的共享内存对象已经存在,那么它将被截短成0长度。shm_open的返回值是一个整数描述字,它随后用作mmap的第五个参数