本文参考Linux-4.1.15
Linux通过PAGE_ALIGN(addr)将addr加大对齐到4096字节的边界(4096的整数倍),假设addr=4096+n,{0<n<4096},则执行PAGE_ALIGN(addr)后,addr=4096+4096
PAGE_ALIGN这个宏在include/linux/mm.h中,
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
同时Linux中如下定义:
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
PAGE_ALIGN(addr)等价于:(addr+(PAGE_SIZE-1)) & ~(PAGE_SIZE-1)
假设PAGE_SIZE=4096,即1 0000 0000 0000(b),则(PAGE_SIZE-1) = 1111 1111 1111(b),~(PAGE_SIZE-1)=0000 0000 0000(b)。
由上可知,一个数为4096的整数倍,则这个数的二进制的低12位等于0。对于(addr+(PAGE_SIZE-1)) & ~(PAGE_SIZE-1)来说,&左边将addr加大到下一个4096字节范围,&右边则将addr低12清零(对齐)。
另外,关于PAGE_SIZE的定义如下,linux-4.1.15\arch\arm64\include\asm\page.h
/* PAGE_SHIFT determines the page size */
#ifdef CONFIG_ARM64_64K_PAGES
#define PAGE_SHIFT 16
#else
#define PAGE_SHIFT 12
#endif
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)//_AC(1,UL)=1UL=1个unsigned long,最终为4KB或64KB
#define PAGE_MASK (~(PAGE_SIZE-1))
当然,PAGE_SIZE的值本质是由ARM SOC寄存器的配置决定的。
本文探讨了Linux中的内存对齐机制,重点介绍了PAGE_ALIGN宏如何将地址调整到4096字节的边界。通过示例解释了(PAGE_SIZE-1)与~(PAGE_SIZE-1)在地址对齐过程中的作用,以及PAGE_SIZE在不同平台上的配置,特别是ARM64架构下的实现。
1224

被折叠的 条评论
为什么被折叠?



