by cszhao1980
换出时,使用函数xswap(),它有三个参数,前两个参数很容易理解:
(1)p——指向进程表项;
(2)ff—— free flag,如非0,则free core空间;
但第三个参数就难以琢磨了:
(3)os—— old size。
是什么意思呢?既然p->p_size记录了进程swap image的size,这个os又是作什么用的。为了理解这一
点,我们可以查看一下xswap()的调用情况——唯一一次os不为0的情形是在expand()中:
2268: expand(newsize)
2269: {
2270: int i, n;
2271: register *p, a1, a2;
2272:
2273: p = u.u_procp;
2274: n = p->p_size;
2275: p->p_size = newsize;
2282: a2 = malloc(coremap, newsize);
2283: if(a2 == NULL) {
2284: savu(u.u_ssav);
2285: xswap(p, 1, n);
2286: p->p_flag =| SSWAP;
2287: swtch();
2288: /* no return */
2289: }
进程要求增大自己的image size,而p_size已经更新,但分配core空间失败,需要将当前进程
换出到swap file中,而此时仅需要将old size大小的内容换出即可。
需要注意的是,此种情况下,xswap()分配swap空间时,是按照新size分配空间的,但仅写入实际需要的内容。
xswap()函数实现比较简单,内部使用swap()函数进行实际的磁盘io——这个函数可看作低层函数,我们以后
再了解。莱昂对xswap的讲解比较清晰——注意“L O C K”和runout等,都是用来和sched()配合,解除竞争
条件用的。
接下来看一下xalloc(),用来连接到一个shared text segment——这听起来很让人费解。但在开始讲解之前,我
们来看一下text结构中剩下的一个不明变量:
4311: int *x_iptr; /* inode of prototype */
它指向inode struct的一个entry,而inode用于文件系统io,以后会细讲,但在这里需要先剧透一下。
5659: struct inode
5660: {
5661: char i_flag;
5662: char i_count; /* reference count */
5663: int i_dev; /* device where inode resides */
5664: int i_number; /* i number, 1-to-1 with device address */
5665:
5666: int i_mode;
……
5675: } inode[NINODE];
0131: #define NINODE 100 /* number of in core inodes */
inode数组用来记录active file,即每open一个file,就需要在inode数组中找一个表项,记录下该file的信息。
接着我们来看看xcalloc函数的用途——仅用于exec sys call,即执行可执行文件。我们可以大胆的猜测一下,
xalloc的用途就是在open用户可执行文件后,分配并设置text segment用的。带着这样的念头,xcalloc函数
就不难理解了。
首先看看它的参数,函数规格里列出了一个参数“ip”,它指向text segment文件的inode entry,而它还有个隐
式的参数u.u_arg[1],是正文段的长度,单位是字节。
xalloc首先会loop系统的text表,如果有表项的x_iptr与传入的ip相同,证明该text segment已经被某进程
Load进了,可以共享之。此时,只需要增加“进程计数”x_count,并设置进程proc表项的p_textp,使之指
向该text entry即可。
否则,就在text表中找一空表项使用,接下来的处理非常有意思:
(1) 进程计数设置为1,活动进程计数为0
4452: xp->x_count = 1;
4453: xp->x_ccount = 0;
(2) 在swap空间中分配区域以存放text segment的image
4454: xp->x_iptr = ip;
4455: ts = ((u.u_arg[1]+63)>>6) & 01777;
4456: xp->x_size = ts;
4457: if((xp->x_daddr = malloc(swapmap, (ts+7)/8)) == NULL)
4458: panic("out of swap space");
(3) 调用expand和estabur为进程分配正文段
4459: expand(USIZE+ts);
4460: estabur(0, ts, 0, 0);
这两条语句非常有意思,首先,它扩大了进程“私有空间”,按其大小来分析,这是用来放置text segment的。
然后,它调用estabur设置user address寄存器,但按其参数看,会设置data segment,而不是text segment。
接着往下看。
4461: u.u_count = u.u_arg[1];
4462: u.u_offset[1] = 020;
4463: u.u_base = 0;
4464: readi(ip); // readi()函数会将ip指向的内容读入进程的data segment。
4465: rp = u.u_procp;
4466: rp->p_flag =| SLOCK;
4467: swap(xp->x_daddr, rp->p_addr+USIZE, ts, 0);
4468: rp->p_flag =& ~SLOCK;
哈哈,原来如此!
xalloc“借用”data segment的空间来读入text segment的内容,然后将text segment swap out到
swap file中,接下来在4473行,“归还”了data segment:
4469: rp->p_textp = xp;
4470: rp = ip;
4471: rp->i_flag =| ITEXT;
4472: rp->i_count++;
4473: expand(USIZE);
博客地址:http://blog.csdn.net/cszhao1980
博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html