2019-2020-1 20199305《Linux内核原理与分析》第八周作业
2024-09-05 06:41:46
可执行程序的工作原理
(一)ELF目标文件
(1)什么是ELF?
这里先提一个常见的名词“目标文件”,是指编译器生成的文件。ELF(Executable and Linkable Format),即可执行的和可链接的格式,是一个目标文件格式的标准,这种格式的文件用于存储Linux程序。
(2)ELF文件的3种类型
可重定位文件
可执行文件
共享目标文件
(3)ELF文件的作用
如果用于编译和链接,则编译器和链结器将把ELF文件看作节的集合,所有节由节头表描述,程序头表可选
如果用于加载执行(可执行文件),则加载器将把ELF文件看作程序头表描述的段的集合,一个段可能包含又多个节和节头表可选
如果是共享文件,则两者都含有
(二)程序编译
程序从源代码到可执行文件的步骤:预处理、编译、汇编、链接。
预处理
gcc -E hello.c -o hello.i
编译
gcc -S hello.i -o hello.s -m32
汇编
gcc -c hello.s -o hello.o -m32
链接
gcc hello.o -o hello -m32
(三)Linux系统构架与执行过程
(1)从内存角度看Linux系统的执行
(2)fork和execve的区别与联系
fork两次返回,第一次返回到父进程继续向下执行,第二次是子进程返回到ret_from_fork后正常返回用户态
execve在执行时陷入内核态,用execve中加载的程序把当前正在执行的进程覆盖掉,当系统调用返回时也就返回到新的可执行程序起点,即返回的已经不是原来的那个可执行程序了
(3)跟踪分析execve系统调用内核处理函数
1)将menu目录删除,利用git命令克隆一个新的menu目录,用test_exec.c将test.c覆盖
2)重新编译rootfs,查看代码发现增加了exec函数,执行exec指令,发现比fork指令多输出了一行“hello,Yizihan”,实际上是新加载了一个可执行程序来输出一行语句
3)启动内核到调试的状态,加载符号表并设置端口,启动新的终端窗口开始gdb调试,设置断点到“sys_exec” “load_elf_binary” “start_thread”
4)查看hello的elf的头部,查看定义的入口地址
5)实验中test.c中增加的代码如下:
int Exec(int argc, char *argv[])
{
int pid;
/* fork another process */
pid = fork();
if (pid < 0)
{
/* error occurred */
fprintf(stderr,"Fork Failed!");
exit(-1);
}
else if (pid == 0)
{
/* child process */
printf("This is Child Process!\n");
execlp("/hello","hello",NULL);
}
else
{
/* parent process */
printf("This is Parent Process!\n");
/* parent will wait for the child to complete*/
wait(NULL);
printf("Child Complete!\n");
}
}
int main()
{
PrintMenuOS();
SetPrompt("MenuOS>>");
MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
MenuConfig("quit","Quit from MenuOS",Quit);
MenuConfig("time","Show System Time",Time);
MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
MenuConfig("fork","Fork a new process",Fork);
MenuConfig("exec","Execute a program",Exec);
ExecuteMenu();
}
(四)总结
execve()的系统调用实质试运行的内核态的函数,大致处理过程总结如下:
(1)sys_execve中的do_execve()读取128个字节的文件头部,以此判断可执行文件的类型
(2)调用search_binary_handle()去搜索和匹配合适的可执行文件转载处理过程
(3)ELF文件由load_elf_binary()函数负责装载,它调用了sart_thread函数,创建新进程的堆栈,修改了终端现场中保存的ELP寄存器,这里分静态链接和动态链接两种:
静态链接:elf_entry指向可执行文件的头部,一般是main函数,是新程序执行的起点,,新的可执行程序的起点的一般地址为0x8048xxx的位置,由编译器设定,可能是由于安全上的考虑并不严格固定
动态链接:elf_entry指向ld(动态链接器)的起点load_elf_interrp
最新文章
- EF Core 杂记
- iOS BUG: Unbalanced calls to begin/end appearance transitions for <;XXXViewController: 0x7fcea3730650>;.
- 常见的JavaScript函数
- 循序渐进Python3(十一) --6-- &#160;Ajax 实现跨域请求 jsonp 和 cors
- 警告: 程序集绑定日志记录被关闭(IIS7 64位系统)
- 高并发应用中客户端等待、响应时间的推算,及RT/QPS概念辨析
- Android res/目录下子目录详解
- HDU5763 another meaning -(KMP+DP)
- C# 多线程操作样例
- C#的winform小合集
- 用net匹配并替换iOS标准的emoji表情符号
- QtXML 举例
- C++编程技巧(长期更新)
- docker学习笔记(一)—— ubuntu16.04下安装docker
- Python json序列化
- (原创)Spice 网表范例
- 二进制安装mysql
- PHP echo()、print()、print_r()、var_dump()、var_export()的区别
- CGJ02、BD09、西安80、北京54、CGCS2000常用坐标系详解
- java 8中列表对象多条件排序
热门文章
- 第三方OAuth授权登录,QQ、微信(WeChat)、微博、GitHub、码云(Gitee)、淘宝(天猫)、微软(Microsoft )、钉钉、谷歌(Google)、支付宝(AliPay)、StackOverflow
- uploadify没反应
- 简单学习【1】——打包JS
- django基础之day08,ajax结合sweetalert的使用
- 《Java练习题》习题集三
- test-hellow world!
- C++生成完全二叉树
- Winform中实现自定义屏保效果(附代码下载)
- 「SAP技术」SAP VL02N 执行批次拆分报错,说不允许批次拆分?
- 可以设置实体在Dynamics 365高级查找中不显示吗?