MIT 6.828 操作系统课程系列10 mmap#
linux的mmap函数#
https://www.man7.org/linux/man-pages/man2/mmap.2.html
https://en.wikipedia.org/wiki/Mmap
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
mmap创建文件/设备到内存的映射。把fd偏移offset处,映射到addr。映射长度至少为length。
addr参数可不传,让函数返回实际映射地址。如果传了addr,addr只是作为一个hint。实际地址以返回值为准。
返回的地址都是对齐的。
prot可为PROT_EXEC
/PROT_READ
/PROT_WRITE
/PROT_NONE
。
flag较多
MAP_ANONYMOUS
匿名映射。不用提供fd和offset。MAP_SHARED
共享映射。对此映射的修改,对于其他映射到此区域的进程可见。
如果和fd关联,也会更新其文件。MAP_PRIVATE
cow映射。本地修改对于其他进程不可见,也不会更新关联的文件。
https://www.man7.org/linux/man-pages/man2/msync.2.html
msync
// uwsgi中的例子
// 创建进程间共享内存
uwsgi.shared = (struct uwsgi_shared *) uwsgi_calloc_shared(sizeof(struct uwsgi_shared));
uwsgi_malloc_shared
void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
uwsgi的mmap。创建匿名共享映射,直接做成类似malloc一个uwsgi_shared。然各个进程共享。
virtual memory#
https://en.wikipedia.org/wiki/Virtual_memory
内容挺多。大概看看看课程的lecture17视频。
他把mmap/页表/vma这些内容归为virtual memory
。建议阅读的论文https://www.cs.princeton.edu/~appel/papers/vmpup.pdf
作为外行听到的虚拟内存,一般是指把硬盘之类充当内存来用(windows有个配置)。
实际是指一个更大的概念,覆盖存储管理/地址管理等一系列内容。
写代码#
最后一个lab了,胜利就在眼前。mmap涉及的内容比较杂,还是需要一点点耐心实现各种规则。
必须搞懂文件系统的流程和结构。打开文件的流程,根据path得到inode,分配file和fd,关联,返回fd。
文件的实际内容在其inode的addrs里,由一串磁盘block号组成,block可位于磁盘的任何位置,不一定是连续的。
写文件时看offset落在addrs的位置,找到对应的磁盘block,写磁盘。
复习lab3页表相关
mmap需要做一个虚拟地址va返回给用户,从va开始,指定长度length。之间的连续地址需要映射到文件的block。
根据prot设置读/写/执行权限。
根据flags决定更新行为。
MAP_SHARED
为共享。一个进程改了数据,其他进程都能看到。并且要更新文件。
MAP_PRIVATE
为私有。每个mmap映射维护一条数据(结构体),每个进程要维护好自己的所有映射数据。
地址怎么生成?如果直接按sz来,删除时会出现
洞
,后续fork时不好处理。
可做成一个固定位置,像TRAPFRAME
那样,更容易处理。创建映射时处理好PTE的flag,使读写走page fault。在trap里读对应的文件block。这样实现lazy分配。
对地址的操作和文件offset的处理类似。
基本测试是先往文件里写1.5page的数据。然后创建mmap,读地址上的数据检查是否和写文件时数据数据一致。
如果文件是read only,禁止
PROT_WRITE
的mmap。munmap删除映射。测试中都是按页对齐来unmap,不用考虑复杂情况。可删除两头的部分映射,不会出现从中间打个洞。
如果是MAP_SHARED
,需要把修改过的页更新到文件。mmap后如果unlink删除文件?如果又创建一个文件再写入,可能把mmap的数据篡改。
需要处理文件和inode的引用计数,hold住数据。exit时删除映射。
fork时要复制维护的mmap数据,做地址映射。参考uvmcopy。
trap里处理mmap,要区分是否mmap导致。如果不是要正常kill,否则usertests会失败。
到此整个课程结束。对os的基本流程有了一定了解。可以开始动手做一个自己的os了。