Linux内核如何装载和启动一个可执行程序

来源:互联网 发布:小嶋阳菜毕业知乎 编辑:程序博客网 时间:2024/05/22 05:13

1.可执行文件的生成过程

1)用vim编辑器新建一个hello.c程序,源程序如下:


2)使用指令:gcc -E -o hello.cpp hello.c -m32,将hello.c预处理成hello.cpp文件,经过预处理的hello.cpp文件将会引入很多宏定义,以及包含很多库文件。内容如下:


3)用gcc -x cpp-output -S -o hello.s hello.cpp -m32指令进行汇编,得到汇编hello.s文件,


4)用指令gcc -x assembler -c hello.s -o hello.o -m32 生成hello.o目标文件,此时如果用vim打开是乱码。

5)用命令gcc -o hello hello.o -m32可以生成目标文件,用vim打开hello文件也将是乱码

6)用命令gcc -o hello.static hello.o -m32 -static将目标文件编译成静态链接文件

7)直接运行命令./hello,可得如下结果:



2.ELF可执行文件格式

最后得到的可执行文件hello就是linux环境中的格式为ELF的可执行文件,相当于windows环境下的.exe可执行文件。

指令readelf -h hello,可以查看ELF文件的文件头:



ELF文件的整体格式如下所示:


它包括一个ELF的头,还有记录程序的头文件,以及之后分的若干个程序段(代码段+数据段),真是基于此,可执行文件才能正确地映射到进程地址空间中,使得系统很容易得为其分配空间,分配多大空间,以及进行这一切的时机等等。

3.使用exec*库函数加载一个可执行文件

执行以下命令启动MenuOS

1)cd ./ LinuxKernel

2)rm -rf menu

3)git clone https://github.com/mengning/menu.git

4)cd menu

5)mv test_exec.c test.c

6)make rootfs

在MenuOS的grab界面中执行exec命令,可成功执行并加载hello可执行程序。


4.使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve

执行qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -S -s”启动调试窗口。

重新打开一个新的终端进入menu目录下:

1)gdb

2)file ../linux3.18.6/vmlinux

3)target remote:1234

设置七个断点,分别为:


追踪过程中,程序大量的时间都在断点2和断点3处,


当系统加载成功是,执行exec命令,就会看到预期效果:



5.总结

本实验详细的分析了elf可执行文件的文件格式,以及如何一步步生成elf可执行文件的过程,最后追踪了内核程序加载可执行文件的过程。exec根据elf头规定的格式,将执行文件进行加载到进程的地址空间。如果是静态链接的就将文件头部标明的入口地址作为开始;如果是依赖动态链接库的可执行文件则需要将动态链接器ld的入口地址作为开始。


张伟 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

0 0
原创粉丝点击