千家信息网

PostgreSQL VFD机制

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,1、结构体VFD机制中由结构体struct vfd来维护。其中各个成员变量的意义如下表所示:fdvfd实际对应的物理文件文件描述符fdstateFD_DELETE_AT_CLOSE:表示文件在关闭时需
千家信息网最后更新 2026年11月02日PostgreSQL VFD机制

1、结构体

VFD机制中由结构体struct vfd来维护。其中各个成员变量的意义如下表所示:

fd

vfd实际对应的物理文件文件描述符

fdstate

FD_DELETE_AT_CLOSE:表示文件在关闭时需删除

FD_TEMP_FILE_LIMIT:标记临时文件

FD_CLOSE_AT_EOXACT:

这几个都针对临时文件

resowner

owner, for automatic cleanup

nextFree

VFD的free链表,实际上是数组的下标。

lruMoreRecently

VFD的最近最少使用链表,为双向。实际上也是数组的下标

lruLe***ecently

lruLe***ecently为正向,每次插入都插入头部

fileSize

文件大小

fileName

文件名

fileFlags

打开文件时的标签,比如O_CREATE等

fileMode

打开文件时的属性,比如读写权限等

2、初始化

启动时初始化,使用malloc,只在本进程中有效,即每个进程都维护各自的VfdCache而并非共享内存。初始化时只申请第一个数组,并将其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时的流程

1)Open时首先会调用AllocateVfd,从VfdCache数组中找一个空闲的slot,然后返回。该函数流程见AllocateVfd调用。

2)然后会调用ReleaseLruFiles判断是否open了最大限制的fd。如超出限制,则将LRU链表最后一个VFD的fd close掉。

3)open文件,并将该VFD插入到LRU链表。插入LRU的函数Insert详细流程看下面的函数分析。

4)然后对vfdP成员变量进行赋值。

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)每次调用BasicOpenFilePerm open文件前都会调用AllocateVfd从VfdCache中获取一个空闲的vfd。

2)首先会判断free链表中是否为空。初始时刻,SizeVfdCache为1,则会将VfdCache初始化成大小32的数组,并将其通过nextFree串联起来形成free链表,注意该free链表为循环。

3)VfdCache[0]不使用。最开始32个的时候,即第一次扩充后free 链表如下图所示,跳过VfdCache[1],1会返回。也就是说每次取VFD都是 VfdCache[0].nextFree

4)后续再次扩充时,都是翻倍进行扩充

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;

ReleaseLruFiles

1)nfile为open打开的文件数,numAllocatedDescs为fopen打开的文件数,max_safe_fds为操作系统计算得出的值。

2)一旦超出max_safe_fds值,就会调用ReleaseLruFile从LRU链表删除一个,注意删除的是VfdCache[0].lruMoreRecently,即链表的尾部,最近最少使用的。

3)首先将该fd关闭,然后将之置为VFD_CLOSED。调用Delete函数将VFD从LRU链表删除。注意这里只是从LRU链表删除,不会释放回收到free链表,也不会修改vfd数据结构的其他成员变量值。因为后续可能还会用到该物理文件,会重新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;

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链表的形式如下:

Insert一个VFD时:

4、Delete

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

例如删除VfdCache[1]:

5、回收VFD

1)每次调用FileClose时,会回收vfd到free链表。

2)先调用close函数

3)然后将之从LRU链表删除

4)如果是临时文件,还会将临时文件删除

5)调用FreeVfd将vfd回收到free链表

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

FreeVfd

调用函数FreeVfd回收,注意几个成员变量的修改。回收时,将之插入到free链表头部。注意每次取时也从头部取

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


文件 函数 数组 成员 并将 变量 头部 实际 流程 结构 下标 件数 大小 实际上 物理 空闲 进程 限制 机制 最大 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 河南云网互联网络科技有限公司 互联网金融监管科技数据 互联网科技英文 奇酷互联网科技 互联网金融 科技创新 科技伦理 互联网公司 佩信高科技互联网 青岛中康互联网医疗科技有限公司 昭通互联网科技选哪家 阿大互联网科技有限公司 青海科技产业互联网发展 迪庆互联网科技招生 四川慕妮娅互联网科技有限公司 朱啸虎曾投资哪些互联网科技企业 烟台灵鸽互联网科技有限公司 互联网科技接地气 万物互联网智能科技 上海互联网科技园景观 广东猫王互联网科技有限公司电话 科技发展第三阶段互联网时代 互联网科技开发公司 为想互联网科技 融贸通互联网科技 联恩商钥互联网科技有限公司 卫星互联网科技股票 荆州市昕露互联网络科技有限公司 智腾互联网科技有限公司 996高科技互联网公司 国大互联网教育科技有限公司薪资 陕西九四连强互联网科技有限公司
0