DIV_ROUND_UP 是一个常用于 Linux 内核中的宏定义,用于执行向上取整的除法运算。它的定义如下:
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
这个宏的作用是计算 n 除以 d 的结果,并且总是向上取整(即取大于或等于实际商的最小整数)[1][2][3]。
工作原理
DIV_ROUND_UP 的工作原理基于整数除法的特性:
- 将被除数 n 加上 (d-1)
- 然后用整数除法除以除数 d
这样设计的原因是整数除法本身会自动向下取整(舍弃小数部分),通过先加上 (d-1) 再进行除法,可以在有余数的情况下使结果向上取整[1][2]。
数学原理
对于 x = βy + δ 的情况(其中 β ≥ 0,y > 0,0 ≤ δ 0(即 x 不能被 y 整除)时,结果是 β + 1[2]
使用场景
DIV_ROUND_UP 在内核中有多种应用场景:
- 内存分配:计算需要多少页来容纳特定大小的内存[3]
- 缓冲区管理:当有一个动态增长的缓冲区,增长步长是 d,某次申请大小是 n 时,可以用这个算法计算出合适的缓冲区大小[1]
- 页表管理:在 ARM64 架构中用于计算页表级别[3]
- 设备驱动:如计算硬盘通道数等[4]
与其他取整宏的关系
Linux 内核中还有其他相关的取整宏:
- ROUND_UP(x, align):
(DIV_ROUND_UP(x, align) * (align)),将 x 向上取整到 align 的倍数[1] - ROUND_DOWN(n, d):
(((n) / (d)) * (d)),将 n 向下取整到 d 的倍数[1]
示例
DIV_ROUND_UP(5, 2) = ((5 + 2 - 1) / 2) = (6 / 2) = 3
DIV_ROUND_UP(4, 2) = ((4 + 2 - 1) / 2) = (5 / 2) = 2
DIV_ROUND_UP(0, 2) = ((0 + 2 - 1) / 2) = (1 / 2) = 0
需要注意的是,如果直接使用 ((n) + (d)) / (d) 而不是 ((n) + (d) - 1) / (d),当 n 已经是 d 的倍数时会出现错误的结果[1]。例如:
// 错误的实现
(10 + 5) / 5 = 3 // 应该是 2,因为 10 已经是 5 的倍数
// 正确的实现
(10 + 5 - 1) / 5 = 2 // 正确结果
这就是为什么 DIV_ROUND_UP 的定义中需要减去 1 的原因[1]。
Citations:
[1] https://blog.csdn.net/sinat_32960911/article/details/128319039
[2] https://www.cnblogs.com/sky-heaven/p/15865165.html
[3] http://www.wowotech.net/memory_management/arm64-memory-addressing.html
[4] https://thunderjie.github.io/2020/06/11/%E7%AE%80%E5%8D%95%E5%86%85%E6%A0%B8%E5%AE%9E%E7%8E%B0%E7%AC%94%E8%AE%B0-part-4/
[5] https://blog.csdn.net/weixin_33805743/article/details/94640670
[6] https://www.cnblogs.com/cmembd/p/3493597.html
[7] https://developer.aliyun.com/article/1411682
[8] https://richardweiyang-2.gitbook.io/kernel-exploring/nei-cun-guan-li/00-memory_a_bottom_up_view/00_page_allocator/03-sparsemem



3394

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



