版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Linux 共享内存实例及文件映射编程及实现原理 .txt 如果我能够看到自己的影子,我想它一 定很忧伤,因为我把快乐都留在了前面。容易伤害别人和自己的人,总是对距离的边缘模糊 不清的人。目录一 IPC 共享内存和文件映射的区别1二共享内存实现流程总结 1三存储映射 I/O 包含实现原理说明 2文件映射 API 补充 4四IPC 共享存储包含实现原理说明6五共享内存实现根本原理10六IPC 共享内存实现机制11七文件映射的实现机制13一IPC 共享内存和文件映射的区别1. 文件映射的页框是磁盘文件高速缓存中的页框, 内核线程 pdflush 会将页框中的内容 回写进磁盘, 如果是私有映射类型,
2、 将会进行写时复制。 而 IPC 共享内存映射的是一种特殊 文件系统中的文件高速缓存,它没有相应的磁盘映像。2. IPC 共享内存只存在于内存中,系统重新启动,数据将会丧失。而文件共享映射会将 数据写回磁盘。3. IPC 共享内存的大小是在创立的时候指定,而且大小不能改变,而文件在创立时大小 为 0,此时还不能建立映射, 文件的大小会间接的决定映射区的大小。 例如文件的大小是 123, 而要求映射的区域大小是 4096*2 ,但实际只会分配 4096 的映射空间, 此时引用 4096 以后的 线性空间将引起缺页异常。4. 当第一次读取共享内存时 IPC 共享内存对象将分配一个新的页框, 而文件
3、映射分配新 页框的同时会将磁盘中的数据写入新页框。5. IPC 共享内存不需要写回磁盘操作, 完全是为共享内存而设计, 所以使用效率会更高。6. IPC 共享内存对象必须调用 shmctl() 显示的撤销, 否那么会一直保存着, 使用 key 或者 id 号定位一个共享内存对象, key 和 id 号的对应关系并不是固定的。例如,第一次使用 key 建立一个共享内存对象为 shm1 对应的 id 为 id1 ,之后系统重新启动,然后再使用 key 建立 一个共享内存对象 shm2,对应的id是id2 ,此时id2和id1是不同的。而文件映射使用相同 的路径将会定位相同的磁盘文件。总结: IPC
4、 共享内存和文件映射的实现机制是一样的,文件映射的目的是加快对文件的 读写速度,而 IPC 共享内存就是为了共享内存而设计的,所以效率会高一些。 二共享内存实现流程总结1. 建立一个线性区对象 struct vm_area_struct 并参加进程的内存描述符 current->mm 中。函数mmap()和shmat()就是用于建立并注册线性区对象, 这个对象中的struct file *vm_file 指向映射文件的文件对象, vm_page_prot 是线性区中页框的访问许可权。 但此时并未修改进 程的页表,而是注册相应的缺页异常回调函数,注册在对象的vm_ops。2. 当进程第一次
5、访问共享内存区时, 由于相应的页表还未填写, 将产生缺页异常, 并根 据线性地址找到对应的线性区对象,然后调用前边注册过的缺页异常回调函数,并根据vm_file 文件对象和 vm_page_prot 的信息来填写相应的页表项, 最后重新执行产生缺页异常 的代码。说明:文件映射和 IPC 共享内存映射的物理页框都是磁盘文件的页高速缓存中的,IPC共享内存使用一种特殊文件系统,这个文件系统并没有对应的磁盘映像,只是复用了文件系 统的框架。更详细的内容参见后边的五,六,七节。F面3, 4节是?UNIX环境高级编程?对文件映射和IPC共享内存的讲解,已经说明的很详细了, 我在它的根底上附加了一些内核实
6、现原理的说明, 实现原理说明局部放在括号内。 三存储映射 I/O 包含实现原理说明存储映射 I/O 使一个磁盘文件与存储空间中的一个缓存相映射。 于是当从缓存中取数据, 就相当于读文件中的相应字节。 与其类似, 将数据存入缓存, 那么相应字节就自动地写入文件。 这样,就可以在不使用 read 和 write 的情况下执行 I/O 。为了使用这种功能,应首先告诉内核将一个给定的文件映射到一个存储区域中。这是由mmap函数实现的。#include <sys/types.h>#include <sys/mman.h>void * mmap(void addr, size_t
7、len, int prot, int flag, int fd, off_t off) ; 返回:假设成功那么为映射区的起始地址,假设出错那么为- 1addr 参数用于指定映射存储区的起始地址。通常将其设置为 0,这表示由系统选择该映 射区的起始地址。此函数的返回地址是:该映射区的起始地址。fd 指定要被映射文件的描述符 fd 用于定位是哪个磁盘文件的页高速缓存 。在映射该文件到一个地址空间之前,先要 翻开该文件。 len 是映射的字节数。 off 是要映射字节在文件中的起始位移量 下面将说明对 off 值有某些限制 。在说明其余参数之前,先看一下存储映射文件的根本情况。图12 - 12 显示
8、了一个存储映射文件。在此图中,“起始地址是 mmap勺返回值。在图中,映射存储区位于堆和栈之间:这属于实 现细节,各种实现之间可能不同。prot 参数说明映射存储区的保护要求。见表12 - 8 。对于映射存储区所指定的保护要求与文件的open 方法匹配。 例如, 假设该文件是只读打开的,那么对映射存储区就不能指定PRO匸WRITE对存储映射区的保护是通过设置页表项的保护标志来实现的,如果页表项的 read/write 标志位为 0,说明页是只读的,如果进程试 图修改页的内容,将产生段错误,这些保护方案都是由CPU硬件控制的flag 参数影响映射存储区的多种属性:? MAP_FIXED返回值必须
9、等于 addr。因为这不利于可移植性,所以不鼓励使用此标志。 如果未指定此标志,而且 addr 非 0,那么内核只把 addr 视为何处设置映射区的一种建议。通 过将 addr 指定为 0 可获得最大可移植性。? MAP_SHARE这一标志说明了本进程对映射区所进行的存储操作的配置。此标志指定存储操作修改映射文件也就是, 存储操作相当于对该文件 write 。这里映射的页是包含在文 件的页高速缓存中,用户态进程在读写磁盘的时候,内核先在页高速缓存中增加一个新页, 将所请求的磁盘块写入新页,用户态进程从页高速缓存中取出数据。如果要写入数据,也是 要添加一个页将磁盘中的数据写入该页,然后再将数据写
10、入该页,内核会在一定的时机对磁 盘进行更新。 以上的页高速缓存是组织在 inode 的 i_mmaping 对象中,对于一个磁盘文件唯一对应 一个磁盘 inode ,每个磁盘 inode 也唯一对应一个内核 inode ,也就是, 每个磁盘文件只有一 个页高速缓存, 如果两个进程映射的是同一个文件的页高数缓存, 那么它们共享相同的物理页? MAP_PRIVATE 本标志说明,对映射区的存储操作导致创立该映射文件的一个副本。所有后来对该映射区的存访都是存访该副本,而不是原始文件。 这里内核用到了写时复制技术,在相应的页表项中设置写时复制标志,当进程试图修改该页,内核将会产生缺页异常,内核 就把该
11、页框进行复制,并在进程页表中用复制的页来替换原来的页框,显然这个新的页框已 经不在页高速缓存中了,对页框的内容进行修改将不会写回文件,其它进程将无法共享这个 页框。如果本进程还未进行写复制,而其它进程修改了页的内容,本进程是可以获得更新后 的数据因为映射文件的起动位移量受系统虚存页长度的限制,那么如果映射区的长度不是页长 度的整数倍时,将如何呢?假定文件长 12字节,系统页长为 512 字节,那么系统通常提供 512 字节的映射区,其中后 500 字节被设 0。可以修改这 50 字节,但任何变动都不会在文件中反 映出来。这是由于内核分配线性区和分配物理内存都是以页为单位与映射存储区相关有两个信
12、号:SIGSEGV和SIGBUS信号SIGSEGV!常用于指示进程试图存取它不能存取的存储区。如果进程企图存数据到用mmapf定为只读的映射存储区,那么也产生此信号。如果存取映射区的某个局部,而在存取时这一局部已不存在,那么产生SIGBUS信号。例如,用文件长度映射一个文件,但在存访该映射区之前,另一个进程已将该文件截 短。此时,如果进程企图存取对应于该文件尾端局部的映射区,那么接收到SIGBUS信号。对信号的实现机制有待进一步分析在 fork 之后, 子进程继承存储映射区 因为子进程复制父进程地址空间, 而存储映射区 是该地址空间中的一局部 ,但是由于同样的理由, exec 后的新程序那么不
13、继承此存储映射区。关闭文件描述符也不影响存储映射区,磁盘文件的页高速缓存并不会因为进程的撤销而撤 销,如果有足够的空闲内存,页高速缓存中的页将长期存在,使其它进程再使用该页时不再 访问磁盘。 进程终止时,或调用了munmap之后,存储映射区就被自动去除。关闭文件描述符fd并不解除映射区。关闭存储映射区, 只是撤销进程页表中的相应目录项, 并不影响页高速缓存。 #include <sys/types.h>#include <sys/mman.h>int munmap(void addr,size_t len) ; 返回:假设成功那么为0,假设出错那么为 - 1munm a
14、p并不影响被映射的对象一也就是说,调用mu nmap并不使映射区的内容写到磁盘文件上。对于 MAP_SHAREI区磁盘文件的更新,在写到存储映射区时按内核虚存算法自动进行。 pdflush 内核线程用于刷新脏页例子程序:#include <unistd.h>#include <stdio.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <sys/mman.h>int main(int argc, char *argv)int f
15、d, i, counter;pid_t pid;char *area = NULL;if(fd = open("test", O_RDWR) )<= 0)printf("open errorn");area = (char *)mmap(0, sizeof(long),PROT_READ| PROT_WRITEM, AP_SHAREDfd, , 0);printf("area:%pn", area);close(fd);*(area + 1) = 'c'文件映射 API 补充msync 函数的使用原型: ? #i
16、nclude <sys/mman.h>? int msync(const void *start, size_t length, int flags);msync 函数用来把映像的文件写入磁盘。调用msync 可以用对内存中的映像的更新写入一个被映像的文件,被强行写入到磁盘的内存取从start 指定的地址开始,写入 length 个字节的数据。 flags 可以是下面的一个值或多个的逻辑“或:? 1、MS_ASYNC调度一次写入操作然后返回? 2、MS_SYN(在msync返回前写入数据 ? 3、MS_INVALIDATE让映像到同一文件的映像无效,以便用新数据更新它们MS_INV
17、ALIDATE的作用是使映射的页高速缓存中的内容无效,重新从磁盘写入数据到映射的页高速缓存。可以使用MS_INVALIDATE来测试内核是否进行页高速缓存数据的回写磁盘操作,测试过 程:写一个字符到映射区,然后使用MS_INVALIDATE使映射区的数据失效,并从磁盘写入数据,从测试结果看字符会被写入磁盘,也就是说内核几乎在对映射区进行写入操作的同时就 进行了回写磁盘操作mprotect 函数的使用 mprotect 函数修改在内存映像上的保护模式。函数原型:? #include<unistd.h>? #include <sys/mmap.h>? int mprotec
18、t(const void *start, size_t len, int prot);mprotect 把自 start 开始的内存区的保护模式修改为 prot 指定的值,如果执行成功 返回0,如果执行失败,mprotect返回-1,并且设置errno变量。port可以是PROT_READ可 读、PROT_WRITE可写、PROT_EXEC可执行、PROT_NON环可访问中的一个或多个 这 里只是修改本进程页表中的访问控制标志,并不涉及物理页,对其它进程没有影响锁定内存原型:? #include <sys/mman.h>int mlock(const void *start, si
19、ze_t len);?int munlock(void *start, size_t len);? int mlockall(int flags);? int munlockall(void); 以 4 上个函数是对指定的内存映像加锁和解锁,其中 mlockall 的 flags 包括MCL_CURRENT MCL_FUTURE有root权限才能使用它们。start指出被加锁或解锁的 内存区,len指出加锁或解锁的内存区大小。flags 的值可以是MCL_CURREN和MCL_FUTURE之一或者两个都有。MCL_CURRE在调用返回前请求锁住所有内存页面,MCL_FUTUR指出锁住所有增加到
20、进程的地址空间的内存页面。mlock的操作结果是vma的属性,VM_LOCKED作用是被lock的内存不参加swap,保证一直存在于内存中内核中具体的策略执行可以看函数 swap_out_vma.当使用exec的时候,lock失效.fork的子进程也不继承此属性 .对于实时进程和平安程序 , 此调用很有意义 对于加密程序 , 密码不会被 dump 到磁盘上 但是 lock 并不能阻止系统休眠的时候内存被存储到磁盘 .mlock,munlock 的操作不可堆叠 . 屡次调用 mlock 的一段内存也会被一次 unlock 操作解 锁.mlock/munlock 指定的地址会被 round dow
21、n 到一个 page 的边界 . mremap 函数的使用 mremap 函数用于改变一个被映像的文件大小。原型:? #include<sys/mman.h>? void *mremap(void *old_addr, size_t olden, size_t new_len, unsigned long flags);mremap 用指定的 flags 把地址在 old_addr 的内存映像大小从 old_len 调整为 new_len,flags如果为MREMAP_MAYMOV调整此内存映像的地址。成功返回新地址,失败 返回 NULL。内核要做事情是:改变线性区对象的长度。内核
22、会检查是否可以直接扩大或者缩小线性区的大小,如果线性对象相邻的线性空间已经被使用了,此时将没法扩大了, 如果此时设置了 MREMAP_MAYMOV志,将会重新分配一块 新的线性空间,显然这个空间的起始地址已经改变四 IPC 共享存储包含实现原理说明IPC 共享存储允许两个或多个进程共享一给定的存储区。因为数据不需要在客户机和服务器之间复制,所以这是最快的一种IPC。使用共享存储的唯一窍门是多个进程之间对一给定存储区的同步存取。假设效劳器将数据放入共享存储区,那么在效劳器做完这一操作之前, 客户机不应当去取这些数据。通常,信号量被用来实现对共享存储存取的同步。调用的第一个函数通常是shmget,
23、它获得一个共享存储标识符。#include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);如果参数key为IPC_PRIVATE。那么会建立新的共享内存对象其大小由size(单位字节Byte)指定,如果key不为IPC_PRIVATE并且存在键值为 key的共享内存对象,那么返回所关联的 id 号,如果不存在键值为 key 的共享内存对象, 那么系统会视参数 shmflg 是否有 IPC_CREAT 来决定是否新建一个共享内存对象。 每个共享内存对象都对应一个目
24、录对象和一个inode对象,每个 inode 对象都包含一个 address_space i_mapping 对象, 但是这些对象并没有磁 盘映像,而是为了可以重复利用文件映射中提供的代码,每个进程映射的物理页就存储在 i_mapping 对象里。以上是一种特殊的文件系统,它并没有挂载在某个目录下,只是为了方便实现共享内存size 是要建立共享内存的长度。 所有的内存分配操作都是以页为单位的。 实际的大小是 (bytes 进位到 4096整数倍 )/4096 + 4) * 4096 。因为线性区和物理内存的分配都是以页 为单位shmflg主要和一些标志有关,其中有效的包括IPC_CREAT和I
25、PC_EXCL它们的功能与open()的 O_CREA和 O_EXCLf 当。IPC_CREAT如果共享内存不存在,那么创立一个共享内存,否那么翻开操作。IPC_EXCL只有在共享内存不存在的时候,新的共享内存才建立,否那么就产生错误。如果单独使用IPC_CREAT,shmget() 函数要么返回一个已经存在的共享内存的操作符,要么返回一个新建的共享内存的标识符。如果将IPC_CREAT和IPC_EXCL标志一起使用,shmget()将返回一个新建的共享内存的标识符;如果该共享内存已存在,或者返回-1。IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证所
26、得的对象是新建的, 而不是翻开已有的对象。返回值成功返回共享内存的标识符;不成功返回 -1, errno 储存错误原因。EINVAL参数 size 小于 SHMMIN或大于 SHMMAXEEXIST预建立 key 所致的共享内存,但已经存在。EIDRM参数 key 所致的共享内存已经删除。ENOSPC超过了系统允许建立的共享内存的最大值 (SHMALL )。ENOENT参数key所指的共享内存不存在,参数shmflg也未设IPC_CREAT位。EACCES没有权限。ENOMEM核心内存缺乏。struct shmid_dsshmid_ds 数据结构表示每个新建的共享内存。当 shmget 创立了
27、一块新的共享内存后, 返回一个可以用于引用该共享内存的 shmid_ds 数据结构的标识符。include/linux/shm.hstruct shmid_ds struct ipc_perm shm_perm; /* operation perms */int shm_segsz; /*_kernel_time_t shm_atime; /* _kernel_time_t shm_dtime; /* _kernel_time_t shm_ctime; /* _kernel_ipc_pid_t shm_cpid; /* _kernel_ipc_pid_t shm_lpid; /* unsign
28、ed short shm_nattch; /*共享内存的大小 */ 最后一次附加这个共享内存的时间 */ 最后一次别离这个共享内存的时间 */ 最后一次改变这个共享内存结构的时间 */ 建立这个共享内存的进程识别码 */ 最后一个操作共享内存的进程识别码 */ 附加这个共享内存的进程个数 */unsigned short shm_unused; /* compatibility */ void*shm_unused2; /* ditto - used by DIPC */void *shm_unused3; /* unused */;struct ipc_perm;对于每个 IPC 对象,系统
29、共用一个 struct ipc_perm 的数据结构来存放权限信息,以确一个 ipc 操作是否可以访问该IPC对象。struct ipc_perm _kernel_key_t key; /共享内存对象的 key_kernel_uid_t uid; /共享内存所属的用户识别码 可以修改_kernel_gid_t gid; /共享内存所属的组识别码 可以修改 _kernel_uid_t cuid; /建立共享内对象的用户识别码_kernel_gid_t cgid; /建立共享内对象的组识别码_kernel_mode_t mode; /这个共享内存的读写权限 可以修改 unsigned short
30、seq; /序号shmctl 函数对共享存储段执行多种操作。#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>int shmctlint shmid, int cmd, struct shmid_ds * buf ;返回:假设成功那么为 0,假设出错那么为 - 1cmd参数指定以下5种命令中一种,使其在shmid指定的段上执行。? IPC_STAT 对此段取 shmid_ds 结构,并存放在由 buf 指向的结构中。? IPC_SET按buf指向的结构中的值设置与此段相关结构中的以下三
31、个字段:只能修改这3个字段shm_perm.uid、shm_perm.gid以及shm_perm.modeb此命令只能由以下两种进程 执行:一种是其有效用户 ID 等于 shm_perm.cuid 或 shm_perm.uid 的进程;另一种是具有超 级用户特权的进程。? IPC_RMID 从系统中删除该共享存储段。因为每个共享存储段有一个连接计数 shm_nattch 在 shmid_ds 结构中 , 所以除非使用该段的最后一个进程终止或与该段脱接, 否那么不会实际上删除该存储段。 不管此段是否仍在使用, 该段标识符立即被删除 , 所以不能再 用 shmat 与该段连接。此命令只能由以下两种
32、进程执行 : 一种是其有效用户 ID 等于 shm_perm.cuid 或 shm_perm.uid 的进程;另一种是具有超级用户特权的进程。? SHM_LOC锁住共享存储段。此命令只能由超级用户执行。? SHM_UNLOC解锁共享存储段。此命令只能由超级用户执行。一旦创立了一个共享存储段,进程就可调用 shmat 将其连接到它的地址空间中。#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>void *shmat(int shmid, void *addr, int flag) ;返回
33、:假设成功那么为指向共享存储段的指针,假设出错那么为 - 1 。 共享存储段连接到调用进程的哪个地址上与 addr 参数以及在 flag 中是否指定 SHM_RND r _/ . 、/、位有关。(1) 如果 addr 为 0,那么此段连接到由内核选择的第一个可用地址上。(2) 如果addr非0,并且没有指定 SHM_RND那么此段连接到 addr所指定的地址上。(3) 如果addr非0,并且指定了 SHM_RND那么此段连接到addr (addr modSHMLBA)所表示的地址上。SHM_RN命令的意思是:取整。SHMLBA勺意思是:低边界地址倍数,它总是2的乘方。该算式是将地址向下取最近1
34、个SHMLBA勺倍数。除非只方案在一种硬件上运行应用程序 这在当今是不大可能的 ,否那么不用指定共享段 所连接到的地址。所以一般应指定 addr 为 0,以便由内核选择地址。如果在f I a g中指定了 SHM_RDONLY,那么以只读方式连接此段。否那么以读写方式连接 此段。在进程页表项中设置只读标志,试图修改该页时将产生缺页异常,这些都是由CPU的页寻址硬件控制的shmat 的返回值是该段所连接的实际地址,如果出错那么返回 1。 当对共享存储段的操作已经结束时,那么调用 shmdt 脱接该段。注意,这并不从系统中删 除其标识符以及其数据结构。 该标识符仍然存在, 直至某个进程 一般是效劳器
35、 调用 shmctI带命令IP C_RMID特地删除它。连接是进程将共享内存的物理页参加进程页表,脱离是 从页表中撤销该物理页的信息,并不改变实际的物理页#incIude <sys/types.h>#incIude <sys/ipc.h>#incIude <sys/shm.h>int shmdt(void * addr);返回:假设成功那么为 0,假设出错那么为 - 1addr 参数是以前调用 shmat 时的返回值。下面是和 IPC 共享内存有关的内核参数,可以修改的。其中 shmaII 是所有共享内存段可以使用的最大页个数 shm mni是一个共享内存段
36、的最小字节数 shmmax是一个共享内存段的最大字节数 下面是显示系统中已近建立的共享内存对象其中 bytes 是申请共享内存时使用的大小参数,实际的大小是 ( bytes 进位到 4096 整 数倍 )/4096 + 4) * 4096。nattch 是附加此共享内存对象的进程数。例子程序:#include <unistd.h>#include <sys/ipc.h> #include <sys/shm.h>#include <stdio.h>#include <sys/stat.h> #include <sys/types.
37、h> #include <fcntl.h> #define KEY 4 #define SIZE 4096*3 int main(int argc, char *argv)int shmid = 0, ret = 0; char *shmaddr = 0; struct shmid_ds buf;shmid = shmget(KEY, SIZE, IPC_CREAT | SHM_R); printf("id: %dn", shmid);shmaddr = (char *)shmat(shmid, NULL, 0); *(shmaddr + 4095*3)
38、= 'c'shmdt(shmaddr);使用ipcs - m查看建立的共享内存对象:要理解 IPC 共享内存和文件映射的实现机制,先要理解什么是共享内存,共享内存实现 的根本原理是什么。五共享内存实现根本原理CPU要访问某块内存,必须要获得内存的物理地址。CPU 集成有寻址硬件,会根据机器语言指令中提供的地址,执行地址转换,获得的物理 地址。CPU有两种转换模式:1.实模式2保护模式。实模式下的物理地址 = 线性地址。保护模式下的物理地址 = 线性地址通过分页机制转化为物理地址。启动保护模式:把 CPU控制存放器CRO中的最高位置1。CPU保护模式寻址方式:图 1 分页机制寻址
39、说明:CR3控制存放器的值是物理地址。 由于寻找的是页框的物理地址, 所以CR3页目 录和页表中存储的物理地址后 12 位都为 0。也就是这 12 位的空间不存储物理地址,而是用 于访问控制可读/可写/CPU特权级别,指示对应的页是否存在等作用。在转换过程中,出现以下情况之一将会引起也异常:涉及的页目录表内的表项或页表内的表项中的P=0,即涉及到的页不在内存;违反也保护属性的规定而对页进行访问。注意:从 2.6.11 版本开始,采用了四级分页模型,但根本原理是一样的。每个进程的CR3的值是不同,进程切换时保存或者恢复CR3的值。只要设置了 CR3的值CPU将自动进行寻址。要将某个物理页参加进程
40、的地址空间,要做的事情就是将物理页的物理地址填写进程页 目录表内的表项和页表内的表项。共享内存实现原理就是:将相同的物理页参加不同进程的地址空间。 显然进程中要参加一块物理页,就必须对应一块线性空间,于是就要先申请一块线性空 间,然后根据这块线性空间填写页目录表内的表项和页表内的表项。 这里可以说明为什么不 同进程中的不同线性地址可以对应相同的物理地址 。由于 linux 会先分配线性空间, 页表的修改会推后进行。 Linux 通过 vm_area_struct 对 象实现线性区, 当产生缺页异常时, 会根据 vm_area_struct 对象来修改页表, 然后重新执行 产生缺页异常的代码。总
41、的来说,内核实际要做的事情是很多的,但是,内核也提供了很多接口,所以我们要 做的事情还是比拟少的。以上就是共享内存实现的根本原理,下面分析一下 IPC 共享内存和内存映射实现机制。 实际上 IPC 共享内存的实现是基于内存映射,原因是:内存映射提供了一些接口,基于内存 映射来实现 IPC 共享内存可以复用这些代码。但是,两者最终的实现原理还是修改页表。 六 IPC 共享内存实现机制先看一下内核是如何组织共享内存对象的,如图 2 所示:图2 共享内存对象组织其中 struct shmid_kernel 就是一个共享内存对象,使用 id radix tree 来组织所有的 共享内存对象。使用 id
42、 号查找一个共享内存对象。我们现在最关心的问题是:如何根据 struct shmid_kernel 结构获得对象所拥有的物理 内存。是根据 file->f_path.dentry->d_inodestruct address_space *mapping = inode->i_mappingmapping 存储着共享内存拥有的物理页,如图 3 所示:图 3 共享内存物理页存储方式其中 page_tree 用于存储物理页,每个节点的值类型是 struct page * 每个共享内存对象对应一个 inode 对象,这个对象是被多个进程共享,也就是说,进程是通 过 inode 对象
43、获得物理页。这里借用了文件映射的框架, i_mmaping 对象也就是文件的页高 速缓存。进程映射共享内存区域的过程:1. 需要申请一块线性地址空间, 也就是生成一个 vm_area_struct 对象,并将对象参加到 自己的地址空间, 当此时并不修改进程页表, 而是把 struct file 对象参加到 vm_area_struct 对象中,执行以下代码:vma->vm_file = file;get_file(file);error = file->f_op->mmap(file, vma);注意:这里的 file 是根据 shm_file 生成的一个新的对象,相当于 s
44、hm_file 的复制。2. 当第一次访问共享内存块时, 由于相应的页表项还未填写, 将产生缺页异常, 内核根 据产生异常的线性地址找到对应的 vm_area_struct 对象,最后将执行以下函数:static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)struct inode *inode = vma->vm_file->f_path.dentry->d_inode;int error;int ret;if (loff_t)vmf->pgoff << PAGE_CAC
45、HE_SHIFT) >= i_size_read(inode)return VM_FAULT_SIGBUS;error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret);if (error)return (error = -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);return ret | VM_FAULT_LOCKED; 本函数的功能是:根据产生缺页异常的线性地址找到对应的物理页,并将这个物理页加 入页表。以上说明的也就是内存映射实现机制,现在做个总结:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2023年莱芜辅警招聘考试真题含答案详解(精练)
- 2024年三亚辅警招聘考试题库含答案详解(a卷)
- 2024年云南辅警协警招聘考试真题含答案详解(考试直接用)
- 2024年六盘水辅警招聘考试题库及完整答案详解1套
- 2024年孝感辅警招聘考试题库含答案详解(预热题)
- 2024年三门峡辅警招聘考试真题附答案详解(突破训练)
- 2023年鄂州辅警招聘考试题库附答案详解(培优a卷)
- 2024年佛山辅警招聘考试真题完整答案详解
- 2023年鹤壁辅警协警招聘考试真题及答案详解(全优)
- 2024年南充辅警协警招聘考试真题含答案详解(b卷)
- 2025-2026学年外研版(三起)(2024)小学英语三年级上册期中检测试卷及答案
- 2025消防月消防安全知识培训课件
- 大规模数据标注技术-洞察及研究
- 2025至2030钛合金产业行业项目调研及市场前景预测评估报告
- 消防工程监理质量评估及验收报告
- 人教版九年级政治上册期中考试试卷及答案
- 知道智慧树网课《中国新闻史(渤海大学)》课后章节测试答案
- 肿瘤科简答试题及答案
- GB 14930.2-2025食品安全国家标准消毒剂
- 房屋拆迁安置协议
- 住院医师规范化培训基地评估指标(培训基地医院部分)
评论
0/150
提交评论