61阅读

linux进程调度浅析-浅析《进学解》

发布时间:2017-10-17 所属栏目:操作系统

一 : 浅析《进学解》

?《进学解》以问答形式抒发不遇之感,是模拟东方朔《答客难》和扬雄《解嘲》的形式,假设了一场师生的对话;《进学解》意谓对增进学问,品行问题的辨析。文章借国子监先生与弟子的对话,抒发了作者长期不受重用,反遭贬斥的不满情绪,也暗寓着韩愈对当时执政者不以才德取人,用人不公不明的讽刺。

《进学解》在结构方面分为“先生训示”、“生徒驳诘”与“先生答问”三个部份。第一部分“先生训示”,大意谓方今圣主贤臣,励精图治,注意选拔和造就人才。故诸生只须在“业”和“行”两方面刻苦努力,便不愁不被录用,无须担忧用人部门的不明不公。作者先提出一个观点:“业精于勤荒于嬉,行成于思毁于随。”对学子提出“业精”“行成”的“进学”标准。这是韩愈对于“学”的问题长期体察、思考所形成的真知灼见,以此勉励弟子进学,希望世人进学。接着称颂政治清明,“方今圣贤相逢,治具毕张”;有司选拔任用公正,选取贤能而去不肖,“拔去凶邪,登崇俊良。占小善者率以录,名一艺者无不庸”;对英才的教化得法,“爬罗剔抉,刮垢磨光”。指出人才可以尽展其能的客观条件已经具备,所以.只怕自己不成才,而不怕有司不明、不公,勉励诸生“进学“。

第二部分“生徒驳诘”,写学生对国子先生所提出的“进学”主张表示怀疑,连用“先生之于儒”;“先生之于文”;“先生之于为人”的三层叠问,指出了先生在“为学”、“于儒”、“为文”及“为人”四方面皆有所成绩,但在政治上还是不免动辄得咎,屡遭贬谪。先生为学非常勤勉,六经诸子无不熟读精研,叙事之文必记其要略,论说之文必究其深义,夜以继日,孜孜不倦;次说先生批判佛、老,力挽狂澜,大有功于儒道;再说先生博取先秦西汉诸家文字之长,故此先生之文章也十分精妙,可以媲美前人;最后说先生敢作敢为,通晓治道,为人处事,可谓有成。这四个方面,一、三相当于“业”,二、四相当于“行”。先生的“业”、“行”均很有成就,却遭际坎坷,则业精行成又有何用呢?通过学生的这些质询,作者含蓄地讽刺身居高位的权贵不辨贤愚,以发泄自己大才小用的牢骚和愤慨。

第三部分“先生答问”,写国子先生回答学生的疑问,进一步申论自己的进学主张。先以工匠、医师为喻,说明工匠使不同才料都能派上各自的用场,做到物尽其用;医师收集不同的药物,用它们治疗不同的疾病,做到药施其宜。以此来说明“宰相之方”在于用人治国,量才录用,贤明公正的人都得选用,。次说孟轲、荀况乃圣人之徒,尚且不遇于世。以孟轲、荀况的不幸遭遇来衬托自己,充满对两位大儒生前遭遇的同情,也包含着对世道的愤慨。最后说若还不知足,不自量力,岂不等于是要求宰相以小材充大用吗?这里说自己“学虽勤而不繇其统”,显然不是韩愈的由衷之言,实际上是反语泄愤。“动而得谤,名亦随之”,是说自己动辄遭受诽谤,而同时却名声益彰。这就更有讽刺意味了。

《进学解》是韩愈写的一篇很有代表性的“不平则鸣”的散文。本文结构严谨,首尾呼应。首段写出进学的主张,次段对进学的意见进行发挥,在末段中加以总结,使全篇成为有机的组合。《进学解》虽然篇幅很短,但内容极为丰富。用对话形式,以自嘲为夸,以反语为讽刺,对当时社会的庸俗腐败,表现了一个有理想的士大夫在黑暗现实中不能妥协的精神。文中通过学生之口,形象地突出了自己学习、捍卫儒道以及从事文章写作的努力与成就,有力地衬托了遭遇的不平;而针锋相对的解释,表面心平气和,字里行间却充满了郁勃的感情,也反映了对社会的批评。用精辟的语句说出了“业精于勤,荒于嬉;行成于思,毁于随”等语,凝聚着作者治学、修德的经验结晶。

二 : 浅析Linux 内核空间和用户空间

    内核空间和用户空间是操作系统理论的基础之一,即内核功能模块运行在内核空间,而应用程序运行在用户空间。(www.61k.com)现代的CPU都具有不同的操作模式,代表不同的级别,不同的级别具有不同的功能,在较低的级别中将禁止某些操作。Linux系统设计时利用了这种硬件特性,使用了两个级别,最高级别和最低级别,内核运行在最高级别(内核态),这个级别可以进行所有操作,而应用程序运行在较低级别(用户态),在这个级别,处理器控制着对硬件的直接访问以及对内存的非授权访问。内核态和用户态有自己的内存映射,即自己的地址空间。

    正是有了不同运行状态的划分,才有了上下文的概念。用户空间的应用程序,如果想要请求系统服务,比如操作一个物理设备,或者映射一段设备空间的地址到用户空间,就必须通过系统调用来(操作系统提供给用户空间的接口函数)实现。如下图所示:

linux 内核 浅析Linux 内核空间和用户空间

    通过系统调用,用户空间的应用程序就会进入内核空间,由内核代表该进程运行于内核空间,这就涉及到上下文的切换,用户空间和内核空间具有不同的地址映射,通用或专用的寄存器组,而用户空间的进程要传递很多变量、参数给内核,内核也要保存用户进程的一些寄存器、变量等,以便系统调用结束后回到用户空间继续执行,所谓的进程上下文,就是一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容,当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。

    同理,硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理,中断上下文就可以理解为硬件传递过来的这些参数和内核需要保存的一些环境,主要是被中断的进程的环境。

    Linux内核工作在进程上下文或者中断上下文。提供系统调用服务的内核代码代表发起系统调用的应用程序运行在进程上下文;另一方面,中断处理程序,异步运行在中断上下文。中断上下文和特定进程无关。

    运行在进程上下文的内核代码是可以被抢占的(Linux2.6支持抢占)。但是一个中断上下文,通常都会始终占有CPU(当然中断可以嵌套,但我们一般不这样做),不可以被打断。正因为如此,运行在中断上下文的代码就要受一些限制,不能做下面的事情:

    1、睡眠或者放弃CPU。

    这样做的后果是灾难性的,因为内核在进入中断之前会关闭进程调度,一旦睡眠或者放弃CPU,这时内核无法调度别的进程来执行,系统就会死掉

    2、尝试获得信号量

    如果获得不到信号量,代码就会睡眠,会产生和上面相同的情况

    3、执行耗时的任务

    中断处理应该尽可能快,因为内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能。

    4、访问用户空间的虚拟地址

    因为中断上下文是和特定进程无关的,它是内核代表硬件运行在内核空间,所以在终端上下文无法访问用户空间的虚拟地址

三 : 详细剖析Linux进程调度时机

Linux在众多进程中是怎么进行调度的,这个牵涉到Linux进程调度时机的概念,由Linux内核中Schedule()的函数来决定是否要进行进程的切换,如果要切换的话,切换到哪个进程等等。

Linux进程调度时机主要有

1、进程状态转换的时刻:进程终止、进程睡眠;

2、当前进程的时间片用完时(current->counter=0);

3、设备驱动程序

4、进程从中断、异常及系统调用返回到用户态时;

时机1,进程要调用sleep()或exit()等函数进行状态转换,这些函数会主动调用调度程序进行进程调度;

时机2,由于进程的时间片是由时钟中断来更新的,因此,这种情况和时机4是一样的。

时机3,当设备驱动程序执行长而重复的任务时,直接调用调度程序。在每次反复循环中,驱动程序都检查need_resched的值,如果必要,则调用调度程序schedule()主动放弃CPU。

时机4,如前所述,不管是从中断、异常还是系统调用返回,最终都调用ret_from_sys_call(),由这个函数进行调度标志的检测,如果必要,则调用调用调度程序。那么,为什么从系统调用返回时要调用调度程序呢?这当然是从效率考虑。从系统调用返回意味着要离开内核态而返回到用户态,而状态的转换要花费一定的时间,因此,在返回到用户态前,系统把在内核态该处理的事全部做完。

对于直接执行调度程序的时机,我们不讨论,因为后面我们将会描述调度程序的工作过程。前面我们讨论了时钟中断,知道了时钟中断的重要作用,下面我们就简单看一下每个时钟中断发生时内核要做的工作,首先对这个最频繁的调度时机有一个大体了解,然后再详细讨论调度程序的具体工作过程。

每个时钟中断(timer interrupt)发生时,由三个函数协同工作,共同完成进程的选择和切换,它们是:schedule()、do_timer()及ret_form_sys_call()。我们先来解释一下这三个函数:

schedule():进程调度函数,由它来完成进程的选择(调度);

do_timer():暂且称之为时钟函数,该函数在时钟中断服务程序中被调用,是时钟中断服务程序的主要组成部分,该函数被调用的频率就是时钟中断的频率即每秒钟100次(简称100赫兹或100Hz);

ret_from_sys_call():系统调用返回函数。当一个系统调用或中断完成时,该函数被调用,用于处理一些收尾工作,例如信号处理、核心任务等等。

这三个函数是如何协调工作的呢?

前面我们看到,时钟中断是一个中断服务程序,它的主要组成部分就是时钟函数do_timer(),由这个函数完成系统时间的更新、进程时间片的更新等工作,更新后的进程时间片counter作为调度的主要依据。

在时钟中断返回时,要调用函数ret_from_sys_call(),前面我们已经讨论过这个函数,在这个函数中有如下几行:

cmpl $0, _need_resched

jne reschedule

……

restore_all:

RESTORE_ALL


reschedule:

call SYMBOL_NAME(schedule)

jmp ret_from_sys_call


这几行的意思很明显:检测 need_resched 标志,如果此标志为非0,那么就转到reschedule处调用调度程序schedule()进行进程的选择。调度程序schedule()会根据具体的标准在运行队列中选择下一个应该运行的进程。当从调度程序返回时,如果发现又有调度标志被设置,则又调用调度程序,直到调度标志为0,这时,从调度程序返回时由RESTORE_ALL恢复被选定进程的环境,返回到被选定进程的用户空间,使之得到运行。

以上就是时钟中断这个最频繁的调度时机。讨论这个的主要目的使读者对时机4有个大致的了解。

最后要说明的是,系统调用返回函数ret_from_sys_call()是从系统调用、异常及中断返回函数通常要调用的函数,但并不是非得调用,对于那些要经常被响应的和要被尽快处理的中断请求信号,为了减少系统开销,处理完成后并不调用 ret_from_sys_call()(因为很显然的,从这些中断处理程序返回到的用户空间肯定是那个被中断的进程,无需重新选择),并且,它们作的工作要尽可能少,因为响应的频率太高了。

Linux进程调度和其他的UNIX进程调度不同,尤其是在“nice level”优先级的处理上,与优先权调度(priority高的进程最先运行)不同,Linux用的是时间片轮转调度(Round Robing),但同时又保证了高优先级的进程运行的既快、时间又长(both sooner and longer)。而标准的UNIX调度程序都用到了多级进程队列。大多数的实现都用到了二级优先队列:一个标准队列和一个实时(“real time”)队列。一般情况下,如果实时队列中的进程未被阻塞,它们都要在标准队列中的进程之前被执行,并且,每个队列中,“nice level”高的进程先被执行。

总体上,Linux 调度序程在交互性方面表现很出色,当然了,这是以牺牲一部分“吞吐量”为代价的。

本文标题:linux进程调度浅析-浅析《进学解》
本文地址: http://www.61k.com/1102973.html

61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1