1. 程式人生 > >(萊昂氏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空間。