第一部分:实验

首先还是网易云课堂的学习,这次的课程是可执行程序的装载。

预处理、编译和链接:

可执行程序是怎么来的

以c语言代码为例的话,经过预处理,编译成汇编代码,再汇编成目标码再链接可执行文件。



过程如图所示,.c用gcc编译成汇编代码.asm,然后再汇编成目标码.o再ld链接成可执行文件。

以helloworld为例,处理过程如下所示

  1. vi hello.c
  2. gcc -E -o hello.cpp hello.c -m32 //对.c文件预处理,hello.cpp是预处理的中间文件,预处理负责把include的文件包含进来及宏替换等工作
  3. vi hello.cpp
  4. gcc -x cpp-output -S -o hello.s hello.cpp -m32 //编译成汇编代码.s
  5. vi hello.s
  6. gcc -x assembler -c hello.s -o hello.o -m32 //汇编成目标代码.o是二进制的文件
  7. vi hello.o
  8. gcc -o hello hello.o -m32 //链接成可执行文件
  9. vi hello
  10. gcc -o hello.static hello.o -m32 -static //hello就是可执行文件,也是二进制的,hello.o和hello都是ELF格式的文件,这样编译出来的可执行文件使用的
  11. //是共享库,加上-static就是静态编译,就是把所有的程序依赖的东西都放到程序内部
使用gdb跟踪sys_execve内核函数的处理过程:

首先是搭载环境,在实验楼中做实验,用test_exec.c覆盖test.c的内容,但是无法克隆,所以只能将test.c的内容修改成test_exec.c的内容,修改部分代码如下

  1. #include <time.h>
  2. #include <unistd.h>
  3. int Time(int argc, char *argv[])
  4. {
  5. time_t tt;
  6. struct tm *t;
  7. tt = time(NULL);
  8. t = localtime(&tt);
  9. printf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
  10. return 0;
  11. }
  12. int TimeAsm(int argc, char *argv[])
  13. {
  14. time_t tt;
  15. struct tm *t;
  16. asm volatile(
  17. "mov $0,%%ebx\n\t"
  18. "mov $0xd,%%eax\n\t"
  19. "int $0x80\n\t"
  20. "mov %%eax,%0\n\t"
  21. : "=m" (tt)
  22. );
  23. t = localtime(&tt);
  24. printf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
  25. return 0;
  26. }
  27. int Fork(int argc, char *argv[])
  28. {
  29. int pid;
  30. /* fork another process */
  31. pid = fork();
  32. if (pid < 0)
  33. {
  34. /* error occurred */
  35. fprintf(stderr,"Fork Failed!");
  36. exit(-1);
  37. }
  38. else if (pid == 0)
  39. {
  40. /* child process */
  41. printf("This is Child Process!\n");
  42. }
  43. else
  44. {
  45. /* parent process */
  46. printf("This is Parent Process!\n");
  47. /* parent will wait for the child to complete*/
  48. wait(NULL);
  49. printf("Child Complete!\n");
  50. }
  51. }
  52. int Exec(int argc, char *argv[])
  53. {
  54. int pid;
  55. /* fork another process */
  56. pid = fork();
  57. if (pid < 0)
  58. {
  59. /* error occurred */
  60. fprintf(stderr,"Fork Failed!");
  61. exit(-1);
  62. }
  63. else if (pid == 0)
  64. {
  65. /* child process */
  66. printf("This is Child Process!\n");
  67. execlp("/hello","hello",NULL);
  68. }
  69. else
  70. {
  71. /* parent process */
  72. printf("This is Parent Process!\n");
  73. /* parent will wait for the child to complete*/
  74. wait(NULL);
  75. printf("Child Complete!\n");
  76. }
  77. }
  78. MenuConfig("time","Show System Time",Time);
  79. MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
  80. MenuConfig("fork","Fork a new process",Fork);
  81. MenuConfig("exec","Execute a program",Exec);

对于Exec()函数跟fork()的代码是类似的,只是在子进程里面增加了execlp(),启动的是hello,就是写的hello world。

接着是创建hello.c文件,如下图所示

menu中的Makefile也有修改的内容,如下图所示



用静态编译的方式编译了hello.c,然后在生成根文件系统时把init和hello都放到rootfs.img里面了,这样在执行exec时就可以自动加载hello这个可执行文件。

程序的执行结果如下



我们可以看到exec命令,执行exec发现比fork命令多了的hello world,实际上这个hello world是执行新加载的程序输出的。

接下来就是使用gdb跟踪。使用-S和-s,命令如下

  1. qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

接下来就是使用gdb设置断点跟踪,设置的断点如下图所示



连续输入三个c启动MenuOS,如下图所示



在MenuOS中输入exec命令就会停在断点sys_execve处,如下图所示





输入c继续执行,停在了第二个断点处,list查看函数,如下图所示



输入c继续执行,来到stard_thread,如下图所示



使用po new_ip查看new_ip的指向,



其实new_ip是返回到用户态的第一条指令的地址。



我们可以看到new_ip的地址就是入口地址。

输入s进入到内部



我们可以看到在修改内核堆栈的位置,把regs_ip修改成hello的起点,这样再返回用户态时就有了新的执行环境。

第二部分:教材

虚拟文件系统中(VFS)有四个主要的对象类型
  • 超级块对象:代表一个具体的已安装文件系统;
  • 索引节点对象:代表一个具体文件;
  • 目录项对象:代表一个目录项,是路径的一个组成部分;
  • 文件对象:代表由进程打开的文件

扇区是设备的最小寻址单元,块是文件的最小寻址单元。

四种I/O调度程序:
  • Linus电梯。能执行合并与排序预处理;
  • 最终期限I/O调度程序。为解决请求饥饿问题;
  • 完全公正的排队I/O调度程序。以时间片轮转调度队列;
  • 空操作的I/O调度程序。专为随机访问设备而设计的。

20169210《Linux内核原理与分析》第九周作业的更多相关文章

  1. 2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    2019-2020-1 20199303第二周作业 1.汇编与寄存器的学习 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中 ...

  2. 20169219 linux内核原理与分析第二周作业

    "linux内核分析"的第一讲主要讲了计算机的体系结构,和各寄存器之间对数据的处理过程. 通用寄存器 AX:累加器 BX:基地址寄存器 CX:计数寄存器 DX:数据寄存器 BP:堆 ...

  3. 2019-2020-1 20199314 <Linux内核原理与分析>第二周作业

    1.基础学习内容 1.1 冯诺依曼体系结构 计算机由控制器.运算器.存储器.输入设备.输出设备五部分组成. 1.1.1 冯诺依曼计算机特点 (1)采用存储程序方式,指令和数据不加区别混合存储在同一个存 ...

  4. Linux内核原理与分析-第一周作业

    本科期间,学校开设过linux相关的课程,当时的学习方式主要以课堂听授为主.虽然老师也提供了相关的学习教材跟参考材料,但是整体学下来感觉收获并不是太大,现在回想起来,主要还是由于自己课下没有及时动手实 ...

  5. 2019-2020-1 20199314 <Linux内核原理与分析>第一周作业

    前言 本周对实验楼的Linux基础入门进行了学习,目前学习到实验九完成到挑战二. 学习和实验内容 快速学习了Linux系统的发展历程及其简介,学习了下的变量.用户权限管理.文件打包及压缩.常用命令的和 ...

  6. Linux内核原理与分析-第二周作业

    写之前回看了一遍秒速五厘米:如果

  7. 2020-2021-1 20209307 《Linux内核原理与分析》第九周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第九周作业> 这个作业的目标 & ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  10. 2019-2020-1 20199329《Linux内核原理与分析》第九周作业

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

随机推荐

  1. Python开发之--前端 HTML基础

    一:HTML介绍 HTML:超文本标记语言,标准通用标记语言下的一个应用.包括"头"部分(英语:Head).和"主体"部分(英语:Body),其中"头 ...

  2. Java 单链表的倒置

    在面试,笔试的过程中经常会遇到面试官问这种问题,实现单链表的倒置方法.现在对单链表的倒置犯法做个记录,方便自己以后查看. 单链表的定义: public class Node { int v; Node ...

  3. C# 实现繁体字和简体字之间的转换

    今天收到一个需求,将一组简体的汉字转换成繁体的汉字,刚开始有点茫然,后来在网上搜了一下思路,结果很少有涉及,终于我在看了MSDN后找到了如何解决,可能这方面对一些高程来说很Easy,但是除了高程还有很 ...

  4. ARM GCC 内嵌汇编手册

    转自:http://blogold.chinaunix.net/u2/69404/showart_1922655.html ARM GCC 内嵌(inline)汇编手册 关于这篇文档这篇文章是本人为方 ...

  5. Tomcat基础教程(四)

    一.将Web应用部署到Tomcat中 为什么要部署?将Web应用部署到Tomcat中,那么Tomcat就能找到相应的Web应用,当Tomcat启动时就会加载和初始化Web应用,而在Tomcat启动后, ...

  6. C++引用之引用的使用

    一旦一个引用被声明,则该引用名就只能作为目标变量名的一个别名来使用,所以,不能再把该引用名作为其他变量名的别名,任何对该引用的赋值就是对该引用对应的目标变量名的赋值. 对引用求地址就是对目标变量求地址 ...

  7. 【C#】动态加载dll程序集

    原文:http://www.cnblogs.com/bomo/archive/2013/03/01/2938165.html 很多时候我们需要用到引用其他程序集,有些程序集是.Net生成的,可以支持反 ...

  8. 李洪强iOS开发Swift篇—08_函数(2)

    李洪强iOS开发Swift篇—08_函数(2) 一.函数类型 函数类型也是数据类型的一种,它由形参类型和返回值类型组成,格式是 (形参类型列表) -> 返回值类型 1 func sum(num1 ...

  9. Learning WCF Chapter2 WCF Contracts and Serialization

    So far I’ve talked about the standards behind it all,but in fact WCF hides most of this from the dev ...

  10. bzoj2434

    利用了bzoj3172提到的性质,x串在y串中的出现的次数即为在fail树上以x结尾节点为根的子树中有多少个节点在y串上所以很明显我们要离线解决,我们先把询问按y分类存起来然后我们顺着操作顺序来,出现 ...