Linux内核如何装载和启动一个可执行程序
来源:互联网 发布:在线视频下载软件 编辑:程序博客网 时间:2024/05/22 05:32
“郭孟琦(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
以下都是梦话,感觉是快坚持不住了!
Linux内核如何装载和启动一个可执行程序?
从刚学C语言开始就知道程序 通过 编译 汇编 链接 产生最终生成一个exe可执行文件,但是到底exe是怎么运行的?实际上并没有给出答案。在这里根据计组所学的东西我认为肯定是什么机制修改了ip从而使cpu开始执行程序中的指令。
这周课里我知道了可执行文件实际上也是一种ELF文件,也是具有一定的文件格式,通过readelf和objdump工具可以分析其内部结构。
readelf -h 反映了头信息,这里显示了该程序的入口地址(0x8048d0a)
objdump则反映了section的size和offset,对helloword而言其执行语句都在.text段,当然还有很多很多的段,这里不具体分析了。
有意思的是可以看出入口地址(0x8048d0a)就指向.text段中的内容。
在大致了解了一个可执行程序的本质后,开始正式探究Linux内核如何装载和启动一个可执行程序。
首先linux是通过execve系统调用来执行一个程序的。因此用gdb追踪了sys_execve。具体使用了老师提供的menu。
在代码中首先fork了一个子进程,并且在子进程中调用了execlp来执行helloworld
在sys_execve出设置断点发现执行过程为
do_execve -> do_execve_common -> exec_binprm
在这里开始对elf文件进行解析
search_binary_handler符合寻找文件格式对应的解析模块。
对于ELF格式的可执行文件fmt->load_binary(bprm);执行的应该是load_elf_binary
因此在load_elf_binary处设置断点
追踪发现了
start_thread(regs, elf_entry, bprm->p);
而elf_entry就在前边的
elf_entry = load_elf_interp(&loc->interp_elf_ex, interpreter, &interp_map_addr, load_bias);
或者
elf_entry = loc->elf_ex.e_entry;
赋值,这2句取决于是否有动态链接器。当然在helloworld中是使用了后者,也就是elf文件中的入口地址(0x8048d0a)(应该就是main函数)
这样堆栈sp和ip的变化就都是在
start_thread(regs, elf_entry, bprm->p);
198start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)199{200set_user_gs(regs, 0);201regs->fs= 0;202regs->ds= __USER_DS;203regs->es= __USER_DS;204regs->ss= __USER_DS;205regs->cs= __USER_CS;206regs->ip= new_ip;207regs->sp= new_sp;208regs->flags= X86_EFLAGS_IF;209/*210 * force it to the iret return path by making it look as if there was211 * some work pending.212 */213set_thread_flag(TIF_NOTIFY_RESUME);214}
中发生了变化,用老师的话说就是 蝴蝶已经变成周公了。
返回用户态后新的eip开始执行helloword了。
补充一下新的sp又是谁呢?
根据参数他是bprm->p
实际上bprm是在 do_execve_common()中
分配新的进程地址空间
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
而p
unsigned long p; /* current top of mem */应该是栈底
我对“Linux内核装载和启动一个可执行程序”的理解可以用一个流程图来表示
- Linux内核如何装载和启动一个可执行程序(Linux)
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- 初学《Linux内核如何装载和启动一个可执行程序》
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- 6.Linux内核如何装载和启动一个可执行程序
- 7.Linux内核如何装载和启动一个可执行程序
- Linux内核如何装载和启动一个可执行程序
- java设计模式---装饰模式
- 在iOS开发中关于正向传值的问题
- git的简单使用
- Comparable(java.lang)和Compatator(java.util)接口的区别
- 【C语言】选择排序
- Linux内核如何装载和启动一个可执行程序
- 通过hover修改其他元素
- 第六周项目2-我的数组类
- Redis配置文件详解
- d3d10查看纹理数据全面总结
- Linux系统下查找文件的方法
- 毕业设计
- 《JAVA与模式》之桥梁模式
- fastjson parseobject错序