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指针。

原文地址:https://www.cnblogs.com/gaojian/p/3096926.html