Linux内核分析(第七周)
2016-04-06 13:55
525 查看
可执行程序的装载
一、预处理、编译、链接和目标文件的格式
1.可执行程序怎么来的?
预处理:
gcc -E -o hello.cpp hello.c -m32
*负责把include的文件包含进来及宏替换
编译:
gcc -x cpp-output -S -o hello.s hello.cpp -m32
gcc -x assembler -c hello.s 0o hello.o -m32
hello.s 汇编代码
hello.o 二进制文件
链接:
gcc -o hello hello.o - -m32
2.目标文件的格式ELF
A.out COFF (PE+ELF)
三种类型:
可重定位文件
可执行文件
共享文件
Entry point address 程序的起点
3.静态链接的ELF
静态链接会将所有代码放在一个代码段
动态链接会有多个代码段
二、可执行程序,共享库,和动态链接
1.装载可执行程序程序之前的工作
执行环境:命令行+参数
*shell本身不限制命令行参数的个数
*shell会调用execve将命令行参数和环境参数传递给main函数
shell>execve>sys_exceve
*初始化新程序堆栈时拷贝进去
*先函数调用参数传递,再系统调用参数传递
2.装载时动态链接和示例
三、可执行程序的装载
1.相关关键问题分析
fork先返回父进程一次;再返回ret_from_fork开始执行然后返回用户态
sys_execve:
do_exceve>do_execve_common>exec_binprm
通过修改内核堆栈中EIP的值作为新程序的起点
2.sys_exceve的内部处理
对于静态链接的文件elf_entry是新程序执行的起点
3.gdb跟踪
new_ip是返回到用户态的第一条指令的地址
实验:
1、
静态链接
静态链接是在链接时将库的内容加入到可执行程序中的做法。因为要将所有需要的库文件放到同一个文件中,所以占用空间会比较大,但是执行效率非常高。
动态链接
动态链接是当需要某个头文件时动态的去库中去找,并不用像静态链接那样去提前全部加载进去。这样链接出来的文件相对来说空间较小,但是效率略逊于静态链接。
动态链接分装载时动态链接和运行时动态链接。两者在gcc下指令相同,但是使用方式略有不同。
Linux下的三种目标文件格式
1.可重定位文件( .o ):二进制代码和数据,由各个数据节(section)构成,从地址0开始。
2.可执行文件:可运行的二进制代码和数据。
3.共享目标文件( .so ):一种特殊类型的可重定位目标文件,动态加载链接。
Linux上,目标文件的格式称为可执行和可链接格式(ELF)
2.步骤
cd LinuxKernel
rm -rf menu
git clone
https:///mengning/menu.git
cd menu
mv test_fork.c test.c
make rootfs
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/21/1ad96de6ab90c0eb1a1be471d3e9369f.png)
qemu -kernel linux-3.18.6/arch/x86/boot
![](http://www.cnblogs.com/java44/p/file:/C:\Users\ADMINI~1\AppData\Local\Temp\N{9{TF[HIQJC}Y0K]`FF@A1.gif)
Image -initrdrootfs.img -s -S
打开gdb进行远程调试
gdb
file linux-3.18.6
![](http://www.cnblogs.com/java44/p/file:/C:\Users\ADMINI~1\AppData\Local\Temp\[LC3U)F{0XCAB)LKNIT0K@G.gif)
mlinux
target remote:1234
B sys_execve
B load_elf_binary
B start_thread
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/21/db2007ae39bc76d7c323a8d1d8b63b7c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/21/9da44b6f86d8ea14904434a814a00702.png)
linux首先创建父进程,然后通过调用fork()系统调用创建一个新的进程,然后新的进程调用execve()系统调用执行指定的ELF文件。 主进程继续返回等待新进程执行结束,然后重新等待用户输入命令。execve()系统调用被定义在unistd.h。
对于ELF格式的可执行文件,按照格式要求加载到内存中相应的地址空间,如果是静态链接的就将文件头部标明的入口地址作为开始;如果是依赖动态链接库的可执行文件则需要将动态链接器ld的入口地址作为开始。
一、预处理、编译、链接和目标文件的格式
1.可执行程序怎么来的?
预处理:
gcc -E -o hello.cpp hello.c -m32
*负责把include的文件包含进来及宏替换
编译:
gcc -x cpp-output -S -o hello.s hello.cpp -m32
gcc -x assembler -c hello.s 0o hello.o -m32
hello.s 汇编代码
hello.o 二进制文件
链接:
gcc -o hello hello.o - -m32
2.目标文件的格式ELF
A.out COFF (PE+ELF)
三种类型:
可重定位文件
可执行文件
共享文件
Entry point address 程序的起点
3.静态链接的ELF
静态链接会将所有代码放在一个代码段
动态链接会有多个代码段
二、可执行程序,共享库,和动态链接
1.装载可执行程序程序之前的工作
执行环境:命令行+参数
*shell本身不限制命令行参数的个数
*shell会调用execve将命令行参数和环境参数传递给main函数
shell>execve>sys_exceve
*初始化新程序堆栈时拷贝进去
*先函数调用参数传递,再系统调用参数传递
2.装载时动态链接和示例
三、可执行程序的装载
1.相关关键问题分析
fork先返回父进程一次;再返回ret_from_fork开始执行然后返回用户态
sys_execve:
do_exceve>do_execve_common>exec_binprm
通过修改内核堆栈中EIP的值作为新程序的起点
2.sys_exceve的内部处理
对于静态链接的文件elf_entry是新程序执行的起点
3.gdb跟踪
new_ip是返回到用户态的第一条指令的地址
实验:
1、
静态链接
静态链接是在链接时将库的内容加入到可执行程序中的做法。因为要将所有需要的库文件放到同一个文件中,所以占用空间会比较大,但是执行效率非常高。
动态链接
动态链接是当需要某个头文件时动态的去库中去找,并不用像静态链接那样去提前全部加载进去。这样链接出来的文件相对来说空间较小,但是效率略逊于静态链接。
动态链接分装载时动态链接和运行时动态链接。两者在gcc下指令相同,但是使用方式略有不同。
Linux下的三种目标文件格式
1.可重定位文件( .o ):二进制代码和数据,由各个数据节(section)构成,从地址0开始。
2.可执行文件:可运行的二进制代码和数据。
3.共享目标文件( .so ):一种特殊类型的可重定位目标文件,动态加载链接。
Linux上,目标文件的格式称为可执行和可链接格式(ELF)
2.步骤
cd LinuxKernel
rm -rf menu
git clone
![](http://www.cnblogs.com/java44/p/file:/C:\Users\ADMINI~1\AppData\Local\Temp\%W@GJ$ACOF(TYDYECOKVDYB.png)
cd menu
mv test_fork.c test.c
make rootfs
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/21/1ad96de6ab90c0eb1a1be471d3e9369f.png)
qemu -kernel linux-3.18.6/arch/x86/boot
![](http://www.cnblogs.com/java44/p/file:/C:\Users\ADMINI~1\AppData\Local\Temp\N{9{TF[HIQJC}Y0K]`FF@A1.gif)
Image -initrdrootfs.img -s -S
打开gdb进行远程调试
gdb
file linux-3.18.6
![](http://www.cnblogs.com/java44/p/file:/C:\Users\ADMINI~1\AppData\Local\Temp\[LC3U)F{0XCAB)LKNIT0K@G.gif)
mlinux
target remote:1234
B sys_execve
B load_elf_binary
B start_thread
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/21/db2007ae39bc76d7c323a8d1d8b63b7c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/21/9da44b6f86d8ea14904434a814a00702.png)
linux首先创建父进程,然后通过调用fork()系统调用创建一个新的进程,然后新的进程调用execve()系统调用执行指定的ELF文件。 主进程继续返回等待新进程执行结束,然后重新等待用户输入命令。execve()系统调用被定义在unistd.h。
对于ELF格式的可执行文件,按照格式要求加载到内存中相应的地址空间,如果是静态链接的就将文件头部标明的入口地址作为开始;如果是依赖动态链接库的可执行文件则需要将动态链接器ld的入口地址作为开始。
相关文章推荐
- linux服务器磁盘坏道的发现及解决全过程
- Linux系统中对SSD硬盘优化的方法
- linux下指定mysql数据库服务器主从同步的配置实例
- CentOS7下安装配置LAMP详细教程
- Linux下动态链接库的创建和使用
- CentOS 自定义安装GitLab
- linux shell 快捷键
- 关于/etc/init.d/rcS not found的解决方法
- linux下加载R包:
- jdk-7u3-linux-i586.tar.gz安装
- Linux 依赖关系的问题
- Linux下只输出文件中未注释掉的部分
- 老男孩Linux运维培训计划书
- 决心书
- Check the available of yum in Linux
- Installing MySQL Server on CentOS
- Linux修复磁盘操作
- Linux C创建守护进程(daemon)及终端相关概念
- 作为一个新人,如何学习嵌入式Linux?
- Linux装载和启动一个可执行程序