2015-10-06 47 views

回答

3

有关于这上LWN一个详细的文章:https://lwn.net/Articles/631631/

具体地,代码由load_elf_binary()加载:http://lxr.free-electrons.com/source/fs/binfmt_elf.c?v=3.18#L571

即功能从do_execve_common()这当然是从execve()称为所谓的(间接)和朋友:http://lxr.free-electrons.com/source/fs/exec.c?v=3.18#L1513

正如您可能已经知道的,execve()和朋友通常在创建新过程后(通过fork())调用。所以在“创建流程”和“加载ELF”之间几乎没有什么关系。

最后,通过由MMU的硬件异常调用的页错误处理程序将代码从虚拟物理存储器加载到物理存储器。

+0

那么你和我涵盖了两个不同的方面。尼斯。 – Joshua

+1

谢谢你的链接。但是二进制文件的实际代码段在第一次开始正确执行之前是不会被加载的?当进程第一次尝试执行时,它会在第一条指令的地址上发生页面错误。不是当实际的文件被加载到内存中吗? (假设这个程序是第一次运行) – woodstok

+1

@MIhahail:当你问“是不是当实际的文件被加载到内存中?”我想你的意思是物理记忆?在这种情况下,我认为你是对的,直到最后一刻才能加载到物理RAM中。 –

2

内核会将ELF exe映像加载到映像标头所示的位置。 (我们记得Unix完全依赖虚拟内存来正常工作,请参阅fork()。)内核具有加载共享库的例程;但是除了装载机本身,这些很少使用。内核然后跳转到图像中指定的起始地址。如果有一个加载器,这个跳转就会被劫持进入加载器。

大多数共享库都由加载器加载(/lib/ld-linux-so.2 for i386),这是一个共享库。加载器可以执行诸如定位共享库在系统中的位置等内容,而不是依赖嵌入在exe镜像中的绝对路径,就像内核所做的那样。加载器将库映射到内存并执行修复。加载器保持加载到内存中,并可用于按需加载其他库(请参阅dlopen())。