您好,登錄后才能下訂單哦!
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 | VFD的free鏈表,實(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)限等 |
啟動(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;
1)Open時(shí)首先會(huì)調(diào)用AllocateVfd,從VfdCache數(shù)組中找一個(gè)空閑的slot,然后返回。該函數(shù)流程見AllocateVfd調(diào)用。
2)然后會(huì)調(diào)用ReleaseLruFiles判斷是否open了最大限制的fd。如超出限制,則將LRU鏈表最后一個(gè)VFD的fd close掉。
3)open文件,并將該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;
1)每次調(diào)用BasicOpenFilePerm open文件前都會(huì)調(diào)用AllocateVfd從VfdCache中獲取一個(gè)空閑的vfd。
2)首先會(huì)判斷free鏈表中是否為空。初始時(shí)刻,SizeVfdCache為1,則會(huì)將VfdCache初始化成大小32的數(shù)組,并將其通過nextFree串聯(lián)起來形成free鏈表,注意該free鏈表為循環(huán)。
3)VfdCache[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;
1)nfile為open打開的文件數(shù),numAllocatedDescs為fopen打開的文件數(shù),max_safe_fds為操作系統(tǒng)計(jì)算得出的值。
2)一旦超出max_safe_fds值,就會(huì)調(diào)用ReleaseLruFile從LRU鏈表刪除一個(gè),注意刪除的是VfdCache[0].lruMoreRecently,即鏈表的尾部,最近最少使用的。
3)首先將該fd關(guān)閉,然后將之置為VFD_CLOSED。調(diào)用Delete函數(shù)將VFD從LRU鏈表刪除。注意這里只是從LRU鏈表刪除,不會(huì)釋放回收到free鏈表,也不會(huì)修改vfd數(shù)據(jù)結(jié)構(gòu)的其他成員變量值。因?yàn)楹罄m(xù)可能還會(huì)用到該物理文件,會(huì)重新open并將之重新insert到LRU鏈表。
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;
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鏈表的形式如下:
Insert一個(gè)VFD時(shí):
Delete(file);--> ????vfdP?=?&VfdCache[file]; ????VfdCache[vfdP->lruLe***ecently].lruMoreRecently?=?vfdP->lruMoreRecently; ????VfdCache[vfdP->lruMoreRecently].lruLe***ecently?=?vfdP->lruLe***ecently;
例如刪除VfdCache[1]:
1)每次調(diào)用FileClose時(shí),會(huì)回收vfd到free鏈表。
2)先調(diào)用close函數(shù)
3)然后將之從LRU鏈表刪除
4)如果是臨時(shí)文件,還會(huì)將臨時(shí)文件刪除
5)調(diào)用FreeVfd將vfd回收到free鏈表
FileClose-> ????close(vfdP->fd); ????--nfile; ????vfdP->fd?=?VFD_CLOSED; ????Delete(file); ????... ????FreeVfd(file);
?
調(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;
免責(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)容。