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

概念总结

1.可执行程序是怎么得来的

C代码——预处理——汇编代码——目标代码——可执行文件

可执行文件的格式

 可执行文件最初为A.out格式,后来演化为COFF格式,再后来变成PE(windows系统)和ELF(linux系统)。ELF:executable and linkable format,即可执行可链接格式。

可执行程序的执行环境

  • 命令行参数和shell环境,一般我们执行一个程序的Shell环境,我们的实验直接使用execve系统调用。
    • $ ls -l /usr/bin 列出/usr/bin下的目录信息
    • Shell本身不限制命令行参数的个数, 命令行参数的个数受限于命令自身
      • 例如,int main(int argc, char *argv[])
      • 又如, int main(int argc, char *argv[], char *envp[])
    • Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数
      • int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
      • 库函数exec*都是execve的封装例程

关于几个问题的回答

1.新的可执行程序是从哪里开始执行的?
默认elf文件从0x8048000出开始加载,前面是elf头部信息,大小一般各不相同。实际的入口在0x8048x000(x为不定值),即程序的入口点地址。

2.为什么execve系统调用返回后新的可执行程序能顺利执行?

在创建一个新的用户态堆栈时,实际上是把命令行参数内容和环境变量的内容通过指针传递到系统调用内核处理函数,然后内核处理函数在创建一个新的可执行程序的用户态堆栈时将参数拷贝到户态堆栈,以此来初始化新的可执行程序的上下文环境。先函数调用参数传递,再系统调用参数传递。

命令行参数和环境串都放在用户态堆栈中

execve和fork都是特殊的系统调用,陷入到内核态在返回到用户态继续执行。fork比较特殊,父进程和一般的系统调用一样,子进程从ret_from_fork开始执行返回到用户态。execve陷入到内核态,用加载的新的可执行文件将当前进程的可执行程序覆盖,当其返回时已经不是原来的可执行程序,而是新的可执行程序了。

3.对于静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时会有什么不同?

静态链接方法:#pragma comment(lib, "test.lib") ,静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来
静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库

load_elf_binary中调用了函数start_thread,其中的参数pt_regs就是内核堆栈的栈底
start_thread(regs, elf_entry, bprm->p)
静态链接的elf_entry就是可执行文件的entry,新的程序在返回用户态之前需要修改int 0x80亚茹内核堆栈的eip

动态链接方法:LoadLibrary()/GetProcessAddress()和FreeLibrary(),使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这种方式使程序初始化时间较短,但运行期间的性能比不上静态链接的程序。

时间: 2024-08-12 20:11:41

Linux内核如何装载和启动一个可执行程序的相关文章

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

原文:http://www.cnblogs.com/petede/p/5351696.html 实验七:Linux内核如何装载和启动一个可执行程序 姓名:李冬辉 学号:20133201 注: 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 云课堂笔记: (1)可执行文件的创建 C代码(.c) - 经过编译器预处理,编译成汇编代码(.asm) - 汇编器,生成目标代码(.o) - 链接

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

2015108 李泽源 Linux内核如何装载和启动一个可执行程序 理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节: 编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接,编程练习动态链接库的这两种使用方式,详细内容参考本周第二节: 使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve ,验证您对Linux系统加载可执行程序所需处理过程的理解,详细内容参考本周第三节:推荐在实验楼Linux虚拟机环境下完成实验.

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

原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 题目自拟,内容围绕对Linux内核如何装载和启动一个可执行程序 可以结合实验截图.ELF可执行文件格式.用户态的相关代码等 博客内容中需要仔细分析新可执行程序的执行起点及对应的堆栈状态等 总结部分需要阐明自己对“Linux内核装载和启动一个可执行程序”的理解 实验报告: 理解编译链接的过程和ELF可执行文件格式: C代码——预处理——汇

Linux内核分析:实验七--Linux内核如何装载和启动一个可执行程序

刘畅 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 写在前面 本次实验着力分析Linux内核装载和启动一个可执行程序的过程,其中包括可执行文件格式的分析.可执行文件的装载和链接的过程,并通过GDB跟踪execve系统调用来梳理Linux系统加载可执行程序的过程. 可执行文件的格式分析 相对于其它文件类型,可执行文件可能是一个操作系统中最重要的文件类型,因为它们是完成操作的真正执行者.可

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

李俊锋 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验原理 1.elf可执行文件格式 ELF文件由4部分组成,分别是ELF头(ELF header).程序头表(Program header table).节(Section)和节头表(Section header table).实际上,一个文件中不一定包含全部内容,而且他们的位置也未必如同所示这样安排,只有ELF头的位置

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

理解编译链接的过程和ELF可执行文件格式 编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接 使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve 特别关注新的可执行程序是从哪里开始执行的?为什么execve系统调用返回后新的可执行程序能顺利执行?对于静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时会有什么不同? 参考文献: http://jzhihui.iteye.com/blog/1447570

Linux内核中的信号机制--一个简单的例子【转】

本文转载自:http://blog.csdn.net/ce123_zhouwei/article/details/8562958 Linux内核中的信号机制--一个简单的例子 Author:ce123(http://blog.csdn.NET/ce123) 信号机制是类UNIX系统中的一种重要的进程间通信手段之一.我们经常使用信号来向一个进程发送一个简短的消息.例如:假设我们启动一个进程通过socket读取远程主机发送过来的网络数据包,此时由于网络因素当前主机还没有收到相应的数据,当前进程被设置

《Linux内核分析》 week8作业-Linux加载和启动一个可执行程序

一.ELF文件格式 ELF(Executable and Linking Format)是x86 Linux系统下常用的目标文件格式,有三种主要类型: 适于连接的可重定位文件,可与其他目标文件一起创建可执行文件和共享目标文件. 适于执行的可执行文件,用于提供程序的进程映像,加载的内存执行. 共享目标文件,连接器可将它与其他可重定位文件和共享目标文件连接成其他目标文件. 文件格式 ELF header在文件开始处描述了整个文件的组织,Section提供了目标文件的各项信息,Program head

20135201李辰希 《Linux内核分析》第七周 可执行程序的装载

李辰希  原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 编译链接的过程 1.预处理阶段 gcc -E -o XX.cpp XX.c -m32 XX.cpp是预处理文件 2.编译器生成汇编代码阶段 gcc -x cpp-output -S -o hello.s hello.cpp -m32 XX.s是汇编代码 3.汇编器