`
insertyou
  • 浏览: 917579 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

palloc.c

 
阅读更多

这个源文件主要讲的是页分配的过程。
enum palloc_flags
{
PAL_ASSERT = 001, /* Panic on failure. */
PAL_ZERO = 002, /* Zero page contents. */
PAL_USER = 004 /* User page. */
};
页分配时可以有三种状态,
PAL_ASSERT:如果页不能被分配,则kernel panics
PAL_ZERO:分配页时清零。
PAL_USER:从user pool中分配页。
前面两种是从kernel pool中分配页。
我们把内存分成两种类型。一种是user pool,一种是kernel pool。
struct pool
{
struct lock lock; /* Mutual exclusion. */
struct bitmap *used_map; /* Bitmap of free pages. */
uint8_t *base; /* Base of pool. */
};
这里我们用bitmap来表明空闲的页。这个和数据库的位图索引等都是差不多的。
lock是为了在寻找bitmap的时候只能是原子的。
void
palloc_init (size_t user_page_limit)
{
/* Free memory starts at 1 MB and runs to the end of RAM. */
uint8_t *free_start = ptov (1024 * 1024); //起始从1MB开始
uint8_t *free_end = ptov (init_ram_pages * PGSIZE); //结束是ram的页数*4KB
size_t free_pages = (free_end - free_start) / PGSIZE; //一共有几页空的
size_t user_pages = free_pages / 2; //如果一半空间不到user_page_limit,则不变,如果大于user_page_limit,则缩小为这个值。
size_t kernel_pages; //
if (user_pages > user_page_limit)
user_pages = user_page_limit;
kernel_pages = free_pages - user_pages; //其余的空闲的页赋给内核。

/* Give half of memory to kernel, half to user. */
init_pool (&kernel_pool, free_start, kernel_pages, "kernel pool");
init_pool (&user_pool, free_start + kernel_pages * PGSIZE,
user_pages, "user pool");
}
这个是内存的分池,user_page_limit参数是为了限制用户池的大小一定要在这个大小以内。

void *
palloc_get_multiple (enum palloc_flags flags, size_t page_cnt)
{
struct pool *pool = flags & PAL_USER ? &user_pool : &kernel_pool; //选择pool的类型。
void *pages;
size_t page_idx;

if (page_cnt == 0) //需求的页数量为0
return NULL;

lock_acquire (&pool->lock);
page_idx = bitmap_scan_and_flip (pool->used_map, 0, page_cnt, false); //寻找第一个连续page_cnt的空页的页位置,即是第几个页。
lock_release (&pool->lock);

if (page_idx != BITMAP_ERROR)
pages = pool->base + PGSIZE * page_idx; //找到页具体位置
else
pages = NULL;

if (pages != NULL)
{
if (flags & PAL_ZERO)
memset (pages, 0, PGSIZE * page_cnt); //如果PAL_ZERO,则分配是还要清零。
}
else
{
if (flags & PAL_ASSERT)
PANIC ("palloc_get: out of pages");
}

return pages;
}
//-----------------------------------------------------------------------------------------------------
static bool
page_from_pool (const struct pool *pool, void *page)
{
size_t page_no = pg_no (page);
size_t start_page = pg_no (pool->base);
size_t end_page = start_page + bitmap_size (pool->used_map);
return page_no >= start_page && page_no < end_page;
}
pg_no是把虚拟地址转为他所在的页号,因此如果page_no在start_page和end_page之间,则说明这个页已经分配了。

当free-page时要把这些页设为0xcc。
//-------------------------------------------------------------------------------------------------------
static void
init_pool (struct pool *p, void *base, size_t page_cnt, const char *name)
//池中除了要放空闲页,还要放bitmap,这个是用来记录的。因此bm_pages就是bitmap所占的页数。
p池为从base开始page_cnt页数的一个池,。
{
size_t bm_pages = DIV_ROUND_UP (bitmap_buf_size (page_cnt), PGSIZE);
if (bm_pages > page_cnt) //如果分配给池的大小还不能装的下bitmap。则不够。
PANIC ("Not enough memory in %s for bitmap.", name);
page_cnt -= bm_pages; //page_cnt-bm_pages为真正空闲的页数。

printf ("%zu pages available in %s./n", page_cnt, name);

/* Initialize the pool. */
lock_init (&p->lock);
p->used_map = bitmap_create_in_buf (page_cnt, base, bm_pages * PGSIZE);
p->base = base + bm_pages * PGSIZE; //池的基地址是原来的base+bitmap_page*PGSIZE;这才是真正的基地址。池的base是指除了bitmap空间的基地址。
}

| || <-----整体是一个pool
|--------------------------------------------------------------------- || <-----page_get_multiple()后返回的指针
| 分配的空间 || 地址
| ||
|----------------------------------------------------------------------|| <-----base (一直不会变)
|DIV_ROUND_UP (bitmap_buf_size (page_cnt), PGSIZE);|| <-----page_cnt要用的空间
|----------------------------------------------------------------------|| |低

分享到:
评论

相关推荐

    Nginx源代码分析

    - **ngx_palloc.c**:实现内存池的具体操作。 内存池的主要结构如下: ```c // ngx_palloc.h struct ngx_pool_s { ... }; typedef struct ngx_pool_s ngx_pool_t; struct ngx_pool_data_s { ngx_pool_t pool; ...

    Nginx_study:学习Nginx原始码和架构

    Nginx_study编写说明本次学习二进制分为多个阶段第一阶段:完成逐步架构,基本功能,各模块能独立运行阶段一1.1封装...实现内存池在nginx的原始码中内存池的定义和实现在core / ngx_palloc.c和core / ngx_palloc.h中,

    nginx-1.14.2 源码

    `src/core/ngx_log.c` 和 `src/core/ngx_palloc.c` 分别处理日志记录和内存分配错误。Nginx 提供了多种级别的日志输出,方便调试和问题排查。 **8. SSL/TLS 支持** Nginx 对 SSL/TLS 的支持位于 `src/...

    nginx-1.7.8源码

    5. **内存管理**: 研究 `src/core/ngx_palloc.c`,了解 Nginx 自有的内存池管理机制。 6. **信号处理**: 分析 `src/os/unix/ngx_process_cycle.c`,理解 Nginx 如何处理进程间的通信和信号。 深入研究 Nginx 1.7.8 ...

    nginx原码版本0.54

    在 `src/core/ngx_palloc.c` 中,我们可以看到如何创建和使用内存池。 8. **日志系统** Nginx 的日志系统非常灵活,可以在 `src/core/ngx_log.c` 中看到其实现。它支持自定义日志格式、日志级别以及日志写入方式,...

    BZRJ.rar_按钮控件_C/C++_

    - `ncx_slab.c`, `ncx_palloc.c`, `ncx_alloc.c`:这些可能是C源码文件,实现了具体的内存池算法,如slab分配器(常用于缓存系统,如早期的Oracle数据库和Linux内核)或者其他内存分配策略。 - `ncx_slab.h`, `ncx_...

    qoxl208.rar_Windows编程

    1. **Palloc.cpp**:这可能包含了主的资源分配算法实现,"Palloc"可能是"Power Allocation"或"Partition Allocation"的缩写,与OFDMA中的功率分配或频谱分割相关。 2. **SIPS04.cpp**:"SIPS"可能代表"Subchannel ...

    cnginx_source:nginx-release-1.19.2版本原始码的学习

    6. **内存池**:Nginx使用内存池(`src/core/ngx_palloc.c`)来减少内存分配和释放的开销。内存池预先分配一大块内存,然后从中分配小块内存,避免频繁的系统调用。 7. **异步非阻塞I/O**:Nginx充分利用了异步非...

    nginx-1.17.9:nginx-1.17.9源码分析

    `src/core/ngx_palloc.c` 提供了基于池的内存分配,能有效减少内存碎片并提高内存分配效率。`ngx_chain_t` 结构体用于构建数据链表,常用于处理网络数据的读写。 此外,Nginx 还支持模块化设计,用户可以通过编写...

    Nginx源代码分析.pdf

    - Nginx内存池:Nginx引入了内存池的概念,它在`core/ngx_palloc.{h,c}`中实现。内存池允许在进程生命周期内创建并管理一组预分配的内存块,提高内存分配效率,减少碎片,并简化内存释放。使用内存池时,模块可以按...

    nginx-0.8.4源代码

    `ngx_string.h`和`ngx_palloc.h`等头文件定义了Nginx内部使用的数据结构和内存管理函数。 6. **conf**:配置文件解析器位于`conf`目录,如`ngx_conf_file.c`,负责读取和解析Nginx的配置文件。 通过阅读和理解...

    apache APR内存池概述

    `apr_palloc`或`apr_pcalloc`函数用于从内存池中分配内存,它们分别对应于标准C库的`malloc`和`calloc`,但使用内存池实现。 3. 释放:内存池管理着所有分配的内存,当不再需要某块内存时,不需要立即释放。相反,...

    cpp-nginx192源码通读分析注释

    `ngx_palloc()`和`ngx_pcalloc()`等函数用于在内存池中分配和清理内存。 8. **多进程与信号处理** Nginx支持多进程模型,主进程`master process`负责监听端口和管理工作进程。信号处理在`ngx_signal_handler()`中...

    Nginx 内存模型.

    ### Nginx内存模型详解 ...通过对 `ngx_create_pool` 和 `ngx_palloc` 这两个核心函数的理解,我们可以更深入地了解Nginx是如何高效管理内存的。这种设计不仅提高了内存分配的效率,也保证了系统的稳定性和可靠性。

    C/C++ Nginx 内存池源码

    - 分配内存使用`ngx_palloc(ngx_pool_t *pool, size_t size)`或`ngx_pcalloc(ngx_pool_t *pool, size_t size)`,前者分配未初始化的内存,后者分配并清零的内存。 - 这些函数会根据所需内存的大小,在当前池块中...

    [应用开发及迁移][服务器编程]服务器编程接口.pdf

    **服务器编程接口(SPI)**是一种专为数据库开发人员设计的工具集,它允许开发者通过C语言编写的函数直接执行SQL命令。这种能力极大地扩展了开发者在数据库应用程序中的操作灵活性。SPI主要包括以下组成部分: 1. *...

Global site tag (gtag.js) - Google Analytics