(萊昂氏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
2515: struct map
2516: {
2517: char *m_size;
2518: char *m_addr;
2519: };
區別是:
(1) swap map的m_size的單位是“磁碟塊”,即512個位元組;
(2) swap map的m_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表來幫助進行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 segment且Loaded的程序數量;
顯然,當“活動程序計數”減至0時,就應該將text segment從core空間中清除掉——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空間。