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

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

开始

复制代码
/*                    
 *    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数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
2月前
麒麟系统mate-indicators进程占用内存过高问题解决
【10月更文挑战第7天】麒麟系统mate-indicators进程占用内存过高问题解决
288 2
|
6天前
|
运维 监控 Ubuntu
【运维】如何在Ubuntu中设置一个内存守护进程来确保内存不会溢出
通过设置内存守护进程,可以有效监控和管理系统内存使用情况,防止内存溢出带来的系统崩溃和服务中断。本文介绍了如何在Ubuntu中编写和配置内存守护脚本,并将其设置为systemd服务。通过这种方式,可以在内存使用超过设定阈值时自动采取措施,确保系统稳定运行。
22 4
|
19天前
|
C语言 开发者 内存技术
探索操作系统核心:从进程管理到内存分配
本文将深入探讨操作系统的两大核心功能——进程管理和内存分配。通过直观的代码示例,我们将了解如何在操作系统中实现这些基本功能,以及它们如何影响系统性能和稳定性。文章旨在为读者提供一个清晰的操作系统内部工作机制视角,同时强调理解和掌握这些概念对于任何软件开发人员的重要性。
|
18天前
|
Linux 调度 C语言
深入理解操作系统:从进程管理到内存优化
本文旨在为读者提供一次深入浅出的操作系统之旅,从进程管理的基本概念出发,逐步探索到内存管理的高级技巧。我们将通过实际代码示例,揭示操作系统如何高效地调度和优化资源,确保系统稳定运行。无论你是初学者还是有一定基础的开发者,这篇文章都将为你打开一扇了解操作系统深层工作原理的大门。
|
28天前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
28天前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
27天前
|
算法 调度 开发者
深入理解操作系统:从进程管理到内存分配
本文旨在为读者提供一个深入浅出的操作系统知识之旅,从进程管理的基础概念出发,探索内存分配的策略与技巧。我们将通过实际代码示例,揭示操作系统背后的逻辑与奥秘,帮助读者构建起对操作系统工作原理的直观理解。文章不仅涵盖理论知识,还提供实践操作的指导,使读者能够将抽象的概念转化为具体的技能。无论你是初学者还是有一定基础的开发者,都能在这篇文章中找到有价值的信息和启发。
|
1月前
|
算法 调度 C++
深入理解操作系统:从进程管理到内存分配
【10月更文挑战第42天】本文将带你进入操作系统的神秘世界,探索其核心概念和关键技术。我们将从进程管理开始,了解操作系统如何协调和管理多个程序的运行;然后,我们将深入研究内存分配,看看操作系统如何有效地分配和管理计算机的内存资源。通过这篇文章,你将获得对操作系统工作原理的深入理解,并学会如何编写高效的代码来利用这些原理。
|
1月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
88 4