PAGE_ALIGN 详解 纯属原创 转载注明出处

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   12

#define PAGE_SIZE     (ASM_CONST(1) << PAGE_SHIFT)

 因为4096用二进制表示需要13位,注意 0~4095哦 4096当然还是无法表示的呢

那么上面的等式我们就可以写为 4050/ (PAGE_SIZE+1)   + 1

 

那么我们现在看下内核是如何实现PAGE_ALIGN(info->fix.smem_len);的

 

#define PAGE_ALIGN(addr)       _ALIGN(addr, PAGE_SIZE)

  这里多了个PAGE_SIZE 刚才已经介绍过了 继续往下看

 

#define _ALIGN(addr,size)     _ALIGN_UP(addr,size)

我们继续吧 哈哈

#define _ALIGN(addr,size)     _ALIGN_UP(addr,size)

还要继续呢 别生气哦

#define _ALIGN_UP(addr,size)    (((addr)+((size)-1))&(~((size)-1)))

#define _ALIGN_DOWN(addr,size)     ((addr)&(~((size)-1)))

哈哈 终于露出来真面目了 我的神仙姐姐啊

可是怎么多了个e _ALIGN_DOWN 呢 烦死了 先不管 还是来看_ALIGN_UP吧

 

更具刚开始的思想 应该是 ADDR/(PAGE_SIZE+1)   + 1啊 现在怎么好乱是这样的 我的公式里有个 除 这个运算在计算机里实现起来效率很低 于是人们就改进这个公式

我们不是按PAGE_SIZE对齐的吗 也就是说我们分配得到的地址肯定是4096的整数倍,如一个数字如果是 4096的整数倍的话是不是他的二进制表示的时候 最后12位都是0 啊 ,这就好办了 我们只要把这个数字和 0x0000 0000 0000位与就好了  为了方便移植 就用PAGE_SIZE来表示0x0000 0000 0000 我们知道

#define PAGE_SHIFT   12

#define PAGE_SIZE     (ASM_CONST(1) << PAGE_SHIFT)

PAGE_SIZE=0x1 0000 0000 0000 共13位 怎么表示12位的0呢,把这个数字减去1不久是了吗 于是就有了

       (~(PAGE_SIZE-1))

为了方便 内核把这个表达式定了个个宏

#define PAGE_MASK   (~(PAGE_SIZE-1))

 

那么我们这个公式的前面为什么还有个((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)    (((addr)+((size)-1))&(~((size)-1)))

#define _ALIGN_DOWN(addr,size)     ((addr)&(~((size)-1)))

 第二个函数还没说呢

这两个比较一下 原来只是除数少了个4095 相当于结果减去1,和名字的意思就知道了是向下对齐,大部分的内存分配道德地址是递增的,所以没默认就是UP,有的分配机制是递减的,这是就要用到DOWN了

最后面回想下 其实PAGE_ALIGN不是函数 只是个宏而已

好了不说了 喝我的排骨花生 枸子汤去了

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值