王玮怡 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000html
《Linux内核分析》期末总结算法
姓名:王玮怡 学号:20135116编程
1、博客目录:数据结构
一、第一周学习总结:计算机是如何工做的?框架
二、第二周学习总结:操做系统是如何工做的?函数
三、第三周学习总结:构造一个简单的Linux系统MenuOS学习
四、第四周学习:扒开系统调用的三层皮(上)ui
五、第五周学习总结:扒开系统调用的三层皮(下)spa
六、第六周学习总结:进程的描述和进程的建立操作系统
七、第七周学习总结:可执行程序的装载
八、第八周学习总结:进程的切换和系统的通常执行过程
2、课程总结
一、计算机是如何工做的?
主要介绍一些基础知识,包括汇编语言基础知识、C语言函数调用过程当中的堆栈变化和参数传递过程。
- 存储程序计算机工做模型——冯诺依曼体系结构。
- 程序:告诉计算机操做的步骤、输入的数据、如何存放处理后的结果。
- 汇编语言:汇编语言是机器语言的一种翻译。
二、操做系统是如何工做的?
简单模拟内核代码。主要包括函数调用堆栈、函数堆栈框架、内核的初始化、中断、进程上下文切换过程的简述以及基于时间片轮转的多道程序模拟。
- 操做系统三个法宝:存储程序计算机、函数调用堆栈、中断机制。
- 操做系统两把宝剑:中断上下文、进程上下文的切换。
- 中断:多道程序设计,能够多个程序同时运行,当一个中断发生时,由CPU和内核代码共同实现了保存现场和恢复现场。
- 操做系统核心功能:进程调度和中断机制,经过与硬件的配合实现多任务处理,再加上上层应用软件的支持,最终变成可使用户能够很容易操做的计算机系统。
- 进程切换:当正在运行的进程等待其余的系统资源时,Linux内核将取得CPU的控制权,并将CPU分配给其余正在等待的进程。进程切换机制中包含esp的切换、堆栈的切换。
三、构造一个简单的Linux系统MenuOS
这一周内,咱们学习了阅读内核源码和构造Linux系统MenuOS,主要包括源码主要结构、内核启动及调试方法和start_kernel的解读。咱们总结为:道生一(start_kernel
-->cpu_idle
),一辈子二(kernel_init
和kthreadd
),二生三(即前面0、1和2三个进程),三生万物(1号进程是全部用户态进程的祖先,2号进程是全部内核线程的祖先)
- 内核启动完成进入menu程序,支持三个命令quit、version、help
- ipc和进程通讯相关的目录
四、扒开系统调用的三层皮(上)
关于系统调用的知识。主要包括对系统调用与用户态、内核态的理解、经过编写汇编代码了解系统调用机制。
- Intel x86 CPU有四种不一样的执行级别0-3,Linux只使用了0级和3级分别表示内核态和用户态。
- 0xc0000000以上的逻辑地址空间只能在内核态下访问,0x00000000-0xbfffffff的逻辑地址空间在两种状态下都能访问。
- 中断处理是从用户态进入内核态的主要方式,而系统调用只是一种特殊的中断。
- 中断处理的完整过程:

- 操做系统提供的API(应用编程接口)和系统调用的关系:并不是一一对应
- 系统调用的三层皮:xyz、system_call和sys_xyz

- 在Linux中经过int$0x80来执行系统调用——产生向量为128的编程异常
- 进程须要经过传递一个名为系统调用编号的参数来指明须要哪一个系统调用(经过eax寄存器来实现传递)——系统调用号将xyz和sys_xyz关联起来
- system_call是Linux中全部系统调用的入口点,每一个系统调用至少有一个参数,即由eax传递的系统调用号
五、扒开系统调用的三层皮(下)
本周实验须要咱们添加一个本身编写的系统调用,加深对系统调用在内核代码中的处理过程的理解。
- 第一步,SAVE_ALL保存现场。
- 第二步,肯定中断信息,将系统调用号经过eax传入,经过
sys_call_table
查询到调用的系统调用,而后跳转到相应的程序进行处理。
- 第三步,处理中断。
- 第四步,
RESTORE_ALL
恢复系统调用时的现场,iret返回用户态。
六、进程的描述和进程的建立
这周咱们主要学习了关于进程的描述和建立。主要包括PCB的组织形式、进程的数据结构进程描述符、fork系统调用的关键执行过程。
- 操做系统三大功能:进程管理(核心)、内存管理、文件系统
- PCB task_struct中包含:进程状态、进程打开的文件、进程优先级信息
- 进程控制块PCB——进程描述符task_stuck提供了内核所需了解的进程信息
- 进程的建立:start_kernel ...cpu_idle -->kernel_init和kthreadd -->0、一、2号进程(其中1号进程是全部用户线程的祖先,2号进程是全部内核线程的祖先)
- fork()系统调用:在用户态建立一个子进程,在父进程和子进程中各会返回一次,在子进程中pid的返回值为0,在父进程中的返回值为子进程的pid
- p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令
七、可执行程序的装载
本周咱们学习了关于程序的加载过程和ELF文件格式。主要包括获得一个可执行程序过程、ELF文件格式的结构和静态连接、可执行程序的静态加载过程和动态加载过程。
- 连接器的两个任务:符号解析、重定位
- 目标文件的三种形式:可重定位目标文件(编译器和汇编器可生成)、可执行目标文件(连接器可生成)、共享目标文件(编译器和汇编器可生成)
- 新的可执行程序起点——通常是地址空间为0x8048000或0x8048300
- execve执行静态连接程序时,经过修改内核堆栈中保存的eip的值做为新进程的起点
- 动态链接有两种形式:可执行程序装载时动态链接和运行时动态连接
- 运行时动态装载连接至少须要用到dlopen、dlsym函数
八、进程的切换和系统的通常执行过程
本周咱们主要学习了关于进程切换和总体执行过程。主要包括Linux进程调度算法简介、进程切换代码分析、switch_to理解、进程相关的数据结构简析。
- Linux进程调度是基于分时和优先级的
- Linux中,内核线程是只有内核态没有用户态的特殊进程
- 内核能够看做各类中断处理过程和内核线程的集合
- 用户态进程没法主动调度,只能经过系统调用或其余中断陷入内核的时机进行调度
- Linux中,内核线程能够主动调度,主动调度时不须要中断上下文的切换
- Linux内核调用schedule()函数进行调度,并调用context_switch进行上下文的切换,这个宏调用switch_to来进行关键上下文切换。
- 进程调度的时机——schedule()函数实现调度
3、感想
一、收获
(1)Linux操做系统之前是没有接触过的,经过此次的学习有又学习到新知识,才知道原来在平常生活中也是很常见的。
(2)基本了解了Linux内核的相关结构和设计原理,学会gdb调试及相关代码分析方法。
(3)在每一周互评博客的过程当中,会发现不少好的总结,对个人学习也是一种补充。
二、遗憾
(1)尽管已经学习完了,但仍是以为这门课很难,有些内容仍是没有彻底理解。
(2)经过此次的学习,咱们了解了Linux内核的相关知识,可是想要灵活使用Linux操做系统还须要之后继续努力~