Linux0.12内核分析之十三——进程初探(理论篇)

提起进程,想必你定会有一些认识,教科书式的理论不是我擅长的表达方式,如果你是一个理论者,那么请你去参考相关的书籍,几乎所有的操作系统相关书籍都会有详细的论述。也许你已经对进程的概念有了深刻理解,但是我还是希望你可以阅读下面的文字,我想你多少会有一些收获。

在前面的文章中我们讨论了计算机异常处理的相关概念,解决了系统异常处理的问题,本人也提到执行流的概念在现代操作系统中有着重要的意义,它是进程概念的坚实实现基础,如果没有执行流的概念,那么进程也便不易实现。也许你会反驳说,进程现在已经不是调度的基本单位,线程才是真正的执行单位。你说的很对,但是我还是要告诉你,从进程的角度来说,进程仍旧是执行的进程,只是它会有多个并发(并行,你是否明白并发和并行的区别呢?仔细想想吧)执行流而已(甚至于在Linux的内核中并没有所谓线程的概念,反而Windows却有实实在在的内核线程的概念)。

也许你对于像我这样在使用word编辑文档的同时可以听自己喜欢的音乐并不感到奇怪,二者可以友好地在你的计算机上相处,彼此之间毫不侵犯。但是做到友好相处不是一件容易的事情,尤其是在共享某些资源的时候就更加的困难,毕竟很多人都不是活雷锋,不计个人得失,专门利人。利益均沾平均分配是解决这个问题的好的方法,这个方法对于有限的参与者可以很好的工作,但是对于参与者很多的时候却不是一个好方法。虽然每个参与者都有同等的一份资源,但是单个参与者拥有的资源很少以至于几乎不能做任何有意义的事情。在这个时候就需要合作,把各自拥有资源集中到一起共同使用,每个参与者都有同样的机会使用共同的资源。参与者可以共同推举一个德高望重的人来担当资源管理者的角色,每个人需要使用资源的时候都必须先向管理者提出申请,获得管理者的许可后才可以使用资源。也许有人会说,如果管理者不能做出公平的决断怎么办,这个确实是一个问题,但是我们应该有理由相信德高望重的人会很好的做到公平公正,虽然有时候会有失偏颇。

在现代操作系统中内核就充当了德高望重的管理者的角色,每个需要运行的程序都必须向内核提出申请才能获得运行的权利。人多好办事固然很有道理,但是协调人与人之间的关系确实是一件很有挑战的事情,不是谁都可以胜任的。操作系统内核是一个聪明的管理者,它可以很好解决并发(并行)运行的程序之间的协调问题。它采用的方式很简单,它给每个运行的程序说,你是本系统上唯一运行的程序,你可以做任何我允许你做的事情,在你做完需要的事情之前,你不会受到任何的打扰,好好干活吧,我会尽量提供给你所需的一切资源。真实一个弥天大谎!可是每个运行的程序竟都相信了,并且终其一生都没有发现这是谎言。如果你不想让自己的谎言被揭穿,那么你就不要用谎言去掩盖谎言,这样只会欲盖弥彰,你要做的只是要把谎言变成真实,至少要对方认为这是真实,当然这是一件很困难的事情。

在内核看来,每个程序从开始运行到结束,都是一系列状态间的相互转换。因此,如果内核可以保持每个执行中程序的正确状态转化,那么就可以保证程序看到的和期望的一摸一样,当然程序便会认为内核所说的并非假话,整个系统确实是独占使用的。为了为每个运行的程序保存相应的状态,内核中需要一些数据结构来保存这些状态,这个数据结构就是进程。也许你是一个心急的人,现在就已经跃跃一试,希望马上就来实现进程数据结构。但是我要告诉你,进程是一个复杂的概念,不仅仅是教科书式的文字表述,而是实实在在的“活”的数据结构。对于一个复杂的任务,不要一下子就期望可以做好,我们要循序渐进,一步步踏踏实实地做,那么我们就可以攻破任何坚固的堡垒。心急的时候做事往往会没有条理,最后变成垂头丧气,甚至不了了之,似乎每个人都有过这样的经历。

既然进程保存了程序执行过程中的状态,那么内核到底需要进程具体保存那些东西呢?最直观的就是处理器的状态和内存中的各个变量,保存处理器的状态不是一件困难的事情,毕竟对于程序来说,它们关心的只是处理器中相关寄存器的信息而已,因此需要保存的数据量是固定的。但是对于内存中的变量就不是简单的事情了,我们不可能在进程结构中保存内存的副本,或者将其纳入内核的范围,这样我内核必定会变得臃肿不堪而变得难以管理效率低下,那么我们应该怎么解决呢?做任何事情都不一定要事事躬亲,精诚合作才是正确的处事方法,这样不仅可以让事情有条理还可以让事情更加高效。想一想在前面介绍的键盘处理的情景,内核并不需要直接处理键盘中断,它只是在当你按键时它会唤醒相应的键盘中断处理例程,让它来处理按键输入。同样的进程结构也不需要保存内存中变量的备份或者将其纳入内核,只需要保留相关内存的相关信息即可(“相关”这个词语,使用很是频繁,我也故弄玄虚一次,你明白的,O(∩_∩)O~),具体管理事务可以交给内存管理例程(又是一个新的例程?)来处理,内核只需要保证相关信息的正确性即可。当然,进程不可能仅仅保存处理器和内存的状态,我们的程序还需要和外设交互,这时进程结构就需要保存外设的状态相关信息等等。现在看来进程结构还真是一个复杂的结构,但是你不必害怕,再复杂的事情只要我们持之以恒,有耐心,那么我们便可以理清这复杂的结构。当你走过这段路程,回望时一切都变得容易简单,并且有章可循。

写到这里,我们没有发现执行流在进程中的基础作用,的确,进程结构只是保存了运行中程序的状态信息,但是进程中保存的信息时刻都反映了运行中程序的状态,它是不断变化的,就如同流过的水流一样,进程中保存的状态也是一个动态流动的过程,从程序开始执行开始,到程序的死亡终止,而这个过程就是所谓的执行流。我在这里要说的是执行流不仅仅是指处理器执行代码的过程,还反映了程序执行过程中内存中变量变化过程和外设交互的过程等。

也许你已经明白了进程的概念,进程保存了程序执行过程中的状态,它使得运行过程中的程序认为自己独占了整个系统,同时由于每个运行的程序在内核中都有相应的进程结构来表示其状态信息,并且这些数据结构之间是相互隔离的(由内核维护保证),从而保证了每个运行的程序不知道有其他的程序在运行,除非进程间进行交互通信。最后,举个不一定恰当的例子来说明进程的概念,你应该听过井底之蛙的故事,我们可以认为执行中的程序就是井底的青蛙,进程就是井,而内核就是可以看到井外之物的先知。

又是一段冗长的文字表述,希望你可以容忍我冗长繁杂的表述O(∩_∩)O~。理论上的描述总是没有实践来的实在,后面的实践我们会走的更远,Good Luck!~~~~

你可能感兴趣的:(Linux,0.12实现与分析)