syscall SYSCALL_DEFINE*()实现

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

原文地址:https://www.cnblogs.com/aspirs/p/15533414.html