Linux内核学习总结

张瑜
原创作品转载请注明出处
《Linux内核分析》MOOC课  http://mooc.study.163.com/course/USTC-1000029000 

自从上学期学了孟宁老师的网络程序设计的课程,觉得老师翻转课堂,注重实践与理论相结合的教学方式特别棒,这学期又看见孟宁老师的Linux内核课程,毫不犹豫的选了。线上视频课程与实验楼的在线实验,还有线下老师的手把手教学辅导,让我受益匪浅。此课程的收获不只是对Linux内核的学习,对Linux的操作也是加深了熟练,对Linux内核加深了了解。

一、博客目录:

  1. Linux内核分析——简单分析汇编代码
  2. Linux内核分析——操作系统的工作原理
  3. Linux内核分析——跟踪分析Linux内核的启动过程
  4. Linux内核分析——扒开系统调用的三层皮(上)
  5. Linux内核分析——扒开系统调用的三层皮(下)
  6. Linux内核分析——分析Linux内核创建一个新进程的过程
  7. Linux内核分析——Linux内核如何装载和启动一个可执行程序
  8. Linux内核分析——进程的切换和系统的一般执行过程

二:课程内容总结

  1. 简单分析汇编代码
    冯诺依曼体系结构的计算机,又叫存储程序计算机,从硬件的角度来看,其工作模型是CPU依次读取内存中的指令来完成工作。这节课详细介绍了CPU计算模块、寄存器和内存是如何配合工作的。

  2. 基于mykernel的一个简单的时间片轮转多道程序内核代码分析
    mykernel是由老师建立的一个用于开放自己的操作系统的内核平台。
    Linux操作系统的正常工作可以说有三个非常重要的部分,就是我们的存储程序原理、堆栈以及中断的支持。 操作系统对进程的管理主要就是进程的管理和调度,我们为每个进程维护一个进程描述和以及进程间的关系。我们的内核的工作主要有两部分组成,首先运行有一个内核线程,然后就是一些中断处理程序的集合,我们在中断处理程序中要就行进程的调度。Linux操作系统由内核来实现具体工作的,一个进程是通过系统调用fork()函数来创建的,先是将先前CPU正在运行的进程的进程上下文保存在内核态堆栈中,包括有eip,esp,ebp,cs等寄存器的数据;然后加载创建的进程的上下文信息到相应的寄存器中,运行当前新建进程;运行完毕后根据系统的调度继续执行相应的进程。Linux操作系统是多进程的操作系统,不同的进程就是基于以上的方式有操作系统实现调度运行的。同时,操作系统以一种中断的机制实现与用户的交互。操作系统中的IDT描述好各个中断对应的处理程序,当发生相对应的中断时,由硬件来实现中断信号的传递,CPU接收到相应的IRQ信号后,由操作系统如调度进程那样调度相应的处理程序,来完成相应的中断请求,实现与用户的交互。

  3. 使用gdb跟踪Linux内核启动过程
    道生一(start_kernel–>cpu_idle),一生二(kernel_init和kthreadd),二生三(即前面0、1和2三个进程),三生万物(1号进程是所有用户态进程的祖先,2号进程是所有内核线程的祖先)。
    start_kernel()是内核的汇编与C语言的交接点,在该函数以前,内核的代码都是用汇编写的,完成一些最基本的初始化与环境设置工作。start_kernel就像是c代码中的main函数。不管你关注Linux的内核模块,总是离不开start_kernel函数的,因为大部分模块的初始化工作都是在start_kernel中完成的。按照这节课的实验步骤,跟踪Linux内核的启动过程。通过自己编译内核源码,并且调试了启动过程,了解到内核在启动时经历了哪些初始化。内核几乎所有的初始化都是在start_kernel进行的,在start_kernel之前主要是汇编代码完成的一些操作。在start_kernel中会初始化中断向量,内存管理模块,调度模块等一系列初始化。在最后的rest_init()中会初始化0号进程和1号用户态进程,然后最终启动系统。

  4. 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
    系统调用的三层皮:xyz(API)、system_ call(中断向量)、sys_xyz(中断向量对应的中断服务程序)。当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数,在Linux中是通过执行int $0x80来执行系统调用的, 这条汇编指令产生向量为128的编程异常。 中断向量0x80与system_call绑定起来。 系统调用号将xyz和sys_xyz关联起来了。

  5. 分析system_call中断处理过程
    系统调用在内核代码中的工作机制和初始化
    int 0x80——>system call:通过中断向量匹配
    system call——>sys_xyz():通过系统调用号匹配
    一旦执行int 0x80后立刻跳转到system_call执行
    通过gdb我们可以给系统调用内核处里程序如sys_write, sys_time设置断点,并让程序停在断点处,进行断点跟踪系统调用处里过程。由于system_call是完全用汇编写就一个的函数,虽然我们也可以在system_call处设置断点,但却无法让系统停在system_call处,所以也无法通过单步跟踪学习其处里流程。这里写图片描述

  6. 进程的描述和进程的创建
    为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。在Linux应用程序的开发中,可以通过fork、vfork和clone等API来创建一个子进程,它们在Linux内核中对应的系统调用分别为sys_fork、sys_vfork和sys_clone函数,而这些函数最终都会调用do_fork完成子进程的创建。do_fork主要是复制了父进程的task_struct,然后修改必要的信息,从而得到子进程的task_struct。

  7. Linux内核如何装载和启动一个可执行程序
    Linux系统可以通过execve API启动一个新进程,该API又呼叫sys_execve系统调用,负责将新的程序代码和数据替换到新的进程中,打开可执行 文件,载入依赖的库文件,申请新的内存空间,最后执行 start_thread(regs, elf_entry, bprm->p) ,设置 new_ip, new_sp ,完成新进程的代码和数据替换,然后返回,接下来就是执行新的进程代码了。

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

    1). 正在运行的用户态进程X

    2). 发生中断: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).

    3). SAVE_ALL //保存现场,这里是已经进入内核中断处里过程

    4). 中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换

    5). 标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)

    6). restore_all //恢复现场

    7). iret - pop cs:eip/ss:esp/eflags from kernel stack

    8). 继续运行用户态进程Y

三、学习总结

这学期选了Linux课程,对于翻转课堂的混合式教学,我自己受益匪浅,线上课程可以重复观看,观看时间也很灵活,进行思考后跟随实验楼的在线实验进行实验,文档写的特别详细。然后线下还可以找老师进行答疑,解决一些困惑,同时老师也会问一些自己没有想到的问题。还有一个每一周的测试,可以让自己及时的总结和衡量自己一周学习的内容和知识。我的自学能力也得到了提升。
当然,对这门课程我还是有很多做的不够,比如有些问题没有进行很深入的思考,“不求甚解”,同时也有很多函数没有被我追踪到,是一个遗憾。
再次强调,孟宁老师的教学方法特别适合软件工程这种重实践的课程。下半学期我还选了孟宁老师的高级软件工程课程,希望自己能得到进一步提升。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值