ngx_pagesize是Nginx运行时确定的基本内存页大小,编译期通过sysconf(_SC_PAGESIZE)或getpagesize()预定义宏,运行时在ngx_os_init()中调用getpagesize()赋值并计算ngx_pagesize_shift,确保准确性和兼容性。

在 Nginx 源码中,ngx_pagesize 是一个关键的全局变量,用于记录当前系统内存页(page)大小,它直接影响内存池分配、缓冲区对齐、mmap 映射等底层行为。这个值并非硬编码,而是编译时或运行时自动探测得出,其逻辑兼顾可移植性与准确性。
编译期优先:通过 _SC_PAGESIZE 或 getpagesize() 宏定义推导
Nginx 在 auto/os/unix 配置脚本阶段就尝试确定页大小:
- 先检查系统是否支持
sysconf(_SC_PAGESIZE)—— 大多数 POSIX 系统(Linux、FreeBSD、macOS)都提供该接口; - 若不支持,则回退到
getpagesize()函数调用(仍是标准 C 库函数); - 配置脚本会生成类似
#define NGX_PAGESIZE getpagesize()或直接写死为常量(如#define NGX_PAGESIZE 4096)的宏,写入objs/ngx_auto_config.h。
这意味着:大多数现代系统下,NGX_PAGESIZE 宏在编译时就已确定,后续 ngx_pagesize 变量初始化即调用该宏。
运行时赋值:在 ngx_os_init() 中完成最终初始化
尽管宏可能已知,Nginx 仍选择在运行时首次调用 ngx_os_init()(通常在 master 进程启动早期)中执行实际探测:
- 调用
getpagesize()获取真实页大小(Linux 下返回/proc/meminfo中的Page size,实际由内核MMU决定); - 将结果存入全局变量
ngx_pagesize和ngx_pagesize_shift(即 log₂(ngx_pagesize),用于位运算快速对齐); - 该步骤确保即使交叉编译环境误判,也能以运行时为准,提升鲁棒性。
为什么不用 sysconf(_SC_PAGESIZE) 直接?
虽然 sysconf 更“标准”,但 Nginx 选择 getpagesize() 主要出于两点:
-
getpagesize()是更轻量的系统调用(无 libc 封装开销),且语义明确——只返回基础内存页大小(非 hugepage); - 某些嵌入式或旧系统(如部分 Solaris 版本)中
sysconf可能未完全实现或返回异常值,而getpagesize()兼容性更广。
注意:ngx_pagesize 始终表示**基本页大小(base page size)**,不反映透明大页(THP)或显式 hugetlbpage 设置 —— 那些需单独处理。
开发者须知:修改或调试页大小相关逻辑的位置
若需定制或排查页大小问题,重点关注以下源码位置:
-
src/os/unix/ngx_posix_init.c:定义ngx_os_init(),其中调用getpagesize()并赋值给ngx_pagesize; -
auto/os/unix:配置脚本,决定NGX_PAGESIZE宏如何生成; -
src/core/ngx_config.h:声明extern size_t ngx_pagesize和ngx_pagesize_shift; - 内存池(
ngx_palloc.c)和共享内存(ngx_shm.c)中大量使用这两个变量做地址对齐,例如ngx_align_ptr(p, ngx_pagesize)。
不复杂但容易忽略:页大小一旦确定,整个进程生命周期内不可变;多线程环境下它是只读共享量,无需加锁访问。

















