PAGE_ALIGN 详解 纯属原创 转载注明出处
(2014-11-09 17:46:03)今天阅读内核代码的时候再一次碰到了这个函数之前只知道他是内存对齐用的,但他究竟是如何实现内存对齐的却从没有去深究,今天正好是周末,于是我拿来和大家一起当午餐,不对,是晚餐吧已经五点了呢 哈哈
这是LCD驱动离得一行代码
unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
那么什么是页对齐呢
原来是这样的我们在分配内存的时候经常是页为单位来分配的,也就是说只能分配到整数页,而页的大小在每一个平台上的大小是确定的,一般是4096字节。那么糟糕,我现在需要4050K字节怎么办呢当然是只能分配到两页了,至于你说那第二页我都基本没用啊,给我这么多,浪费死了。可是系统也是冤枉的啊,总不能给你一页导致你不够用吧。那么这个二页的二是怎么来的呢,是不是 4050/4090 +1 呢 ,现在反正我知道我的平台上页的大小是4096,于是我就用个宏来代替吧,页方便移植呢,于是就有
#define PAGE_SHIFT
#define PAGE_SIZE
那么上面的等式我们就可以写为 4050/ (PAGE_SIZE+1)
那么我们现在看下内核是如何实现PAGE_ALIGN(info->fix.smem_len);的
#define PAGE_ALIGN(addr)
#define _ALIGN(addr,size)
我们继续吧 哈哈
#define _ALIGN(addr,size)
还要继续呢 别生气哦
#define _ALIGN_UP(addr,size)
#define _ALIGN_DOWN(addr,size)
哈哈 终于露出来真面目了 我的神仙姐姐啊
可是怎么多了个e _ALIGN_DOWN 呢 烦死了 先不管 还是来看_ALIGN_UP吧
更具刚开始的思想 应该是 ADDR/(PAGE_SIZE+1)
我们不是按PAGE_SIZE对齐的吗 也就是说我们分配得到的地址肯定是4096的整数倍,如一个数字如果是 4096的整数倍的话是不是他的二进制表示的时候 最后12位都是0 啊 ,这就好办了 我们只要把这个数字和 0x0000 0000 0000位与就好了
#define PAGE_SHIFT
#define PAGE_SIZE
PAGE_SIZE=0x1 0000 0000 0000 共13位 怎么表示12位的0呢,把这个数字减去1不久是了吗 于是就有了
为了方便 内核把这个表达式定了个个宏
#define PAGE_MASK
那么我们这个公式的前面为什么还有个((size)-1)呢
你想一下 假设我们要分配1K字节 直接和PAGE_MASK 位与 结果就是0 ,显然我们需要的答案是1啊 ,就是要结果最后加上1 为了方便计算机操作 我们先给这个被除数加上个除数 就相当于 商加1了 ,回到小学数学了 哈哈 那么为什么是 加size -1 不是加size就好了呢,这里别忘记了 size是 1<<12 是13位的二进制 我们只需要除以4095就可以了呢假设要分配4096字节 显然是一页刚刚好,如果加4096的话 就是两页了 所以这里减去1
好了,差不多了吧 不清楚的私信我哦
对 想起了
#define _ALIGN_UP(addr,size)
#define _ALIGN_DOWN(addr,size)
这两个比较一下 原来只是除数少了个4095 相当于结果减去1,和名字的意思就知道了是向下对齐,大部分的内存分配道德地址是递增的,所以没默认就是UP,有的分配机制是递减的,这是就要用到DOWN了
最后面回想下 其实PAGE_ALIGN不是函数 只是个宏而已
好了不说了 喝我的排骨花生 枸子汤去了