(莱昂氏unix源代码分析导读-28) swap in/out (中)

本文详细介绍了Unix系统中xswap函数的作用,特别是在进程内存扩展失败时如何按照旧尺寸换出进程内容。同时,讨论了xalloc函数如何用于连接到共享文本段,特别是执行可执行文件时的文本段分配和设置。文中通过对源代码的分析,揭示了数据结构和内存管理的细节。
摘要由CSDN通过智能技术生成

                                               by cszhao1980

换出时,使用函数xswap(),它有三个参数,前两个参数很容易理解:

1p——指向进程表项;

2ff—— free flag,如非0,则free core空间;

 

但第三个参数就难以琢磨了:

3os—— old size

是什么意思呢?既然p->p_size记录了进程swap imagesize,这个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 segmentimage

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)         调用expandestabur为进程分配正文段

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值