TL;DR
1. 初始化内存空间
2. 载入动态库
3. 初始化全局变量
如果用 gdb 调试一个 C 程序,可以发现函数调用栈的栈底不是
main
,而是 _start
,_start
调用了 __libc_start_main_impl
函数,这个函数有 main,argc,argv,
init,fini,rtld_fini
和 stack_end
参数,其中上面下划线的是回调函数指针, init
函数中做了初始化相关的工作,比如内存申请,动态库载入,全局变量初始化,而 fini
主要是 atexit
函数的调用,rtld_fini
主要是卸载动态库(就如名字 runtime ld)。动态库不是共享的吗?为什么需要载入到内存?
因为程序只能访问自己的用户空间,所以只能映射过来。在老版的 Linux 中,它的地址是 0x4000 0000 开始的一块空间,位于堆内存的内部(新版 Linux 内核修改了位置)。