考虑以下针对Linux x86_64的程序:
inf.s:
.global _start
.text
_start:
jmp _start
这基本上是一个无限循环。
如果我链接并删除它,我会得到一个ELF可执行文件:
$ gcc -nostdlib inf.s
$ ./a.out &
[1] 15862
$ cat /proc/15862/maps
00400000-00401000 r-xp 00000000 fc:00 11404632 a.out
7fffacdb8000-7fffacdd9000 rwxp 00000000 00:00 0 [stack]
7fffacddd000-7fffacdde000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
在ELF可执行文件中,第一个程序头LOAD
包含占上述mmaps(a.out)中第一个条目的映射。 (即使我删除每个,但是这个标题和代码都会观察到相同的地图。)execve(2)
调用fs/binfmt_elf.c
中的ELF处理程序,它读取程序头并在文件上调用mmap。
我不明白的是其他三个来自哪里(stack,vdso,vsyscall)。它们未在ELF文件中提及,因此Linux内核必须默认设置这三个“匿名”或“特殊”映射。
我的问题是Linux内核在内核代码(或如何)中创建其他三个映射的位置?他们是否继承了这个人?我似乎无法看到它们在fs/exec.c
中的位置。
答案 0 :(得分:6)
内核在将文件加载到内存中时会自动创建它们。
[vdso]
和[vsyscall]
的精确控制流程难以理解,因为根据内核是32位还是64位而是一些相关的函数名称,将各种函数名称定义和重新定义为宏例程包括:
load_elf_binary
fs/binfmt_elf.c
调用arch_setup_additional_pages
在arch_setup_additional_pages
中arch/x86/vdso/vma.c
在arch_setup_additional_pages
arch/x86/vdso/vdso32-setup.c
[stack]
映射不是特定于ELF的,并且由__bprm_mm_init
中的fs/exec.c
创建,execve
代码在{{1}}代码调用格式特定加载器之前调用。