zoukankan      html  css  js  c++  java
  • PostgreSQL 后台进程对共享内存的指针

    开始

    /*                    
     *    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);
    }                    

    其实 ShmemIndex 就是对共享内存的指针:

    /*                            
     * 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 的相关代码:

    /*                                
     * 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)                                
    {                                
        HTAB       *hashp;                        
        HASHHDR    *hctl;                            
                                    
        /*                            
         * For shared hash tables, we have a local hash header (HTAB struct) that                            
         * we allocate in TopMemoryContext; all else is in shared memory.                            
         *                            
         * For non-shared hash tables, everything including the hash header is in                            
         * a memory context created specially for the hash table --- this makes                            
         * hash_destroy very simple.  The memory context is made a child of either                            
         * a context specified by the caller, or TopMemoryContext if nothing is                            
         * specified.                            
         */                            
        if (flags & HASH_SHARED_MEM)                            
        {                            
            /* Set up to allocate the hash header */                        
            CurrentDynaHashCxt = TopMemoryContext;                        
        }                            
        else                            
        {                            
            /* Create the hash table's private memory context */                        
            if (flags & HASH_CONTEXT)                        
                CurrentDynaHashCxt = info->hcxt;                    
            else                        
                CurrentDynaHashCxt = TopMemoryContext;                    
            CurrentDynaHashCxt = AllocSetContextCreate(CurrentDynaHashCxt,                        
                                       tabname,
                                       ALLOCSET_DEFAULT_MINSIZE,
                                       ALLOCSET_DEFAULT_INITSIZE,
                                       ALLOCSET_DEFAULT_MAXSIZE);
        }                            
                                    
        /* Initialize the hash header, plus a copy of the table name */                            
        hashp = (HTAB *) DynaHashAlloc(sizeof(HTAB) + strlen(tabname) +1);                            
        MemSet(hashp, 0, sizeof(HTAB));                            
                                    
        hashp->tabname = (char *) (hashp + 1);                            
        strcpy(hashp->tabname, tabname);                            
                                    
        ……                            
        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                            
        {                            
            ……                        
        }                            
                                    
        if (!hashp->hctl)                            
        {                            
            hashp->hctl = (HASHHDR *) hashp->alloc(sizeof(HASHHDR));                        
            if (!hashp->hctl)                        
                ereport(ERROR,                    
                        (errcode(ERRCODE_OUT_OF_MEMORY),            
                         errmsg("out of memory")));            
        }                            
                                    
        ……                            
        if (flags & HASH_FIXED_SIZE)                            
            hashp->isfixed = true;                        
        return hashp;                            
    }                                

    在 src/backend/storage/ipc/shmem.c 的注释中也是这么说的:

    /*
    * POSTGRES processes share one or more regions of shared memory.
    * The shared memory is created by a postmaster and is inherited
    * by each backend via fork() (or, in some ports, via other OS-specific
    * methods). The routines in this file are used for allocating and
    * binding to shared memory data structures.

    ......

    /

    ......

    static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */

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

    结束

  • 相关阅读:
    COBBLER无人值守安装
    消息头 Content-Type引发的问题:Jmeter请求中postdata不是期望的,响应数据请求参数为null;已经请求没问题,可变量还是为空
    python爬虫-'gbk' codec can't encode character 'xa0' in position 134: illegal multibyte sequence
    正则表达式30分钟入门教程-链接
    linux常见命令学习汇总3-控制语句
    postman循环操作及响应判断-支持文本多变量输入
    linux常见命令学习汇总2-运算符
    linux常见命令学习汇总1
    Jmeter连接数据库方法与问题:Cannot load JDBC driver class 'com.mysql.jdbc.Driver'
    mysql学习笔记-ifnull()函数与nullif()函数
  • 原文地址:https://www.cnblogs.com/gaojian/p/2757162.html
Copyright © 2011-2022 走看看