syscall SYSCALL_DEFINE*()实现
include/linux/syscalls.h
#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__) #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
#define SYSCALL_DEFINEx(x, sname, ...) \ SYSCALL_METADATA(sname, x, __VA_ARGS__) \ __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
上面__SYSCALL_DEFINEx()如果有define CONFIG_ARCH_HAS_SYSCALL_WRAPPER,将会用arch那边的实现,比如我这边的是arch64的,则是使用如下这个:
arch/arm64/include/asm/syscall_wrapper.h
#define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long __arm64_sys##name(const struct pt_regs *regs); \ ALLOW_ERROR_INJECTION(__arm64_sys##name, ERRNO); \ static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ asmlinkage long __arm64_sys##name(const struct pt_regs *regs) \ { \ return __se_sys##name(SC_ARM64_REGS_TO_ARGS(x,__VA_ARGS__)); \ } \ static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ __MAP(x,__SC_TEST,__VA_ARGS__); \ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ return ret; \ } \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
以SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
上述__SYSCALL_DEFINEx()里的参数x是3,name是_finit_module
看上述macro的实现,它实际是define了3个函数,展开来看,即是define了如下3个函数:
asmlinkage long __arm64_sys_finit_module(const struct pt_regs *regs)
static long __se_sys_finit_module(long fd, long uargs, long flags)
static inline long __do_sys_finit_module(int fd, const char __user * uargs, int flags)
其中__do_sys_finit_module()的实现就是SYSCALL_DEFINE3(finit_module)下的函数体。
其调用顺序是__arm64_sys_finit_module() -> __se_sys_finit_module() -> __do_sys_finit_module(),即最终会call到SYSCALL_DEFINE*()下的函数体。
__SC_LONG是强制转化为long类型,如果__VA_ARGS__里的类型是long long,则转为long long型,一般参数类型不会为long long,所以一般转化为long
__SC_CAST是将参数转化为__VA_ARGS__里define的类型
__SC_DECL是将SYSCALL_DEFINE里define的type、arg形成"type arg,"这样的参数列表,原本SYSCALL_DEFINE里type、arg之间是有“,”的。
看以看出SYSCALL_DEFINE后的数字表示这个syscall API参数列表里有几个参数,允许的参数数量为1-6,最多为6个。
以上分析基于linux 4.19