Linux内核分析(九)——总结篇
序:写在前面的话
本次内容作为Linux内核的总结内容,主要涉及对Linux系统的总体的一些理解,同时将之前的一些总结贴出来作为大家的一个索引,希望笔者的博客能对和笔者一样的菜鸟有一些帮助和入门的作用。从一个初学者的角度对Linux有一个较为整体的印象,从而加速对Linux操作系统的理解。
一、Linux内核分析系列文章简介及导航
下面就是本系列博客的文章目录,后期还会更加细致的对每个环节进行补充,这一系列【Linux内核分析(一)至(九)】作为系统的入门概览希望大家能够在一个较为总体的层次上对Linux有所了解。下面给出文章的列表供作为目录参考:
涉及内容(函数堆栈、反汇编C程序、AT&T汇编基础讲解、操作系统概述)
本节内容简述了在Linux操作系统中是如何调度各个进程的。实际上我们知道现代的操作系统都是多任务的操作系统。那么这些任务或者说进程之间是采用什么要的机制决定哪个先被执行,哪个后被执行呢?事实上这些就是进程调度所关注的问题。我们知道Linux内核是一个基于分时的调度机制,所以我们也可以简单的理解为同一时刻只有一个进程在CPU中真正的执行着。
涉及内容(mykernel内核中进程的切换源代码分析、进程的数据结构组织、进程的切换过程)
本节介绍了一个基于时间片轮转的建议操作系统内核代码。分析了操作系统中进程之间是如何进行切换的。通过对mykernel的源代码分析,体会进程在切换过程中操作系统对进程运行环境的管理。事实上有时候我们可以把它叫做运行框架,也可以说是上下文,现场环境等等。实际上这些东西指的都是程序运行时候的堆栈,运行内存空间的地址,寄存器值的集合。因为程序运行需要改变他们,而他们中的一些也许会被其他程序运行时改变,所以在切换进程的时候要对所有进程恢复当前状态的系统资源进行保存,这就是切换的核心。
3、
涉及内容(Linux系统的启动分析(start_kernel)、BIOS的结构、操作系统启动的各历史时期简介)
涉及内容(系统调用的基本概念、系统调用的实现、系统调用的过程、内核态、用户态)
本文介绍了如何通过两种方式实现一个系统调用的。一种是通过系统API函数的方式实现,另外一种通过软中断int0x80来实现,通过软中断实现的时候,我们需要在之前先传入中断入口参数,然后中断时候系统就可以知道要执行哪个服务程序。入口参数就是一些必要的标识和系统执行这个功能必要的输入数据。
涉及内容(系统调用的过程详解、用户态内核态的切换)
我们知道操作系统为在用户态运行的进程与硬件设备进行交互提供了一组几口。在应用程序与硬件之间设置一个额外的层实际上是有很多优点的——所谓的系统调用。首先这使得编程更加容易,把用户从学习硬件设备的低级编程特性中解放出来。其次,着极大的提高了系统的安全性,因为内核在试图满足某个请求之前在接口级别上就可以检查这种请求是否是正确的合法的。最后更为重要的是,这些接口是的程序更具有可以执行,因为只要内核所提供的一组接口相同,那么在任意一个内核之上就可以正确的编译和执行我们编写的程序了。Linux系统就是通过内核发出的系统调用(system call)实现了用户态进程和硬件设备之间的大部分接口。最后我们还是以一张图来从很抽象的层次说明这件事情。
涉及内容(进程的创建、fork)
涉及内容(可执行程序的加载、execve)
本节的内容主要讲述了程序在系统中是如何被装载和执行的,另外我们将介绍ELF格式的文件的一些内容,这个文件实际上是用来描述程序一些执行时候被用到的属性,例如他的堆栈信息之类的。然后我们将利用实验的方式跟踪调试一个程序的具体体执行过程,从而更加深入的理解程序在内核中是如何被装载和编译连接执行的。同时介绍一下新可执行程序的执行起点及对应的堆栈状态,以及笔者对其的一些理解。
8、Linux内核分析(八)——进程的调度(切换)
涉及内容(Linux进程切换代码分析、switch_to、进程相关的数据结构简析)
二、课程总结篇
经过两个月的学习,对操作系统的启动、系统功能调用、函数堆栈、进程的创建、切换和可执行程序加载有了较为详细的了解。比较遗憾的是没有进行关于存储管理内容和调度算法的涉及,笔者会在之后的文章中更加详细的阐述Linux系统的各方面内容。(笔者在计算机系统上的目标就是自己写一个内核并把它成功运行在一个嵌入式处理器上,我觉得笔者还有好多需要学习,越学习发现不会的越多╮(╯▽╰)╭)
下面我们来总结一些Linux操作系统的一些内容,首先要明确操作系统主要只做一件事情就是资源管理,包括存储资源和处理资源。
存储资源这一系列我们没有主要涉及,实际上就是对内存和外部存储器比如硬盘的管理。这部分的内容大体上就是一个调度的问题,实际上处理资源也是个调度的问题,所以我们也可以说操作系统就是一个解决资源调度的软件。那么存储资源的调度实际上是由于存储结构分层所导致的。举个简单的例子CPU的缓存(catch)很快但是不大,内存呢比他大但是比他慢一些,一个作业或者程序不可能完全调入catch中,但是运行时候CPU是直接从catch中取数据和指令的,所以有的时候程序的一些执行指令和数据在内存中却不在catch中,这个时候就需要从内存中调出此时用到的数据放入catch,这个调度是基于局部性原理的策略进行的。那么同样的事情也发生在内存和硬盘中间。这就是存储的管理。同时此部分还涉及外存到底如何组织大量的数据(文件结构、磁盘格式等)从而方便人们查找。
处理资源主要我们指的是程序的执行,我们知道程序的一个可执行实例是进程,里面包含了代码可以运行的最基本数据集合。那么从时间的维度上看,操作系统如何加载一个程序就是我们首先需要关心的,Linux中是把这个程序的执行地址的开头作为参数传递给操作系统然后由系统将它启动,系列文章中有涉及。从宏观的角度上看,任务或者说程序被实例化成很多的进程,作为允许多进程同时运行的系统,Linux是如何在进程之间进行切换的呢?实际上我们在文章中有介绍Linux进程创建和切换源代码的分析。这就好比你在做作业,比如你在做数学,用到了计算器,草算纸,做到一半你忽然需要看数学书了,这个时候你要记住你做到哪一个题、计算这个题的一些中间结果在草纸上要标记一下、看完书回来你才可以继续做这道题。进程切换也是这样的一个过程,包括中断处理也是这样的过程,你需要保存你正在做的这件事情的上下文(哪道题、计算的中间结果等等)然后再去做别的,这样保证你回来继续做的时候能够连贯不出错。这里面看出操作系统实际上在处理任务的时候和人有一定的相似性。从微观的角度来看,函数的调用也是上述这个过程,你需要知道怎么回到调用你的函数继续执行。系统调用也同样是这个思路。那么所有的这些保存的信息都是用堆栈完成的。
此外,再就是系统的启动过程和一些调试技巧,我们每篇文章都有实验过程的详述大家可以好好交流一下。那么这一阶段的Linux内核分析初级系列就这样结束了,感谢USTC孟宁老师以及网易云课堂《Linux内核分析》课程,希望有兴趣的同学继续参加下一期的学期。日后笔者也将继续更新这个博客希望能被更多的人看到,给更多的人起到一些学习上的帮助作用。