我找不到的是当我的请求超出页面边界时,现代系统/硬件如何处理这种情况?
这是一个例子:
>我malloc()一块8KB的内存.
>假设malloc()没有足够的内存,而sbrk()的内存为8KB.
>内核获取两个内存页(每个4KB)并将它们映射到我的进程的虚拟地址空间(假设这两个页面在内存中不是一个接一个)
> movq(offset $0xffc),%rax我从第4092个字节开始请求8个字节,这意味着我需要从第一页末尾开始的4个字节和从第二个页面开头开始的4个字节.
物理内存:
---|---------------|---------------|--> |... 4b| | |4b ...|-->
我需要在页面边界分割的8个字节.
x86-64和ARM上的MMU如何处理这个问题?内核MM中是否有任何机制以某种方式为这种请求做准备? malloc中有某种保护吗?处理器做什么?他们取两页吗?
我的意思是完成这样的请求MMU必须将一个虚拟地址转换为两个物理地址.它如何处理这样的请求?
如果我是软件程序员,我应该关心这些事情吗?为什么?
我正在阅读谷歌,SO,drepper的cpumemory.pdf和gorman的Linux VMM书中的很多链接.但它是一个信息的海洋.如果您至少向我提供一些我可以使用的指针或关键字,那将会很棒.
解决方法
- An operation that performs an unaligned access can abort on any memory access that it makes,and can abort on more than one access. This means that an unaligned access that occurs across a page boundary can generate an abort on either side of the boundary.
因此,除了可能从单个操作生成两个页面错误之外,它只是另一个未对齐的访问.当然,这仍然假设“只是另一个未对齐的访问”的所有警告 – 即它仅在普通(非设备)内存上有效,仅对于某些加载/存储指令,不保证原子性并且可能很慢 – 微架构将可能从多个对齐的访问1合成一个未对齐的访问,这意味着多个MMU转换,如果它跨越行边界,可能有多个缓存未命中等.
另一方面,如果未对齐的访问不跨越页面边界,那么所有这意味着如果第一个“子访问”的对齐地址转换为OK,则任何后续部分的对齐地址肯定会被击中在TLB中. MMU本身并不关心 – 它只是翻译处理器提供的一些地址.除非MMU引发页面错误,否则内核甚至不会进入图片,即便如此,它也与任何其他页面错误无异.
我已经快速浏览了英特尔手册并且他们的答案没有突然出现 – 但是在“数据类型”一章中他们说:
[…] the processor requires two memory accesses to make an unaligned access; aligned accesses require only one memory access.
如果不是大致相同(即每个对齐访问一个翻译),我会感到惊讶.
现在,这是大多数应用程序级程序员不必担心的事情,只要他们自己行事 – 在汇编语言之外,实际上很难进行未对齐的访问.可能的罪魁祸首是打字指针和搞乱结构包装,这两种情况都是99%的时间没有理由接近,而另外1%的事情几乎肯定是错误的.
[1] ARM体系结构伪代码实际上将未对齐访问指定为一系列单独的字节访问,但我希望实现实际上在适当的情况下将其优化为更大的对齐访问.