1 基于tmpfs的mmap系统调用过程
前面一篇blog:mmap那些事之android property实现,讲述了android的属性系统是基于tmpfs的mmap来实现内存的共享,只是论述了应用层的使用,并未涉及到内核空间是怎么处理的。
包括如下几个问题:
mmap系统调用过程
tmpfs文件针对mmap做了哪些处理?这里包括tmpfs是怎样分配实际的物理内存到共享内存的,然后其他应用进程映射到这个tmpfs的文件时,又是怎么取得这个共享物理内存的,并且又是怎么建立到自己所属进程的地址空间映射页表的)
2 mmap的系统调用过程
首先简单说明下mmap的系统调用过程:
do_mmap是应用空间mmap调用在内核空间入口,该函数前面只是做了些参数的合法性检查,在这里addr一般为0,如果不为0,则说明应用空间希望内核使用该地址作为虚拟地址的开始地址,但实际返回的地址是由当前进程的地址空间使用情况决定的,所以返回值并不一定是用户希望的addr的值,应用空间应用使用mmap系统嗲用返回的addr值。len参数指定映射的虚拟内存的长度。我们直接转到do_mmap_pgoff函数:
............
............
上面的line998 addr参数就是linux mm系统自动为我们分配的这段映射内存的开始虚拟地址
mmap_region函数主要做如下几件事情:
首先将[addr,addr+len]的这段虚拟地址空间的之前的映射拆除掉。
其次将[addr,addr+len]这段地址范围跟相邻的wma进行合并
如果不能合并,则分配新的wma结构体来管理[addr,addr+len]这段地址范围
最重要的地方出现了,如下图高亮部分,执行该映射文件句柄对应的mmap操作函数,该函数是需要支持mmap系统调用的驱动来实现的。file_operations中的mmap操作函数的实现方法有两种典型实现,ldd3的参考书籍上有详细的描述和实例,在这里,我们发现op->mmap的函数原型跟系统调用的mmap函数原型已经简化多了,因为linux的mm子系统已经为我们做了大部分事情,譬如已经为我们找到了一块合适的虚拟内存空间(vma数据结构体来表示)来为映射具体的物理内存空间做准备,并且在调用了驱动中的mmap函数后,将这个vma结构体连接到当前进程的mm结构体中。
最后,将vma数据结构连接到所属进程的mm内存管理数据结构中,