• 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

  • 相关阅读:
    C++中的模板编程
    C++中的抽象类
    C++中的多态
    C++中的继承
    操作符重载(二)
    操作符重载(一)
    C++中的类与对象模型
    [八省联考2018] 劈配 (网络流+二分)
    CF51F Caterpillar (边双+树形DP)
    CF36E Two Paths (欧拉回路+构造)
  • 原文地址:https://www.cnblogs.com/aspirs/p/15533414.html
Copyright © 2020-2023  润新知