第九周--期中总结

Linux内核分析期中知识点总结

潘恒   原创做品转载请注明出处  《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000html

学习目录

  • 第一周《计算机是如何工做的?》http://www.cnblogs.com/ppph1995/p/5215374.html
  • 第二周《操做系统是如何工做的?》http://www.cnblogs.com/ppph1995/p/5247287.html
  • 第三周《构建一个简单的操做系统MenuOS》http://www.cnblogs.com/ppph1995/p/5268550.html
  • 第四周 《系统调用的工做机制》http://www.cnblogs.com/ppph1995/p/5284196.html
  • 第五周《扒开操做系统的“三层皮”》http://www.cnblogs.com/ppph1995/p/5324096.html
  • 第六周《进程的描述与建立》http://www.cnblogs.com/ppph1995/p/5351052.html
  • 第七周《可执行程序的装载》http://www.cnblogs.com/ppph1995/p/5361134.html
  • 第八周《进程的切换和系统的通常执行过程》http://www.cnblogs.com/ppph1995/p/5390019.html

计算机是如何工做的

  • 计算机:计算机实现很复杂的功能,计算和处理大量的数据,其实是经过不断地重复大量既定的简单的操做
  • 程序:告诉计算机操做的步骤、输入的数据、如何存放处理后的结果。计算机会尽量忠实地按照程序的顺序将每个操做步骤的指令取出,变成机器语言,经过软硬件协同工做
  • 汇编语言:汇编语言是机器语言的一种翻译。如今编译器功能强大,汇编语言真正用的时候并很少,但可以看懂汇编语句,在分析程序真正执行的流程、单步调试程序的方面都有很大帮助

操做系统是如何工做的

简单模拟内核代码
主要包括:linux

  • 函数调用堆栈
  • 函数堆栈框架
  • 内核的初始化、中断、进程上下文切换过程的简述以及基于时间片轮转的多道程序模拟

操做系统三个法宝:算法

  • 存储程序计算机
  • 函数调用堆栈
  • 中断机制
    操做系统两把宝剑:中断上下文、进程上下文的切换

操做系统核心功能:进程调度和中断机制,经过与硬件的配合实现多任务处理,再加上上层应用软件的支持,最终变成可使用户能够很容易操做的计算机系统
多进程的Linux操做系统:进程必须等到正在运行的进程空闲CPU后才能运行
进程切换:当正在运行的进程等待其余的系统资源时,Linux内核将取得CPU的控制权,并将CPU分配给其余正在等待的进程。进程切换机制中包含esp的切换、堆栈的切换数据结构

构造一个简单的Linux系统MenuOS

生一(start_kernel-->cpu_idle),一辈子二(kernel_init和kthreadd),二生三(即前面0、1和2三个进程),三生万物(1号进程是全部用户态进程的祖先,2号进程是全部内核线程的祖先)

跟踪调试Linux内核的启动框架

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

系统调用:即使是最简单的程序,在进行输入输出等操做时也会须要调用操做系统所提供的服务,也就是系统调用。Linux下的系统调用是经过中断(int 0x80)来实现的函数

传递参数:在执行int 80指令时,寄存器 eax 中存放的是系统调用的功能号,而传给系统调用的参数则必须按顺序放到寄存器 ebx,ecx,edx,esi,edi 中,当系统调用完成以后,返回值能够在寄存器 eax 中得到。Linux 采用的是 C 语言的调用模式,这就意味着全部参数必须以相反的顺序进栈,即最后一个参数先入栈,而第一个参数则最后入栈。
用户态、内核态和中断处理过程
使用库函数API和C代码中嵌入汇编代码触发同一个系统调用
使用库函数API获取系统当前时间
使用C代码中嵌入汇编代码触发系统调用获取系统当前时间学习

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

给MenuOS增长time和time-asm命令
使用gdb跟踪系统调用内核函数sys_time
系统调用在内核代码中的工做机制和初始化spa

系统调用就是特殊的一种中断
系统调用:操作系统

  • SAVE_ALL保存现场。
  • 肯定中断信息,将系统调用号经过eax传入,经过sys_call_table查询到调用的系统调用,而后跳转到相应的程序进行处理。
  • 处理中断。
  • RESTORE_ALL恢复系统调用时的现场,iret返回用户态。

进程的描述和进程的建立

进程的描述:进程描述符task_struct数据结构线程

从系统调用的角度理解fork():一次调用两次返回(fork系统调用在父进程和子进程各返回一次,子进程中返回的是0,父进程中返回值是子进程的pid)

Linux经过复制父进程来建立一个新进程,经过调用do_fork来实现并为每一个新建立的进程动态地分配一个task_struct结构
执行起点与内核堆栈保证一致:设置子进程的ip以前:childregs = current_pt_regs();将父进程的regs参数赋值到子进程的内核堆栈,其中存放了SAVE_ALL中压入栈的参数
新进程的开始:copy_thread()中:p->thread.ip = (unsigned long) ret _from _fork;将子进程的 eip 设置为ret_from _fork的首地址,子进程从ret_from_fork开始执行的

进程的建立:

  • 进程的建立概览及fork一个进程的用户态代码
  • 理解进程建立过程复杂代码的方法
  • 浏览进程建立过程相关的关键代码
  • 建立的新进程是从哪里开始执行的?
  • 使用gdb跟踪建立新进程的过程
    可执行程序的装载
    ------------------

    关于程序的加载过程和ELF文件格式。主要包括获得一个可执行程序过程、ELF文件格式的结构和静态连接、可执行程序的静态加载过程和动态加载过程

    execve执行的时候陷入到内核态,用execve中加载的程序把当前正在执行的程序覆盖掉,当系统调用返回的时候也就返回到新的可执行程序起点
    预处理、编译、连接和目标文件的格式:
  • 可执行程序是怎么得来的
  • 目标文件的格式ELF
  • 静态连接的ELF可执行文件和进程的地址空间
    可执行程序、共享库和动态加载:
  • 装载可执行程序以前的工做
  • 装载时动态连接和运行时动态连接应用举例
    可执行程序的装载:
  • 可执行程序的装载相关关键问题分析
  • sys_execve的内部处理过程
  • 使用gdb跟踪sys_execve内核函数的处理过程
  • 可执行程序的装载与庄生梦蝶的故事
  • 浅析动态连接的可执行程序的装载

进程的切换和系统的通常执行过程

进程切换的关键代码switch_to分析:

  • 进程进度与进程调度的时机分析
  • 进程上下文切换相关代码分析
    Linux系统的通常执行过程:
  • Linux系统的通常执行过程分析
  • Linux系统执行过程当中的几个特殊状况
    进程调度算法:根据分类不一样,调度的设计原则也不一样
    进程的切换:切换地址空间、切换内核堆栈、切换内核控制流程和一些必要的寄存器保存和恢复
    调度时机:内核线程能够直接调用schedule()进行进程切换(主动),也能够在中断处理过程当中进行调度(被动)。用户态进程没法实现主动调度,仅能经过陷入内核态后的某个时机点进行调度,即在中断处理过程当中进行调度
    内核的使用:32位x86系统下,每一个进程的地址空间有4G,用户态0-3G,3G以上仅内核态能够访问。全部进程3G以上是共享的,在内核中代码段,堆栈段都是相同的,回到用户态才不一样。进程进入内核就都同样,没有进程陷入内核就执行0号进程。内核能够看做各类中断处理过程和内核线程的集合

总结:

每周若是静下心来学习总结相应课程的话确实会感到有所收获,但本人以为虽然内容不错,每每看完视频写完做业就不会记忆深入了,仍是要经常复习,多加以实践才能掌握linux内核的真正原理。往后遇到实践复习的机会必定要好好把握,就这半学期的学习来讲仍是掌握的很差,深层次的理解远远不够。

相关文章
相关标签/搜索