SA12226266 王星
起初是没有计算机的,后来,有人觉得必须要有计算机,于是便有了计算机,但是这个计算机是一个人,他会做很多事情,但是必须要有人告诉他要做什么 ,这样的话,虽然有人愿意为你做事情,但是你还是不不能清闲下来,要站在他旁边告诉他下一步该做什么,这样体验太差了。 有人觉得必须要改变,于是就给了那个名叫计算机的人一个口袋(硬盘),聪明的人会将步骤一步步写在一张纸上,放在计算机的口袋里面,这样计算机要做什么事情,就直接从硬盘里面取出来,按照里面的步骤一步步做就好了。这样,这样的计算机进化成了存储程序计算机。
后来,人们发现将所有的命令写在一张纸上是很愚蠢的,这样如果有一个地方出错了,就要找遍一整张纸,然后改正错误,重新写一张没有错误的塞到计算 机的口袋里面。这个过程及其繁琐,于是有更聪明的人把纸分成了一块一块, 每张纸都有名字(函数名/模块名),有可能一张纸上的命令会需要另外一张纸来完成,但是不管怎么样,比以前方便多了。这样写完之后,把这些纸塞给计算机,计算机脑袋笨,只能执行固定的几条命令,当有几张纸片的时候,就会晕头转向。更加聪明的人不忍心这样,于是就找来了一个叫函数调用栈的人帮助计算机,这样计算机只管执行他知道的命令就好了,至于纸片的调用顺序神马的就交给函数调用栈吧。这样看来,函数调用栈会忙的焦头烂额,但是恰恰相反,因为函数调用的特点,他用一个栈来保存ebp和返回地址,就可以处理好函数之间的调用关系,于此同时,为了方便计算机,他也顺带的在栈上面放了与当前执行有关的参数和局部变量,虽然他可以讲这些事情给一个叫堆的人,但是那样的话,就会引发别的问题,而且那是属于函数程序设计方面的知识。不管怎么样,现在存储程序计算机和函数调用栈配合得非常好。他们的努力得到了很多人的肯定,越来越多的人来找他们,他们很忙很忙。后来,有人发现,计算机必须要有多任务处理能力,才不会被累死,这样计算机在很多人 的帮助下进入了多任务处理。。。。。。。。。。
以上是一个比喻,下面是过渡。。。。。。。。。
有了存储程序计算机和函数调用栈之后,计算机现在已经是一个合格的单任务计算机。 但是单任务计算机远远不能达到人类的计算需求,而其在等待IO操作时所浪费的时间更是让人难以忍受,这个时候便出现了中断这个概念。 通过中断,计算机可以实现多任务计算机,同时也将极大地减少计算机在等待输入输出时所浪费的时间。 到此为止,单任务计算机+中断-->多任务计算机,基本上就是我们现在所使用的计算机,当然里面绝不仅仅这么简单。
之前说到了函数调用栈,看到这个,就会想到C语言,同时也想到之前在编译课程上老师所说的: 任何语言编写的程序,最后都可以被表示成C代码执行。当时想了一下,现在再次细细思考,确实如此,由此也想到了,C语言是汇编语言的抽象, 而诸如C++,Java面向对象或者Lisp,Haskell面向函数语言是C语言的抽象,更何况python的解释器还是C语言写的。
继续说说中断的作用。 但是在说中断之前,先说一下进程,因为大部分中断都发生在进程执行期间。 进程是一个程序完整的执行环境。中断发生时,系统会将现在执行的进程的重要的上下文保存在该程序的内核栈上。 此处中的重要的上下文和内核栈便都是该程序的执行环境之一。然而虽然在中断处理过程中使用的是被中断程序的内核栈, 但是该中断处理程序并不属于该进程。
我们可以换一种方法形容中断处理程序:一个进程在办公室里面正在工作,突然有人(中断)来找他麻烦,进程马上就被中断打晕了, 这个时候内核就叫一个小弟(中断处理程序)去那个进程的办公室(进程的内核栈)去解决,小弟三下两下就解决了,叫醒了进程。然后那个进程就像临时性失忆一样,忘记了刚才的中断,继续做以前的事情。
好,中断说完了,再来说说进程调度,进程调度产生的原因很多,时间片用完了,等待IO,等某个信号量。。。。 那么这是个神马过程呢。还是比喻吧。进程A在办公室里面工作,一切很顺利,但是这个时候又有人(还是中断,时间中断,IO中断。。 找他麻烦的人非常多)找他麻烦了(真蛋疼),把他打晕了,他非常蛋疼,不过还好, 内核叫一个小弟去解决,小弟又是很快就解决了,但是这次小弟不走了, 因为他要看看进程A是不是要被调度走,然后他发现很有必要把进程A调度走,换进程B进来,于是进程A并没有被叫醒, 而是被放在别的地方,小弟叫醒了新来的进程B,事情还没有结束,因为进程间有通信, 所以小弟要看看进程B被打晕的过程中有没有给他写信,如果没有,就叫醒进程B, 然后让进程B工作,否则,就叫一个人进来专门处理进程B接收到的消息,处理完了之后,便叫醒进程B, 此时进程B继续工作。
内核非常开心,因为管他们被打晕了多少次,只要办公室里面有人在工作就好了, 小弟真管用,要不然一个进程要是被IO卡住了,就要晕在里面好久。。基本上就是上面这些了。。。
班级聚餐,要去吃饭了。。。
所以在上面例子中,小弟怎么把进程A抬出去和把进程B抬进去的过程,就留给以后写吧,这一个过程与内核代码中的schedule函数有关, 而办公室(进程上下文)的布置与内核代码中的context_switch有关, 而在细节则与宏switch_to(栈的切换)和一个处理硬件级别上的切换代码有关。。
以后再写吧~