20135125陈智威

原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

这学期开始学习Linux,刚刚接触,也是不容易的坚持了下来。第一次学习这种网上课堂,形式非常的新颖,图文结合,并且孟老师教授的也很详细,一些概念也说的通俗易懂,这个课程整个学习下来还是受益匪浅。

现在整个网课的学习过程已经结束,按照孟老师的要求写一份关于Linux的总结和报告,有许多不足之处,欢迎大家指正,希望能一起进步。

(一)计算机是如何工作的

  • 总是通过EIP取得下一段要执行的代码,然后执行该段代码,即总是取指执行
  • 当进行函数调用时,堆栈会保存调用函数之前的程序状态,同时堆栈指针bp和sp会在一个伪初始位置
  • 每次函数调用结束,堆栈指针bp和sp回复到调用之前的状态

(二)操作系统是如何工作的

  • 三个法宝——存储程序计算机、函数调用堆栈、中断机制;
  • 在my_schedule函数中,完成进程的切换。进程的切换分两种:

1.下一个进程没有被调度过;
     2.下一个进程被调度过,可以通过下一个进程的state知道其状态。

(三) Linux内核源代码简介

start_kernel()是内核的汇编与C语言的交接点,在该函数以前,内核的代码都是用汇编写的,完成一些最基本的初始化与环境设置工作。start_kernel就像是c代码中的main函数。不管你关注Linux的内核模块,总是离不开start_kernel函数的,因为大部分模块的初始化工作都是在start_kernel中完成的。按照这节课的实验步骤,我们可以跟踪Linux内核的启动过程。

(四) 扒开系统调用的三层皮(上)

  • getpid的函数很简单,就是获取当前进程的进程号

      1.系统调用号放在eax中。
      2.系统调用的参数,按照顺序分别放在ebx、ecx、edx、esi、edi和ebp中
      3.返回值使用eax传递

  • fork函数同样不需要参数,只有输出,
  • fork这个函数有个特点,就是调用一次返回两次,原因在于它复制出了一个子进程,执行同样地代码段。
  • 区分子进程和父进程的手段就是检查返回值。
  • read函数需要三个参数。参数保存在ebx、ecx等寄存器中,这里的三个参数就是放在这三个寄存器中。

(五) 扒开系统调用的三层皮(下)

  • set_system_trap_gate,设置系统陷阱门,即系统调用。
  • 使用gdb跟踪
  • make rootfs:自动编译,生成根文件系统,自动启动.
  • (gdb)list 查看代码.
  • (gdb)s 单步调试进入函数体.
  • (gdb)n 单步调试不进入函数体.
  • 给MenuOS增加time和time-asm命令、添加了fork

(六) 进程的描述和进程的创建

  • Linux中一般进程都是由现有的一个进程创建的,也就是我们所说的父进程
  • 具体的创建是通过fork()实现的
  • fork()的大体工作过程:
  1. 在内存中申请一页内存存放进程控制块task_struct,并返回进程号nr,并在task数组的nr处存放task_struct的指针,还要将task的当前指针current指到nr处;
  2. 将父进程的task_struct的内容复制到新进程的task_struct中作为模版
  3. 对task_struct中的信息进行修改,主要进行一下工作:设置父进程、清除信号位图、时间片、运行时间、根据当前环境设置tss(内核态指针esp0指向task_struct所在页的顶端)、设置LDT的选择子等(根据nr指向GDT中相应的ldt描述符)。
  4. 设置新进程的代码段、数据段的基地址和段长:更新task_struct中的代码开始地址:进程号(nr)×64M,更新task_struct中局部描述符表中的代码段和数据段描述符。
  5. 复制父进程的页表目录项和页表:在页目录表中,复制父进程的页表目录项,目的地址由新进程的线性地址计算出来;对每个对应的页表目录项申请一个空闲页,并用页表地址更新页表目录项,最后将父进程页表中各项复制到新进程对应的页表中,也就是说,这个时候,子进程与父进程共享物理内存。
  6. 更新task_struct中的文件信息:文件打开次数加1,父进程的当前目录引用数加1。
  7. 设置TSS和LDT描述符项:在全局描述符表(GDT)中设置新任务的TSS描述符项和LDT段的描述符项,使TSS描述符项和LDT描述符项分别指向task_struct的TSS结构和LDT结构。
  • 将任务设置为就绪状态,向当前进程(父进程)返回新进程号。​
  • fork()中,内核并不立刻为新进程分配代码和数据物理内存页,新进程与父进程共同使用父进程已有的代码和数据物理内存页面。只有当以后执行过程中由一个进程一写方式访问内存时候被访问的内存页面才会在写操作之前被复制到新申请的内存页面中。
  • 另外在fork的最后是将任务设置成了就绪状态,由于fork()是一个系统调用,在系统调用部分system_call.s,可以看到在系统函数返回后,会调用调度函数schedule(),在schedule()中,就会检测到新进程的就绪状态,并用switch_to()切换到新进程进行执行。

(七) 可执行程序的装载

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

1.创建新进程
     2.新进程调用execve()系统调用执行指定的ELF文件
     3.调用内核的入口函数sys_execve(),sys_execve()服务例程修改当前进程的执行上下文;
    (以上系统调用终止后,新进程开始执行放在可执行文件中的代码。)

  • 当ELF被load_elf_binary()装载完成后,函数返回至do_execve()在返回至sys_execve()。ELF可执行文件的入口点取决于程序的链接方式:

1.静态链接:elf_entry就是指向可执行文件里边规定的那个头部,即main函数处。
     2.动态链接:可执行文件是需要依赖其它动态链接库,elf_entry就是指向动态链接器的起点。

(八) 进程的切换和系统的一般执行过程

Linux系统的一般执行过程,最一般的情况是:正在运行的用户态进程X切换到运行用户态进程Y的过程要经过以下步骤

  • 正在运行的用户态进程X
  • 发生中断:save cs:eip/esp/eflags(current) to kernel stack, then load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).
  • SAVE_ALL //保存现场,这里是已经进入内核中断处里过程
  • 中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换
  • 标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)
  • restore_all //恢复现场
  • iret - pop cs:eip/ss:esp/eflags from kernel stack
  • 继续运行用户态进程Y

Linux内核分析学习总结的更多相关文章

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

    #linux内核分析学习笔记 --第八章 进程的切换和系统的一般执行过程 学习目标:重点关注进程切换的过程,进程调度的时机,操作系统的基本构成以及一般的执行过程. 进程调度的时机 因为进程的调度只发生 ...

  2. 2018-2019-1 20189206 《Linux内核原理与分析》第八周作业

    #linux内核分析学习笔记 --第七章 可执行程序工作原理 学习目标:了解一个可执行程序是如何作为一个进程工作的. ELF文件 目标文件:是指由汇编产生的(*.o)文件和可执行文件. 即 可执行或可 ...

  3. 2018-2019-1 20189206 《Linux内核原理与分析》第七周作业

    linux内核分析学习笔记 --第六章 进程的描述和进程的创建 学习重点--子进程的创建以及运行流程 进程描述和进程的创建 操作系统的三大功能--进程管理.内存管理和文件系统. 在linux内核中利用 ...

  4. 2018-2019-1 20189206 《Linux内核原理与分析》第六周作业

    linux内核分析学习笔记 --第五章 系统调用的三层机制 学习重点--深入理解系统调用的过程 给MenuOS添加命令 添加命令的方式较为简单,在LinuxKernel/menu/test.c目录下, ...

  5. 2018-2019-1 20189206 《Linux内核原理与分析》第五周作业

    linux内核分析学习笔记 --第四章 系统调用的三层机制 学习重点--系统调用 用户态.内核态和中断 Intel x86 CPU有四种不同的执行级别,分别是0,1,2,3其中数字越小,特权越高. L ...

  6. 2018-2019-1 20189206 《Linux内核原理与分析》第四周作业

    linux内核分析学习笔记 --第三章 MenuOS的构造 计算机的"三大法宝"和操作系统的"两把宝剑" 三大法宝 程序存储计算机 即冯诺依曼体系结构,基本上是 ...

  7. 2018-2019-1 20189206 《Linux内核原理与分析》第三周作业

    linux内核分析学习笔记 --第二章 操作系统是如何工作的 计算机的"三大法宝" 程序存储计算机 即冯诺依曼体系结构,基本上是所有计算机的基础性的逻辑框架 函数调用堆栈 高级语言 ...

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

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

  9. 20169211《Linux内核原理与分析》课程总结

    第一周作业:linux入门学习:熟悉操作linux的基础命令 第二周作业:实验反汇编一个简答的C程序,学习汇编代码的工作过程 第三周作业:学习linux内核的启动过程 第四周作业:学习linux内核进 ...

随机推荐

  1. eclipse: The superclass "javax.servlet.http.HttpServlet" was not found 解决方案

    解决步骤: 1. 安装Tomcat8.5 Server 2. eclipse 新建Tomcat 8.5 Server 3. 配置build path 添加  Server Runtime 1.右键项目 ...

  2. reqwest请求api和约束(转载)

    转自:https://www.oschina.net/p/reqwest reqwest 用于浏览器异步HTTP请求.支持xmlHttpRequest, JSONP, CORS, 和 CommonJS ...

  3. C4.5,CART,randomforest的实践

    #################################Weka-J48(C4.5)################################# ################### ...

  4. JAV07接口与继承之动手动脑问题解决

    动手动脑:请自行编写代码测试以下特性:在子类中,若要调用父类中被覆盖的方法,可以使用super关键字. 1.源代码: package Work; class A{ public A(){ System ...

  5. WordPress登陆页和后台面空白解决方法

    真没想到我居然也会碰到这么蛋疼的事情,有一天我登陆博客,输入账号密码之后登陆没有反应,之后我就试着用首页前台登陆(因为这个模板前台带登陆功能),之后成功登陆进入后台更新文章.我想算了.这小毛病就丢那吧 ...

  6. synchronized和ReentrantLock

    一.什么是sychronized sychronized是java中最基本同步互斥的手段,可以修饰代码块,方法,类. 在修饰代码块的时候需要一个reference对象作为锁的对象. 在修饰方法的时候默 ...

  7. SpringMVC流程

    Spring工作流程描述 1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获: 2. DispatcherServlet对请求URL进行解析 ...

  8. Objective-C( Foundation框架 一 NSDictionary (NSMutaleDictionary))

    NSDictionary 不可变的字典 创建字典的方法 // 创建字典的方式 NSDictionary *dy = [NSDictionary dictionaryWithObject:@" ...

  9. Tableau10.0学习随记-分组问题

    1.根据官网的练习视频,分组时可多选列,之后使用回形针按钮创建分组,并重新命名即可,截图如下: 2.但在Tableau10中打开练习工作簿练习时,并没有直接显示分组后结果,仅仅是创建了分组的纬度,结果 ...

  10. phpize建立php扩展 Cannot find config.m4

    centos  php  安装 memcache 扩展的时候   爆 Cannot find config.m4 错误 解决方案参考以下文章 参考文章 http://blog.csdn.net/wgl ...