PostgreSQL 后台进程对共享内存的指针

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介:

开始

复制代码
/*                    
 *    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 */






本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/11/06/2757162.html,如需转载请自行联系原作者

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
1月前
|
存储 Go iOS开发
掌握Go语言:探索Go语言指针,解锁高效内存操作与动态数据结构的奥秘(19)
掌握Go语言:探索Go语言指针,解锁高效内存操作与动态数据结构的奥秘(19)
|
1月前
|
移动开发 Linux
Linux下如何查看哪些进程占用的CPU内存资源最多
Linux下如何查看哪些进程占用的CPU内存资源最多
|
1天前
|
消息中间件 算法 Linux
【Linux】详解如何利用共享内存实现进程间通信
【Linux】详解如何利用共享内存实现进程间通信
|
4天前
|
消息中间件 存储 Unix
【探索Linux】P.15(进程间通信 —— system V共享内存)
【探索Linux】P.15(进程间通信 —— system V共享内存)
16 0
|
5天前
|
运维 监控 Ubuntu
Python实现ubuntu系统进程内存监控
Python实现ubuntu系统进程内存监控
12 1
|
11天前
|
存储 Web App开发 运维
|
11天前
|
Java Go 区块链
【Go语言专栏】Go语言中的指针与内存管理
【4月更文挑战第30天】Go语言,由Google开发,是一种静态强类型、编译型、并发型语言,具有垃圾回收功能,常用于云计算、微服务、区块链等领域。本文聚焦Go中的指针和内存管理。指针表示变量内存地址,可用于直接访问和修改变量,如示例代码所示。指针运算有限制,仅支持相同类型变量和数组元素访问。内存管理由Go运行时的垃圾回收机制处理,自动回收无引用对象,简化管理但引入性能开销。可通过`runtime.GC()`手动触发垃圾回收。
|
18天前
|
消息中间件 Linux
【linux进程间通信(二)】共享内存详解以及进程互斥概念
【linux进程间通信(二)】共享内存详解以及进程互斥概念
|
1天前
|
负载均衡 关系型数据库 MySQL
关系型数据库的安装和配置数据库节点
关系型数据库的安装和配置数据库节点
12 3
|
1天前
|
SQL 关系型数据库 数据库
关系型数据库选择合适的数据库管理系统
关系型数据库选择合适的数据库管理系统
8 2