进程与内存4-mmap实现1(nopage方法原理及实例)

本文介绍了Linux内核中mmap内存映射的原理,特别是针对请页机制中的nopage方法。文章以arm平台的Linux 3.2.36为例,探讨了进程地址空间、vm_area_struct结构以及vm_operations_struct中的fault方法。讨论了缺页的原因,包括程序出错、缺页和写保护,并详细解释了页故障处理流程,尤其是do_page_fault()和__do_page_fault()函数的作用。最后,给出了一个关于正确使用nopage方法的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设现在有个有个驱动,有一段内存叫做sh_mem。当用户打开这个文件并mmap。mmap要做什么,当然是建立用户态的地址与此驱动建立对应关系。我知道的有两种:

1. 我们给用户提供一个方法,如果你要用这个内存时才会映射。这就是请页机制。

2. 我们一次映射好。

这篇文章,我们先讲第一种,实验:arm平台linux-3.2.36

如果你只想看看nopage使用方法,就直接倒下面代码去。中间就不要看了,也没什么。


 普通进程的地址空间定义:允许进程使用的全部线性地址组成。

内核可以通过增加或删除某些线性地址区间来动态地修改进程的地址空间。

 

普通进程获得新线性区的可能:

1.      创建新进程执行一个程序。这就是新地址空间+新进程。

2.      正在运行的进程装入不同的程序(如用exec函数),这个相当上面就是新地址空间+旧进程。

3.      对一个文件执行“内存映射”。内核给这个进程分配新线性区来映射这个文件。这对于我们搞驱动来说,主要就是mmap()。这个“内存映射”是我们的重点。

4.      进程可能持续向它的用户态堆栈增加数据,直到映射这个堆栈的线性区用完为止。这时内核也许会决定扩展这个线性区的大小。

5.      在我学习Linux高级编程中,进程间通信中说到一种共享内存区的东西,这个也需要分配新内存。

6.      malloc分配。进程可能扩展自己的动态区(堆),内核可能确定扩展给这个堆所分配的线性区。

上面有些内核提供了系统调用方法。

 

普通进程地址空间信息包含在一个叫做内存描述符的结构的类型为struct mm_struct.网上有很多它的资料。它包涵一个struct vm_area_struct列表,一个struct vm_area_struct代表一个VMA,可以把structvm_area_struct叫做线性区描述符。structvm_area_struct包涵一个

const struct vm_operations_struct *vm_ops;这个是此线性区的操作方法。有个no_page方法:

在2.6.23之前structvm_operations_struct中只有

struct page * (*nopage)(struct vm_area_struct * area,unsigned long address, int *type)

从2.6.24后在structvm_operations_struct中的出现

int (*fault)(struct vm_area_struct *vma, structvm_fault *vmf)

并在一段时间里,内核同时支持这两个函数,但后面的内核版本取消了

struct page * (*nopage)(struct vm_area_struct * area,unsigned long address, int *type)

我的linux-3.2.36就取消了。 缺页也很我要弄明白的东西。

现在是fualt,struct vm_fault如下:

 

struct vm_fault {

        unsigned intflags;             /* FAULT_FLAG_xxxflags */

        pgoff_t pgoff;                  /* Logical page offset b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值