Lab: mmap
这个实验的本质就是实现mmap和munmap的系统调用。
mmap介绍和用途
mmap系统调用是UNIX系统一个十分强大的功能,给用户进程规划自己地址空间的一个强大工具,具体内容可以要求内核将一个文件或者其他对象直接映射到该进程的虚拟地址空间中。
具体函数原型如下:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
-
addr:建议的起始地址。进程可以建议一个希望映射开始的虚拟地址。通常设置为NULL,让内核自动选择一个合适的地址。如果非空,内核会尽量满足,但不会保证。 -
length:映射区域的长度,单位是字节。 -
prot:保护模式,指定了对映射内存的访问权限。可以是以下值的组合:-
PROT_READ:页面可读。 -
PROT_WRITE:页面可写。 -
PROT_EXEC:页面可执行。 -
PROT_NONE:页面不可访问。
-
-
flags:控制映射行为的标志。这是mmap强大功能的关键。重要的标志包括:-
MAP_SHARED:共享映射。对映射区域的修改会写回到文件中,并且对其他映射了同一文件的进程是可见的。这是实现进程间通信(IPC)的基础。 -
MAP_PRIVATE:私有映射。会创建一个写时复制 的映射。对映射区域的修改不会写回文件,并且对其他进程不可见。进程最初会看到文件的原始内容,但当它尝试写入时,会为该页面创建一个私有副本,所有修改都发生在副本上。这通常用于加载动态库或初始化一段内存。 -
MAP_ANONYMOUS/MAP_ANON:匿名映射。此时不需要文件描述符(fd设为 -1)。它映射的不是文件,而是一块由内核初始化为零的物理内存。常用于分配大块内存(类似于malloc,但更底层)。
-
-
fd:文件描述符。代表要映射的文件。如果使用MAP_ANONYMOUS,此参数应设为 -1。 -
offset:文件偏移量。指定从文件的哪个位置开始映射,必须是系统页大小的整数倍。
mmap在操作系统中的用途非常广泛,具体用途如下:
1.首先是简化了文件操作,相比于传统的read/write操作,mmap使得进程可以直接操作内存从而实现操作文件的目的,简化流程也提高了效率。
2.MAP_SHARED共享映射,是实现IPC之间的基石。通过将同样一个文件或者匿名文件共享映射给不同的进程中,实现了进程间的通信,这也是共享内存的逻辑。(进程间通信还包括管道(匿名管道支持有亲缘关系的进程,命名管道支持无亲缘关系的进程)、共享内存、消息队列(内核维护一个消息链表,每个消息由类型和优先级,进程通过消息队列标识访问)、信号、套接字等)。
3.MAP_ANON匿名映射,当程序申请较大空间时,不从堆区通过sbk系统调用申请,而是通过mmap匿名映射一块物理内存,通过延迟分配等技巧供进程使用。
实验思路和实现
本次实验并没有要求我们实现全部的mmap功能,规定addr恒等于0,也就是完全由内核决定将文件映射到进程的哪个虚拟地址。
回顾进程的虚拟地址空间,如下图:

除了堆区和栈区,其余的空间都不太好塞,并且发现栈区全部只有一个PAGESIZE,可能不够文件放的,我们只能放到堆区。但堆区进程自己使用的时候是从下到上生长的,我们不可能和他同样的生长方式或者在中间,最好的方式从trapframe从上往下生长,这样尽可能做到不冲突。
之后我们根据提示创建一个VMA的结构,考虑这个区域是个进程使用的,我们创建在proc.h中并将其添加到进程数组中,代码如下:
struct mmap_vma
{
uint64 addr; //起始首地址
uint64 length; //长度
int prot; //权限
int flags; //私有映射

最低0.47元/天 解锁文章
1309

被折叠的 条评论
为什么被折叠?



