2019-2020-1 20199310《Linux内核原理与分析》第八周作业
1.问题描述
在前面的文章中,学习了在Linux系统之中如何创建一个新进程进行追踪,本文将围绕编译链接的过程和ELF可执行文件格式,对Linux内核装载和启动一个可执行程序。
2.解决过程
2.1 ELF文件
(1)可重定位文件:保存代码和适当数据,用来和其他object文件一起创建可执行文件或者共享文件,即.o文件。
(2)可执行文件:保存用来执行的程序,该文件指出了exec(BA_OS)如何来创建程序进程映像。
(3)共享目标文件:共享库,是指可以被可执行文件或其他库文件使用的目标文件,如标准C的库文件libc.so,只有一堆函数可供其他可执行文件调用。
2.2 ELF文件程序编译
程序经过的四个步骤:
预处理:编译器将C程序的头文件编译进来,还有宏的替换,可以用gcc的参数-E来参看。
gcc -E louhao.c -o louhao.i
编译:这个阶段编译器主要做词法分析、语法分析、语义分析等,在检查无错误后后,把代码翻译成汇编语言。可用gcc的参数-S来参看。
gcc -S louhao.i -o louhao.s
汇编:汇编器as将louhao.s 翻译成机器语言保存在louhao.o 中(二进制文本形式)。
gcc -c louhao.s -o louhao.o
链接:链接器负责处理多个.o文件的并入,结果得到louhao文件,它就是一个可执行的目标文件。
gcc louhao.o -o louhao
2.3 静态链接和动态链接
静态链接:在编译时直接将需要的执行代码复制到最终可执行的文件中,优点是代码的装载速度快,执行速度也比较快,对外部环境依赖度低。编译时会把所有需要的代码都链接进去,应用程序相对比较大。缺点是如果多个应用程序使用同一库函数,会被装载多次,浪费内存。
动态链接:在编译时不直接复制可执行代码,而是通过一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统。操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库去执行代码,最终达到运行时链接的目的。优点是多个程序可以共享同一段代码,而不需要在磁盘上存储多个复制。缺点时在运行时加载,可能会影响程序的前期执行性能,而且对库的依赖度极高。
2.4 装载和启动一个可执行程序
将menu目录删除,利用git命令克隆一个新的menu目录,然后用test_exec.c覆盖test.c:
重新编译rootfs:
可以看到test.c中增加了exec函数,执行exec指令,显示如下:
返回LinuxKernel目录,shift+ctrl+o水平分割,用gdb设置断点:
c执行至start_thread断点暂停:
输入exec:
继续执行:
关闭qume,在menu目录下查看hello可执行文件:
给出对exec函数的分析:
int do_execve(struct filename *filename,
const char __user *const __user *__argv,
const char __user *const __user *__envp)
{
return do_execve_common(filename, argv, envp);
}
static int do_execve_common(struct filename *filename,
struct user_arg_ptr argv,
struct user_arg_ptr envp)
{
// 检查进程的数量限制
// 选择最小负载的CPU,以执行新程序
sched_exec();
// 填充 linux_binprm结构体
retval = prepare_binprm(bprm);
// 拷贝文件名、命令行参数、环境变量
retval = copy_strings_kernel(1, &bprm->filename, bprm);
retval = copy_strings(bprm->envc, envp, bprm);
retval = copy_strings(bprm->argc, argv, bprm);
// 调用里面的 search_binary_handler
retval = exec_binprm(bprm);
// exec执行成功
}
static int exec_binprm(struct linux_binprm *bprm)
{
// 扫描formats链表,根据不同的文本格式,选择不同的load函数
ret = search_binary_handler(bprm);
// ...
return ret;
}
3.总结
本文主要学习了编译链接的过程和ELF可执行文件格式,对Linux内核装载和启动一个可执行程序。可执行文件开始执行的起点在修改调用execve系统调用时压入内核堆栈的EIP寄存器的值,此时标志着当前进程的可执行文件已经被完全替换为新的可执行文件,但实际上开始执行可执行文件中的指令还需要等到执行可执行文件中定义的入口地址的位置。如果是静态链接的可执行文件,那么eip指向该elf文件的文件头e_entry所指的入口地址;如果是动态链接,eip指向动态链接器。
2019-2020-1 20199310《Linux内核原理与分析》第八周作业的更多相关文章
- 2019-2020-1 20199329《Linux内核原理与分析》第九周作业
<Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...
- 2019-2020-1 20199329《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...
- 20169212《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...
- 20169210《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业
2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...
- 2017-2018-1 20179215《Linux内核原理与分析》第二周作业
20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...
- 2019-2020-1 20209313《Linux内核原理与分析》第二周作业
2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...
- 2018-2019-1 20189221《Linux内核原理与分析》第一周作业
Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...
- 《Linux内核原理与分析》第一周作业 20189210
实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...
- 2018-2019-1 20189221《Linux内核原理与分析》第二周作业
读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...
随机推荐
- Spring Boot创建一个HelloWorld项目
目录 Spring Boot 简介 微服务框架 以前使用spring开发web的方式 Spring Boot 启动器介绍 如何创建一个helloword的SpringBoot项目 Spring Boo ...
- stm32:extern关键字
参考:http://c.biancheng.net/view/404.html 1.在一个文件中: #include <stdio.h> int max(int x,int y); int ...
- Nagios监控服务
Nagios监控服务 案例1:常用系统监控命令 案例2:搭建nagios监控服务器 案例3:配置文件及插件使用 案例4:监控远程主机的公有数据 案例5:监控远程主机的私有数据 1 案例1:常用系统监控 ...
- php zip打包
zip中加入文件 <?php $zip = new ZipArchive; if ($zip->open('test.zip', ZipArchive::OVERWRITE) === TR ...
- thinkphp后端开发ajax接口开发测试(2)
非常好用的Postman,Google chrome上必备测试ajax接口插件:
- 数据结构和算法(Golang实现)(30)查找算法-2-3-4树和普通红黑树
文章首发于 阅读更友好的GitBook. 2-3-4树和普通红黑树 某些教程不区分普通红黑树和左倾红黑树的区别,直接将左倾红黑树拿来教学,并且称其为红黑树,因为左倾红黑树与普通的红黑树相比,实现起来较 ...
- 从零开始实现放置游戏(十三)——实现战斗挂机(4)添加websocket组件
前两张,我们已经实现了登陆界面和游戏的主界面.不过游戏主界面的数据都是在前端写死的文本,本章我们给game模块添加websocket组件,实现前后端通信,这样,前端的数据就可以从后端动态获取到了. 一 ...
- ssm整合简单例子
1.首先新建一个maven项目 2.在pom.xml文件中加入以下代码引入包 <properties> <project.build.sourceEncoding>UTF-8& ...
- 33 File 文件及目录操作
/* * File:文件和目录路径名的抽象表示形式,File 类的实例是不可变的 * * 构造方法: * File(String pathname) 将指定的路径名转换成一个File对象 * File ...
- Python爬虫系列(三):requests高级耍法
昨天,我们更多的讨论了request的基础API,让我们对它有了基础的认知.学会上一课程,我们已经能写点基本的爬虫了.但是还不够,因为,很多站点是需要登录的,在站点的各个请求之间,是需要保持回话状态的 ...