2021.08.31

linux v5.14-rc7 x86-64

以mmap为例

TLDR: 系统调用表是sys_call_table, 系统调用实现是SYSCALL_DEFINE6(mmap)。 两者的符号名不同, 连接两者的桥梁是一系列宏。

详细:

系统调用表&调用表中的函数定义

@arch/x86/entry/syscall_64.c

/// __x64_sys_mmap,在/proc/kallsyms中可见

#define __SYSCALL(nr, sym) extern long __x64_##sym(const struct pt_regs *);
#include <asm/syscalls_64.h>
#undef __SYSCALL

#define __SYSCALL(nr, sym) __x64_##sym
sys_call_table[] = {
#include <asm/syscalls_64.h>
/// inclue展开包含
__SYSCALL(9, sys_mmap)
};

系统调用的实现

@arch/x86/kernel/sys_x86_64.c

/// 6表示该系统调用的参数数目为6
SYSCALL_DEFINE6(mmap, ...){...}

/// SYSCALL_DEFINEx展开为多个套壳函数的
/// 声明和定义,如下
@include/linux/syscalls.h
/// 下者override上者的__SYSCALL_DEFINEx宏,见
/// syscalls.h: 97 include syscall_wrapper.h
@arch/x86/include/asm/syscall_wrapper.h
/// se指符号扩展,参考:
/// arch/x86/include/asm/syscall_wrapper.h
__se_sys_mmap(...);
__do_sys_mmap(...);
__x64_sys_mmap(...);
__x64_sys_mmap(...){__se_sys_mmap(...);}
__se_sys_mmap(...){...
    __do_sys_mmap(...);
...}
__do_sys_mmap(...)
/// 后接上面的SYSCALL_DEFINE6具体实现

/// include/linux/syscalls.h: 89-98
/// 因为CONFIG_ARCH_HAS_SYSCALL_WRAPPER开启
/// 将不会生成sys_mmap()函数。
/// 若没有开启,syscalls.h生成sys_mmap过程如下
sys_mmap(...)
    __attribute__((alias "__se_sys_mmap"));
/// alias为gcc语法,
/// 用于之前已声明的同类型符号的别名