zoukankan      html  css  js  c++  java
  • 对PostgreSQL中后台进程内存挂载的初步学习

    开始

    从 CreateSharedMemoryAndSemaphores 开始:

    对于 Postmaster 的各个子进程而言,内存结构在 Postmaster 中已经建立,只是需要挂到各子进程自己的本地变量上。

    /*                            
     * CreateSharedMemoryAndSemaphores                            
     *        Creates and initializes shared memory and semaphores.                    
     *                            
     * This is called by the postmaster or by a standalone backend.                            
     * It is also called by a backend forked from the postmaster in the                            
     * EXEC_BACKEND case.  In the latter case, the shared memory segment                            
     * already exists and has been physically attached to, but we have to                            
     * initialize pointers in local memory that reference the shared structures,                            
     * because we didn't inherit the correct pointer values from the postmaster                            
     * as we do in the fork() scenario.  The easiest way to do that is to run                            
     * through the same code as before.  (Note that the called routines mostly                            
     * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.                            
     * This is a bit code-wasteful and could be cleaned up.)                            
     *                            
     * If "makePrivate" is true then we only need private memory, not shared                            
     * memory.    This is true for a standalone backend, false for a postmaster.                        
     */                            
    void                            
    CreateSharedMemoryAndSemaphores(bool makePrivate, int port)                            
    {                            
        ……                        
        /*                        
         * Set up shmem.c index hashtable                        
         */                        
        InitShmemIndex();                        
                                
        /*                        
         * Set up xlog, clog, and buffers                        
         */                        
        XLOGShmemInit();                        
        CLOGShmemInit();                        
        SUBTRANSShmemInit();                        
        MultiXactShmemInit();                        
        InitBufferPool();                        
                                
        /*                        
         * Set up lock manager                        
         */                        
        InitLocks();                        
                                
        /*                        
         * Set up predicate lock manager                        
         */                        
        InitPredicateLocks();                        
                                
        /*                        
         * Set up process table                        
         */                        
        if (!IsUnderPostmaster)                        
            InitProcGlobal();                    
        CreateSharedProcArray();                        
        CreateSharedBackendStatus();                        
        TwoPhaseShmemInit();                        
                                
        /*                        
         * Set up shared-inval messaging                        
         */                        
        CreateSharedInvalidationState();                        
                                
        /*                        
         * Set up interprocess signaling mechanisms                        
         */                        
        PMSignalShmemInit();                        
        ProcSignalShmemInit();                        
        CheckpointerShmemInit();                        
        AutoVacuumShmemInit();                        
        WalSndShmemInit();                        
        WalRcvShmemInit();                        
                                
        /*                        
         * Set up other modules that need some shared memory space                        
         */                        
        BTreeShmemInit();                        
        SyncScanShmemInit();                        
        AsyncShmemInit();                        
                                
        #ifdef EXEC_BACKEND                        
                                
            /*                    
             * Alloc the win32 shared backend array                    
             */                    
            if (!IsUnderPostmaster)                    
                ShmemBackendArrayAllocation();                
        #endif                        
                                
        /*                        
         * Now give loadable modules a chance to set up their shmem allocations                        
         */                        
        if (shmem_startup_hook)                        
            shmem_startup_hook();                    
    }                            

    接着看 InitShmemIndex

    /*                    
     *    InitShmemIndex() --- set up or attach to shmem index table.                
     */                    
    void                    
    InitShmemIndex(void)                    
    {                    
        HASHCTL        info;        
        int        hash_flags;        
                        
        /*                
         * Create the shared memory shmem index.                
         *                
         * Since ShmemInitHash calls ShmemInitStruct, which expects the ShmemIndex                
         * hashtable to exist already, we have a bit of a circularity problem in                
         * initializing the ShmemIndex itself.                The special "ShmemIndex" hash
         * table name will tell ShmemInitStruct to fake it.                
         */                
        info.keysize = SHMEM_INDEX_KEYSIZE;                
        info.entrysize = sizeof(ShmemIndexEnt);                
        hash_flags = HASH_ELEM;                
                        
        ShmemIndex = ShmemInitHash("ShmemIndex",                
                           SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE,
                           &info, hash_flags);
    }                    

    然后是 ShmemInitHash,重点要关注 hash_flag 的设置

    /*                                
     * ShmemInitHash -- Create and initialize, or attach to, a                                
     *        shared memory hash table.                        
     *                                
     * We assume caller is doing some kind of synchronization                                
     * so that two processes don't try to create/initialize the same                                
     * table at once.  (In practice, all creations are done in the postmaster                                
     * process; child processes should always be attaching to existing tables.)                                
     *                                
     * max_size is the estimated maximum number of hashtable entries.  This is                                
     * not a hard limit, but the access efficiency will degrade if it is                                
     * exceeded substantially (since it's used to compute directory size and                                
     * the hash table buckets will get overfull).                                
     *                                
     * init_size is the number of hashtable entries to preallocate.  For a table                                
     * whose maximum size is certain, this should be equal to max_size; that                                
     * ensures that no run-time out-of-shared-memory failures can occur.                                
     *                                
     * Note: before Postgres 9.0, this function returned NULL for some failure                                
     * cases.  Now, it always throws error instead, so callers need not check                                
     * for NULL.                                
     */                                
    HTAB *                                
    ShmemInitHash(const char *name, /* table string name for shmem index */                                
                  long init_size,    /* initial table size */                
                  long max_size,    /* max size of the table */                
                  HASHCTL *infoP,    /* info about key and bucket size */                
                  int hash_flags)    /* info about infoP */                
    {                                
        bool       found;                        
        void       *location;                        
                                    
        /*                            
         * Hash tables allocated in shared memory have a fixed directory; it can't                            
         * grow or other backends wouldn't be able to find it. So, make sure we                            
         * make it big enough to start with.                            
         *                            
         * The shared memory allocator must be specified too.                            
         */                            
        infoP->dsize = infoP->max_dsize = hash_select_dirsize(max_size);                            
        infoP->alloc = ShmemAlloc;                            
        hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE;                            
                                    
        /* look it up in the shmem index */                            
        location = ShmemInitStruct(name,                            
                       hash_get_shared_size(infoP, hash_flags),                
                       &found);                
                                    
        /*                            
         * if it already exists, attach to it rather than allocate and initialize                            
         * new space                            
         */                            
        if (found)                            
            hash_flags |= HASH_ATTACH;                        
                                    
        /* Pass location of hashtable header to hash_create */                            
        infoP->hctl = (HASHHDR *) location;                            
                                    
        return hash_create(name, init_size, infoP, hash_flags);                            
    }                                

    再下来:

    /*                            
     * hash_create -- create a new dynamic hash table                            
     *                            
     *    tabname: a name for the table (for debugging purposes)                        
     *    nelem: maximum number of elements expected                        
     *    *info: additional table parameters, as indicated by flags                        
     *    flags: bitmask indicating which parameters to take from *info                        
     *                            
     * Note: for a shared-memory hashtable, nelem needs to be a pretty good                            
     * estimate, since we can't expand the table on the fly.  But an unshared                            
     * hashtable can be expanded on-the-fly, so it's better for nelem to be                            
     * on the small side and let the table grow if it's exceeded.  An overly                            
     * large nelem will penalize hash_seq_search speed without buying much.                            
     */                            
    HTAB *                            
    hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)                            
    {                            
        ……                        
        if (flags & HASH_SHARED_MEM)                        
        {                        
            /*                    
             * ctl structure and directory are preallocated for shared memory                    
             * tables.    Note that HASH_DIRSIZE and HASH_ALLOC had better be set as                
             * well.                    
             */                    
            hashp->hctl = info->hctl;                    
            hashp->dir = (HASHSEGMENT *) (((char *) info->hctl) + sizeof(HASHHDR));                    
            hashp->hcxt = NULL;                    
            hashp->isshared = true;                    
                                
            /* hash table already exists, we're just attaching to it */                    
            if (flags & HASH_ATTACH)                    
            {                    
                /* make local copies of some heavily-used values */                
                hctl = hashp->hctl;                
                hashp->keysize = hctl->keysize;                
                hashp->ssize = hctl->ssize;                
                hashp->sshift = hctl->sshift;                
                                
                return hashp;                
            }                    
        }                        
        else                        
        {                        
            ……                    
        }                        
        ……                        
        return hashp;                        
    }                            
                                

    [作者:技术者高健@博客园  mail: luckyjackgao@gmail.com ]

    结束

  • 相关阅读:
    NOIp2018集训test-9-4
    「THUSC 2016」成绩单 & 方块消除 (区间dp)
    NOIp2018集训test-9-2(pm)
    NOIp2018集训test-9-2(am)
    NOIp2018集训test-9-1(pm)
    NOIp2018集训test-9-1(am)
    暑假集训test-8-31(pm)
    暑假集训test-8-31(am)
    暑假集训test-8-30
    day22 笔记
  • 原文地址:https://www.cnblogs.com/gaojian/p/2757116.html
Copyright © 2011-2022 走看看