二进制重排简介

200 阅读2分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。

二进制重排的背景介绍

物理内存和虚拟内存

当应用被加载到内存中的时候,只会把用到的那一部分放到内存里,即应用用多少,就加载多少到内存里。 为什么要这么做呢?

  • 如果全用物理内存,那么访问的都是物理地址,那么随便一偏移就访问到其它的进程上了
  • 现在软件越来越大,用户通常不会用到这个程序的所有内容,全加载会造成内存浪费 但是我们程序访问的相对内存地址通常在编译的时候就已经确定了,所以需要引入虚拟内存的概念:进程中可以按原有设定的地址去访问,但是访问的其实都是虚拟的地址,最终通过一张映射表去访问到真实的物理地址。每个进程都有自己的映射表,能访问的实际物理地址是受限的,这样就解决了之前提到的安全问题和效率问题。

缺页中断

为了提高效率和管理方便,又对虚拟内存和物理内存进行了分页,当访问一个虚拟内存的页但是对应的物理内存不存在,就会触发一次缺页中断,从而开始分配物理内存,需要的话需要从磁盘读入数据。

通过 AppStore 分发的 App,缺页中断还需要进行签名认证,所以耗时甚至更高。 linux 系统和 macos,一页大小为 4kb,ios 系统一页大小为 16kb。

二进制重排

假设我们做一件事需要调用多个函数,如果这多个函数在编译的时候离的比较远,那么就可能会发生缺页中断,因为这几个函数不在同一个页上,那么它们有可能没有同时被加载到内存中,当调用到没被加载的函数,就会发生缺页中断。

二进制重排的目的就是将一次调用的函数放到同一页中,这样就最大程序减少缺页中断了。这个需要在编译阶段对编译顺序进行干预,保证编译顺序跟调用顺序保持一致。