(莱昂氏unix源代码分析导读-23) 若干系统调用的实现

来源:互联网 发布:linux expr 编辑:程序博客网 时间:2024/06/05 18:28

           

                                                                                           By cszhao1980

                                                                                                 

System call是提供给user进程的接口,使其可以主动进入内核,完成一些特殊的操作。

 

多数的sys call的实现很简单,莱昂留给大家分析,我在这里多说几句。

首先是35号系统调用——sleep。这个system callsslep()函数处理,它的实现比较简单,

我们唯一需要注意的是,它的参数是通过r0传入的。当user进程要休眠一段时间时,会

调用此函数——其参数为醒来的时间。而sslep会用输入时间同tout[ ]数组内记录的下次叫

醒时间作比较,如果早于tout[ ]则更新tout[ ],然后以tout[ ]数组的首地址为睡眠id,调用

sleep(汇编)例程进入睡眠。

 

显然,所有调用sleep sys call的进程都使用同样的睡眠id,而系统也仅仅记录了第一个要醒来

的时间(即tout数组)。这样,在进行进程唤醒时,所有进程都会醒来。因此,必须在进程醒

来后作一些额外(以确定是否需要再次睡眠)的工作。这样的设计似乎有些低效——莱昂也

提到了这一点。

 

然后是第35sys call——nice,用来设置p_nice值,p_nice会用在setpri()那个古怪的算法里。显然,

用户进程可以通过设置nice来改变自己的优先级,但是根据setpri()的算法来看,其影响是有限的。

 

还有第43sys call——times2955: 1, &times, /* 43 = times */),用来获取与进程相关的6种时间。

 

0447: int u_utime; /* this process user time */

0448: int u_stime; /* this process system time */

0449: int u_cutime[2]; /* sum of childs' utimes */

0450: int u_cstime[2]; /* sum of childs' stimes */

 

这个sys call的实现很简单,但其内部调用了suword0861)——这个汇编小程序指定地址的word拷贝

到前地址空间去,它同莱昂重点分析过的fuword的实现很相似,大家不妨看看,也温习一下莱昂的解析。

 

最后,来几个稍微复杂些的。

sbreak()——用来调整user data segment空间大小,莱昂书中给出了分析。但如果大家看的够仔细的话,可能

会有这样的疑问:

 

3371: if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep))

3372: return;

……

3383: expand(i);

 

(1)         为什么先调用了estabur,而后才调用expand呢?

(2)         为什么可以这样做呢?

 

莱昂在这个问题上保持了自己简洁的风格——对此他仅有短短的一句注释:“3 3 7 1:检查新长

度是否满足对存储段的限制”。莱昂的注释解释了问题1,在他看来问题2不需要回答。

 

如果您觉得难以理解的话,让咱们复习一下estabur ()expand()的用法:

estabur()的主要作用是:

(1)     验证输入三个segment的大小的合法性;

(2)     根据输入的user三个segment的大小,设置各个segmentprotype地址;

(3)     然后,调用sureg()——此函数会根据segmentprotype地址、私有空间首地址

               进行计算,并设置各个user地址register

 

expand()的作用:

(1)     调整data地址空间大小——如果需要新分配空间,则还需要将原有的内

               容拷贝到新空间去,并重新设置进程的私有空间地址;

(2)     调用sureg()设置各个user地址register

 

您一定要注意:protype地址是相对于进程user私有空间的偏移位置。

因此,调用estabur()后会有两个结果:

(1)         正确设置了protype地址;

(2)         (可能)错误设置了user address register

 

但是,其后的expand()调用会修正这一错误——因此,“先调用estabur,而后才调用expand”是可行的。

 

很遗憾,我们现在还不讨论“exec”系统调用,要对它进行分析还需要我们积累更多的知识。

 

博客地址:http://blog.csdn.net/cszhao1980

博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html

 

原创粉丝点击