写点什么

PostgreSQL 中的虚拟文件描述符

作者:KaiwuDB
  • 2023-06-13
    山东
  • 本文字数:1474 字

    阅读完需:约 5 分钟

PostgreSQL 中的虚拟文件描述符

由于每个操作系统限制了一个进程能打开的文件数(例如:ubuntu 为 1024),因此进程能获得的文件描述符是有限的。对于经常需要打开许多文件的数据库进程来说,很容易会超过操作系统对于文件描述符数量的限制。


为解决这个问题,PostgreSQL 中使用了虚拟文件描述符 (VFD) 机制,通过 VFD 管理真实的文件描述符,帮助进程摆脱操作系统的限制。

typedef struct vfd{  int          fd;  unsigned short fdstate;    ResourceOwner  resowner;  File        nextFree;    File        lruMoreRecently;  File        lruLessRecently;  off_t        fileSize;  char         *fileName;  int          fileFlags;  mode_t        fileMode;} Vfd;
复制代码


VDF 中各字段含义:

  1. fd 记录该 VFD 所对应的真实文件描述符,如果当前 VFD 没有打开文件,则其值为 VFD_CLOSED (-1)。

  2. fdstate 标记位:如 FD_DELETE_AT_CLOSE,表明该文件在关闭时要被删除。

  3. nextFree:指向下一个空闲的 VFD,其数据类型 File 表示其在 VFD 数组中的下标。

  4. lruMoreRecently:指向比该 VFD 最近更常用的虚拟文件描述符。

  5. lnuLessRecently:指向比该 VFD 最近更不常用的虚拟文件描述符。

  6. fileSize:当前文件大小。

  7. fleName:该 VFD 对应文件的文件名,如果是空闲的 VFD 则 fileName 为空。

  8. fileFlags:该文件打开时的标志,包括只读、只写、读写等。

  9. fileMode:文件创建时所指定的模式。

VFD 数组 VfdCache 作为 LRU 池管理文件描述符,并根据需要打开和关闭实际的 OS 文件描述符。LRU 池使用数组实现,数组元素是 VFD 结构体,数组大小会根据需要增长(最大 1024)。

static Vfd *VfdCache;static Size SizeVfdCache = 0;
复制代码



当 LRU 池未满时,进程可以申请一个 VFD 用来打开物理文件;而当 LRU 池已满时,进程需要首先关闭一个 VFD。在 LRU 中,使用替换最长时间未使用 VFD 策略。


进程在 VfdCache 上保持了两个链表,一个是 LRU 池(双向链表),另一个是 FreeList (空闲链表,记录了所有可被分配的 VFD)。前者通过 lruMoreRecently 属性和 lruLessRecently 属性来链接,后者则通过 nextFree 属性来链接。


VfdCache [0] 不是可用的 VFD,它仅用来标识 FreeList 和 LRU 池的链表头部。对 LRU 池里的 VFD 的操作主要包括以下三种:


(1) 将 VFD 插入 LRU 池


打开一个新的 VFD 时,会将该 VFD 对应的物理文件打开,并将该 VFD 插入到 VfdCache[O] 之后的位置。例如,我们要插入的 VFD 为 a,首先要根据 a 中的 fd 字段判断对应的物理文件是否已经打开。如果没有打开则根据 a 中的 fileName 打开此文件,并插入到 LRU 池中。


插入时要将 a 的 lruMoreRecently 指向 VfdCache[0],VfdCache[0] 的 lruLessRecently 指向 a,然后 a 的 lruLessRecently 指向 V1,V1 的 lruMoreRecently 指向 a。


(2) 从 LRU 池删除 VFD


进程使用完一个文件并关闭它时,将该文件的 VFD 从 LRU 池中删除,并将该 VFD 对应的文件关闭掉。例如,我们要对 V2 操作,则首先将 V1 的 lrulessRecently 指向 V3,将 V3 的 lruMoreRecently 指向 V1。 


这样就将 V2 从 LRU 池中删除了,如果 V2 的 fdstate 被置为 FD_DELETE_AT_CLOSE,则要先将 V2 对应的文件删除,再清掉 FD_DELETE_AT_CLOSE 位,接着将 fileSize 置为 0,将 fd 置为 VFD_CLOSED。这样 V2 就变为空闲,最后将其加入到空闲链表中。


(3) 删除 LRU 池尾 VFD


当 LRU 池已满,而此时又要打开新的文件时,就需将池尾的 VFD 删掉,这样新打开的 VFD 就可以插入到 LRU 中。注意,这里被删除的 VFD 仅仅只是从 LRU 池中脱链并关闭其对应的物理文件,VFD 本身并不做其他修改和删除。

用户头像

KaiwuDB

关注

还未添加个人签名 2021-04-29 加入

KaiwuDB 是浪潮集团控股的数据库企业,公司汇聚了全球顶尖的数据库人才,以多模数据库为核心产品,面向工业物联网、数字能源、交通车联网、智慧产业等各大行业领域,提供领先创新的数据服务软件。

评论

发布
暂无评论
PostgreSQL 中的虚拟文件描述符_KaiwuDB_KaiwuDB_InfoQ写作社区