分享
 
 
 

操作系统(UNIX与Linux内核信息输出过程比较)[1]

王朝system·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

操作系统在启动之初,或检测到内部错误时,就需要向控制台输出有关信息。可以想象,这在操作系统中是潜在的常用过程。无论是UNIX,还是Linux,作为操作系统的内核部分,都尤其注意了程序的执行效率。我们所选的过程,它们的魅力,都可以用“清丽”之词言之;清丽之意,乃介乎天生丽质,韵味内涵皆清晰可观。我们细致的来看它们魅力与异同。

Ⅰ. UNIX部分(printf)

在UNIX中,是文件prf.c里的过程printf来完成这项工作的。它调用了其他一些过程,程序如下:

/*UNIX 6 --- prf.c

*我们所选的过程为printf和printn。可对应于莱昂氏原2340至2378行的程序部分。

*/

001 printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc)

002 char fmt[];

003 {

004 register char *s;

005 register *adx, c;

006

007 adx = &x1;

008 loop:

009 while((c = *fmt++) != '%') {

010 if(c == '\0')

011 return;

012 putchar(c);

013 }

014 c = *fmt++;

015 if(c == 'd' || c == 'l' || c == 'o')

016 printn(*adx,c=='o'? 8: 10);

017 if(c == 's') {

018 s = *adx;

019 while(c = *s++)

020 putchar(c);

021 }

022 adx++;

023 goto loop;

024 }

025 /*-------------------------- */

026

027 printn(n, b)

028 {

029 register a;

030

031 if(a = ldiv(n, b))

032 printn(a, b);

033 putchar(lrem(n, b) + '0');

034 }

035 /*-------------------------- */

036

037 /* putchar(c); */

038

对程序做简单说明。首先您注意到,这里c语言是旧时的风格,由printf的参数fmt可看出。还有就是,过程putchar涉及硬件相关的知识,同样,过程ldiv和lrem是汇编语言的过程,我们为简略起见,不再分析相关代码,而只提供如下提示:

对于printn,假设 n = A*b+B,则其中

l A=ldiv(n,b),而且

l B=lrem(n,b),0<=B<b。

过程printf是一种简单而直接的方法,可以方便的向系统控制台终端发送消息。并无缓存,也没有消息的优先级,后面可以看到这和我们所选的Linux的那个过程是不一样的。而且,printf和putchar都在核心态下运行,类似但不同于由C程序调用库函数“printf”和“putchar”,后者其实是在用户态下运行的。

现在您可以回过头去,试着品味一下这段代码。

我们先看过程printf。

007 007 寄存器变量adx记录了第一个参数x1的地址,注意x1占用的是栈单元,编译时不能对此表达

式求值。从008到023,则是一个大循环,关乎我们的全部工作。

009 009 至 013 一个while循环,消息字符串在fmt内,而这里,边输出消息,边检测可有

“%d”、“%l”、“%o”或“%s”出现,分别表明后面的参数里有十进制数、八进制数或字

符串内容需要输出。如果遇到结束符,则返回。

014 014 可以和009里相同的部分对照看。C语言的简练,竟可至此。当在009里,若寄存器变量c取出

字符‘%’时,其后fmt会后移一位,转到014执行。而这里是先取fmt内容,然后后移,则

c可为‘d’、‘l’、‘o’或‘s’了。若fmt中无‘%’出现,则整个字符串被送出后过程

就立刻返回,没有执行014及其后程序的可能,也就没有fmt超界的险情。这是逻辑力量的魅

力。

015 与 016 调用了递归过程printn。后面详细叙述。

017 017 至 021 处理字符串s。整个过程比较清晰,看上去也极易明白。

022 022 adx后移一位。最初adx存储的是谁的地址?第一个参数x1的。后移一位指向哪里?再仔细

一看,其它参数如x2、x3等皆未在程序中用到。您是否有些糊涂了?

C语言程序设计在过程调用和过程说明时,两者之间的参数不进行匹配检查。参数皆按逆序放到栈上,如图:

之所以如此,是因为这个版本的UNIX运行的机器PDP11中栈向下生长,也就是向低地址方向扩展。所以“x1”的地址高于“fmt”,但低于“x2”,其他类推。

这样,adx自增1,其实指向了下一个参数。

023 goto 语句,回至loop处。

下面看printn过程。由提示,您或许能分析出,该过程将一个二进制数按第二个参数b所表示的基数转换成一组数字字符。这里设计了一个小小的算法。

031 和 032 这个递归调用是算法的主题部分。若n = a*b+c,而递归调用,就是

“a(m)=a(m+1)*b+c(m),0<=c(m)<b,

a(0)=n,至a(m+1)==0时开始返回“

的计算过程。

033 033 依次返回,输出数字字符c(m),…,c(0)。数字的算术值,加‘0’可方便的得到对应

的字符值。

这个算法本身较好,又部分采用了汇编代码实现,效率很高了。可是,UNIX的哲学是“尽量使其简化”,使用递归调用使得算法不太明朗,而且于效率也略有损害。不做跟踪,您能明白033行 lrem的第一个参数传n,为什么又输出的是c(m),…,c(0) 吗?如果稍做更改,可能会更好。读者可以尝试。

但这也是白玉微瑕,现在再回头看整个程序,可有新的收获?

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有