(莱昂氏unix源代码分析导读-27) Swap in/out (下)

(莱昂氏unix源代码分析导读-27) Swap in/out (上)

                                                     By   cszhao1980

Swap in/out指的是进程在物理内存(core空间)和磁盘交换文件间的双向移动过程,进程在active状态时,

segment必然被swap in内存空间(core空间),而一旦处于非活动状态就有可能swap out到磁盘交换

文件中。换进换出的过程必然涉及到磁盘io——这可看作是比较低层的操作,因此,这部分内容可以分

为两部分:高层的模型和低层的实际io

1 高层模型

Unix使用“swapmap”这个高层模型来记录swap区域,swapmap类似coremap,都是map结构:

2515: struct map

2516: {

2517:    char *m_size;

2518:    char *m_addr;

2519: };

 

区别是:

(1)         swap mapm_size的单位是“磁盘块”,即512个字节;

(2)         swap mapm_addr为“磁盘块号”——而不是内存block号。

 

使用“swapmap”来管理swap空间有一个巨大的好处——同“coremap”一样,对空间资源

的管理可以通过高层函数malloc()free()来实现。

整个swap区域由main函数初始化:

1583: mfree(swapmap, nswap, swplo);

4697: int swplo 4000; /* cannot be zero */

4698: int nswap 872;

 

因此,swap区域即定义为自磁盘第4000块开始,连续872个块。 

在进行换进换出时,必须包括进程的“私有空间”——也被称为“swappable image”,

proc表项里记录了它的地址和大小:

 

0371: int p_addr; /* address ofswappable image*/

0372: int p_size; /* size of swappable image (*64 bytes) */

 

但对可共享的text segment,情况就复杂一些。由于多个进程可以共享同一个text segment,即使进程被换进

或换出也不一定需要相应的换进或换出其text segment。系统定义了text表来帮助进行swap,每个进程都拥

有自己的text表项,而proc表项里的p_textp就指向该该表项。

 

4306: struct text

4307: {

4308:    int x_daddr; /* disk address of segment */

4309:    int x_caddr; /* core address, if loaded */

4310:    int x_size; /* size (*64) */

4311:    int *x_iptr; /* inode of prototype */

4312:    char x_count; /* reference count */

4313:    char x_ccount; /* number of loaded references */

4314: } text[NTEXT];

 

由于text segment是可共享的,因此,text struct中有两个引用计数;

(1)         x_count ——  进程计数,使用该text的进程数量;

(2)         x_ccount ——活动进程计数,使用该text segmentLoaded的进程数量;

 

显然,当“活动进程计数”减至0时,就应该将text segmentcore空间中清除掉——text segment

总是在swap空间中保留副本,故无需被换出;而如果“进程计数”也为0时,磁盘交换文件中

也不该再保留此text segment了。

 

xccdec用来减少“活动进程计数”,显然,当进程换出时,就应该调用此函数,当活动进程计数

减至0时,就应该调用mfree(coremap,…),将text段从core空间中clear掉。

4490: xccdec(xp)

4491: int *xp;

4492: {

4493:    register *rp;

4494:

4495:    if((rp=xp)!=NULL && rp->x_ccount!=0)

4496:        if(--rp->x_ccount == 0)

4497:            mfree(coremap, rp->x_size, rp->x_caddr);

4498: }

 

当进程退出时,应该调用xfree函数,不仅会减少“活动进程计数”,还会减少“进程计数”。

4398: xfree()

4399: {

4400:    register *xp, *ip;

4401:

4402:    if((xp=u.u_procp->p_textp) != NULL) {

4403:       u.u_procp->p_textp = NULL;

4404:       xccdec(xp);

4405:       if(--xp->x_count == 0) {

4406:          ip = xp->x_iptr;

4407:          if((ip->i_mode&ISVTX) == 0) {

4408:             xp->x_iptr = NULL;

4409:             mfree(swapmap, (xp->x_size+7)/8, xp->x_daddr);

4410:             ip->i_flag =& ~ITEXT;

4411:             iput(ip);

4412:          }

4413:       }

4414:     }

4415: }

 

而当进程计数为0后,swap文件空间也会被free掉——为了效率起见,对于经常调用的程序设置了

“黏着位”ISVTX,即使进程计数为0,也会保留在swap空间。

 

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

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