溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PostgreSQL VFD機(jī)制

發(fā)布時(shí)間:2020-06-17 15:38:41 來源:網(wǎng)絡(luò) 閱讀:2074 作者:yzs的專欄 欄目:數(shù)據(jù)庫

1、結(jié)構(gòu)體

VFD機(jī)制中由結(jié)構(gòu)體struct vfd來維護(hù)。其中各個(gè)成員變量的意義如下表所示:

fd

vfd實(shí)際對應(yīng)的物理文件文件描述符

fdstate

FD_DELETE_AT_CLOSE:表示文件在關(guān)閉時(shí)需刪除

FD_TEMP_FILE_LIMIT:標(biāo)記臨時(shí)文件

FD_CLOSE_AT_EOXACT

這幾個(gè)都針對臨時(shí)文件

resowner

owner, for automatic cleanup

nextFree

VFDfree鏈表,實(shí)際上是數(shù)組的下標(biāo)。

lruMoreRecently

VFD的最近最少使用鏈表,為雙向。實(shí)際上也是數(shù)組的下標(biāo)

lruLe***ecently

lruLe***ecently為正向,每次插入都插入頭部

fileSize

文件大小

fileName

文件名

fileFlags

打開文件時(shí)的標(biāo)簽,比如O_CREATE

fileMode

打開文件時(shí)的屬性,比如讀寫權(quán)限等

2、初始化

啟動(dòng)時(shí)初始化,使用malloc,只在本進(jìn)程中有效,即每個(gè)進(jìn)程都維護(hù)各自的VfdCache而并非共享內(nèi)存。初始化時(shí)只申請第一個(gè)數(shù)組,并將其fd置為VFD_CLOSED

PostgresMain->BaseInit->InitFileAccess:
????VfdCache?=?(Vfd?*)?malloc(sizeof(Vfd));
????MemSet((char?*)?&(VfdCache[0]),?0,?sizeof(Vfd));
????VfdCache->fd?=?VFD_CLOSED;
????SizeVfdCache?=?1;

2、open時(shí)的流程

1Open時(shí)首先會(huì)調(diào)用AllocateVfd,從VfdCache數(shù)組中找一個(gè)空閑的slot,然后返回。該函數(shù)流程見AllocateVfd調(diào)用。

2)然后會(huì)調(diào)用ReleaseLruFiles判斷是否open了最大限制的fd。如超出限制,則將LRU鏈表最后一個(gè)VFDfd close掉。

3open文件,并將該VFD插入到LRU鏈表。插入LRU的函數(shù)Insert詳細(xì)流程看下面的函數(shù)分析。

4)然后對vfdP成員變量進(jìn)行賦值。

PathNameOpenFilePerm->
????file?=?AllocateVfd();
????vfdP?=?&VfdCache[file];
????ReleaseLruFiles();
????vfdP->fd?=?BasicOpenFilePerm(fileName,?fileFlags,?fileMode);
????Insert(file);
????vfdP->fileName?=?fnamecopy;
????/*?Saved?flags?are?adjusted?to?be?OK?for?re-opening?file?*/
????vfdP->fileFlags?=?fileFlags?&?~(O_CREAT?|?O_TRUNC?|?O_EXCL);
????vfdP->fileMode?=?fileMode;
????vfdP->fileSize?=?0;
????vfdP->fdstate?=?0x0;
????vfdP->resowner?=?NULL;

AllocateVfd

1)每次調(diào)用BasicOpenFilePerm open文件前都會(huì)調(diào)用AllocateVfdVfdCache中獲取一個(gè)空閑的vfd。

2)首先會(huì)判斷free鏈表中是否為空。初始時(shí)刻,SizeVfdCache1,則會(huì)將VfdCache初始化成大小32的數(shù)組,并將其通過nextFree串聯(lián)起來形成free鏈表,注意該free鏈表為循環(huán)。

3VfdCache[0]不使用。最開始32個(gè)的時(shí)候,即第一次擴(kuò)充后free 鏈表如下圖所示,跳過VfdCache[1],1會(huì)返回。也就是說每次取VFD都是 VfdCache[0].nextFree

4)后續(xù)再次擴(kuò)充時(shí),都是翻倍進(jìn)行擴(kuò)充

AllocateVfd->
????if?(VfdCache[0].nextFree?==?0){
????????Size??newCacheSize?=?SizeVfdCache?*?2;
????????if?(newCacheSize?<?32)
????????????newCacheSize?=?32;
????????newVfdCache?=?(Vfd?*)?realloc(VfdCache,?sizeof(Vfd)?*?newCacheSize);
????????VfdCache?=?newVfdCache;
????????for?(i?=?SizeVfdCache;?i?<?newCacheSize;?i++){
????????????MemSet((char?*)?&(VfdCache[i]),?0,?sizeof(Vfd));
????????????VfdCache[i].nextFree?=?i?+?1;
????????????VfdCache[i].fd?=?VFD_CLOSED;
????????}
????????VfdCache[newCacheSize?-?1].nextFree?=?0;
????????VfdCache[0].nextFree?=?SizeVfdCache;
????????SizeVfdCache?=?newCacheSize;
????}
????file?=?VfdCache[0].nextFree;
????VfdCache[0].nextFree?=?VfdCache[file].nextFree;
????return?file;

PostgreSQL VFD機(jī)制

ReleaseLruFiles

1nfileopen打開的文件數(shù),numAllocatedDescsfopen打開的文件數(shù),max_safe_fds為操作系統(tǒng)計(jì)算得出的值。

2)一旦超出max_safe_fds值,就會(huì)調(diào)用ReleaseLruFileLRU鏈表刪除一個(gè),注意刪除的是VfdCache[0].lruMoreRecently,即鏈表的尾部,最近最少使用的。

3首先將該fd關(guān)閉,然后將之置為VFD_CLOSED。調(diào)用Delete函數(shù)將VFDLRU鏈表刪除。注意這里只是從LRU鏈表刪除,不會(huì)釋放回收到free鏈表,也不會(huì)修改vfd數(shù)據(jù)結(jié)構(gòu)的其他成員變量值。因?yàn)楹罄m(xù)可能還會(huì)用到該物理文件,會(huì)重新open并將之重新insertLRU鏈表。

ReleaseLruFiles->
????while?(nfile?+?numAllocatedDescs?>=?max_safe_fds){
????????if?(!ReleaseLruFile())
???????????break;
????}
ReleaseLruFile->
????LruDelete(VfdCache[0].lruMoreRecently);->
????????vfdP?=?&VfdCache[file];
????????close(vfdP->fd);
????????vfdP->fd?=?VFD_CLOSED;
????????--nfile;
????????Delete(file);-->
????????????vfdP?=?&VfdCache[file];
????????????VfdCache[vfdP->lruLe***ecently].lruMoreRecently?=?vfdP->lruMoreRecently;
????????????VfdCache[vfdP->lruMoreRecently].lruLe***ecently?=?vfdP->lruLe***ecently;

3、Insert

Insert->
????vfdP?=?&VfdCache[file];
????vfdP->lruMoreRecently?=?0;
????vfdP->lruLe***ecently?=?VfdCache[0].lruLe***ecently;
????VfdCache[0].lruLe***ecently?=?file;
????VfdCache[vfdP->lruLe***ecently].lruMoreRecently?=?file;

?

LRU鏈表的形式如下:

PostgreSQL VFD機(jī)制

Insert一個(gè)VFD時(shí):

PostgreSQL VFD機(jī)制

4、Delete

Delete(file);-->
????vfdP?=?&VfdCache[file];
????VfdCache[vfdP->lruLe***ecently].lruMoreRecently?=?vfdP->lruMoreRecently;
????VfdCache[vfdP->lruMoreRecently].lruLe***ecently?=?vfdP->lruLe***ecently;

例如刪除VfdCache[1]

PostgreSQL VFD機(jī)制

5、回收VFD

1)每次調(diào)用FileClose時(shí),會(huì)回收vfdfree鏈表。

2)先調(diào)用close函數(shù)

3)然后將之從LRU鏈表刪除

4)如果是臨時(shí)文件,還會(huì)將臨時(shí)文件刪除

5)調(diào)用FreeVfdvfd回收到free鏈表

FileClose->
????close(vfdP->fd);
????--nfile;
????vfdP->fd?=?VFD_CLOSED;
????Delete(file);
????...
????FreeVfd(file);

?

FreeVfd

調(diào)用函數(shù)FreeVfd回收,注意幾個(gè)成員變量的修改?;厥諘r(shí),將之插入到free鏈表頭部。注意每次取時(shí)也從頭部取

FreeVfd->
????free(vfdP->fileName);//注意fileName需要釋放,他是另malloc的
????vfdP->fileName?=?NULL;
????vfdP->fdstate?=?0x0;
????vfdP->nextFree?=?VfdCache[0].nextFree;
????VfdCache[0].nextFree?=?file;


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI