PostgreSQL在VFD管理上是一套还是多套
VFD是为了解决文件句柄的限制,防止把OS级别的文件句柄用光。
原来我认为VFD是各个进程间共有的。但是根据观察,发现每一个进程都拥有自己的VFD数组指针。
看看下面两段加了调试信息后的代码:
InitFileAccess:
从 VfdCache = (Vfd *) malloc(sizeof(Vfd)) 基本可以断定,没有使用共享内存方式
/* * InitFileAccess --- initialize this module during backend startup * * This is called during either normal or standalone backend start. * It is *not* called in the postmaster. */ void InitFileAccess(void) { fprintf(stderr,"In %s ...by Process %d\n", __FUNCTION__,getpid()); fprintf(stderr,"----------------------------------------------------\n\n"); Assert(SizeVfdCache == 0); /* call me only once */ /* initialize cache header entry */ VfdCache = (Vfd *) malloc(sizeof(Vfd)); if (VfdCache == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd)); VfdCache->fd = VFD_CLOSED; SizeVfdCache = 1; /* register proc-exit hook to ensure temp files are dropped at exit */ on_proc_exit(AtProcExit_Files, 0); }
AllocateVfd:
会因为扩充内存结构数组的需要,进行 realloc,这导致 VfdCache指针的值会在进程的范畴里发生变化。
static File AllocateVfd(void) { Index i; File file; DO_DB(elog(LOG, "AllocateVfd. Size %lu", SizeVfdCache)); Assert(SizeVfdCache > 0); /* InitFileAccess not called? */ if (VfdCache[0].nextFree == 0) { /* * The free list is empty so it is time to increase the size of the * array. We choose to double it each time this happens. However, * there's not much point in starting *real* small. */ Size newCacheSize = SizeVfdCache * 2; Vfd *newVfdCache; if (newCacheSize < 32) newCacheSize = 32; /* * Be careful not to clobber VfdCache ptr if realloc fails. */ newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize); if (newVfdCache == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); VfdCache = newVfdCache; ... file = VfdCache[0].nextFree; VfdCache[0].nextFree = VfdCache[file].nextFree; return file; }
PathNameOpenFile:
/* * open a file in an arbitrary directory * * NB: if the passed pathname is relative (which it usually is), * it will be interpreted relative to the process' working directory * (which should always be $PGDATA when this code is running). */ File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode) { char *fnamecopy; File file; Vfd *vfdP; DO_DB(elog(LOG, "PathNameOpenFile: %s %x %o", fileName, fileFlags, fileMode)); /* * We need a malloc'd copy of the file name; fail cleanly if no room. */ fnamecopy = strdup(fileName); if (fnamecopy == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); //VfdCache fprintf(stderr,"In %s ...by Process %d...", __FUNCTION__,getpid()); fprintf(stderr,"VfdCache Address is: %p \n\n +++++++++++++++++++++++++++++++++++\n",VfdCache); file = AllocateVfd(); vfdP = &VfdCache[file]; ... return file; }
实际运行的结果如下(开两个psql客户端,一个pid为 6518,另一个为6584):
+ In BaseInit ...by Process 6518 In InitFileAccess ...by Process 6518 ---------------------------------------------------- In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10dfff50 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6518...VfdCache Address is: 0x10e9c450 In BaseInit ...by Process 6584 In InitFileAccess ...by Process 6584 ---------------------------------------------------- In PathNameOpenFile ...by Process 6584...VfdCache Address is: 0x10e04e00 +++++++++++++++++++++++++++++++++++ In PathNameOpenFile ...by Process 6584...VfdCache Address is: 0x10ecaad0
两个进程里面的 VfdCache 地址是不同的。
我想,可能是出于效率的原因,各进程各自保持VFD指针。