# linux2021: WayneLin1992 ###### tags: `linux2021` - [ ] 說明程式碼的運作原理 - [ ] 在 Linux kernel 找出類似 `align_up` 的程式碼,並舉例說明其用法 ## 測驗 $\beta$ ```cpp #include <stdint.h> static inline uintptr_t align_up(uintptr_t sz, size_t alignment) { uintptr_t mask = alignment - 1; if ((alignment & mask) == 0) { /* power of two? */ return ((sz + mask) & (~mask)); } return (((sz + mask) / alignment) * alignment); } ``` `main` ```cpp int main() { printf("%d \n", align_up(120, 4)); printf("%d \n", align_up(121, 4)); printf("%d \n", align_up(125, 4)); return 0; } ``` 得到下列結果 ```shell 120 124 128 ``` ## 在 Linux kernel 找出類似 `align_up` 的程式碼,說明其用法 在 <include/linux/mm.h> 和 <include/linux/kernel.h> 有定義出 `PAGE_ALIGN` 及 `ALIGN` `#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)` :::info 其中 `PAGE_SIZE` 在 <arch/x86/include/asm/page_types.h> 中定義 ```cpp /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) <include/uapi/linux/const.h> #define _AC(X,Y) X ``` 可以了解到 PAGE_SIZE 預設在 x86下為 4KB ::: `#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))` 由此可知內部的實作為 `__ALIGN_KERNEL` `#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)` `#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))` `typeof` 為 gcc 的 extension 將會回傳對應的 x 的 type 。 由此可以知道 `mask = (typeof(x))(a) - 1` 也可以對應到題目的 `mask = alignment - 1;` ### 觀察 kernel 中使用的 `ALIGN` 的部分 - [ ] `videobuf2` 在 <drivers/media/common/videobuf2/videobuf2-core.c> 中有 `__vb2_buf_mem_alloc` `__vb2_buf_mem_alloc() - allocate video memory for the given buffer` 裡面使用了 `PAGE_ALIGN` 在於決定記憶體配置的大小 size ```cpp /* Memops alloc requires size to be page aligned. */ unsigned long size = PAGE_ALIGN(vb->planes[plane].length); ``` ## 測驗 $\zeta$