Try   HackMD

linux2021: WayneLin1992

tags: linux2021
  • 說明程式碼的運作原理
  • 在 Linux kernel 找出類似 align_up 的程式碼,並舉例說明其用法

測驗
β

#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

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;
}

得到下列結果

120
124
128

在 Linux kernel 找出類似 align_up 的程式碼,說明其用法

在 <include/linux/mm.h> 和 <include/linux/kernel.h> 有定義出
PAGE_ALIGNALIGN
#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)

其中 PAGE_SIZE 在 <arch/x86/include/asm/page_types.h> 中定義

/* 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
/* Memops alloc requires size to be page aligned. */
unsigned long size = PAGE_ALIGN(vb->planes[plane].length);

測驗
ζ