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

  • 相关阅读:
    WCF学习笔记之宿主在IIS中
    WCF学习笔记之配置文件
    WCF学习笔记之自托管
    深入C#中的事件
    深入理解c#中的const 和readonly的区别滴呀;
    鼠标跟着键盘飞=====兼容代码
    offset系列,scroll系列
    无缝链接轮播图
    完整轮播图
    location对象
  • 原文地址:https://www.cnblogs.com/gaojian/p/3096926.html
Copyright © 2020-2023  润新知