linux内核syscall_define6,为AM335x移植Linux内核主线代码(40)什么是SYSCALL_DEFINEx

do_vfs_ioctl函数是一个非常重要的函数,如果在它里面加入打印信息,会发现系统启动时它被执行了很多次,系统运行时也在不断的执行它。它被下面这个函数调用:

SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)

{

int error;

struct fd f = fdget(fd);

if (!f.file)

return -EBADF;

error = security_file_ioctl(f.file, cmd, arg);

if (!error)

error = do_vfs_ioctl(f.file, fd, cmd, arg);

fdput(f);

return error;

}

在include/linux/syscalls.h中有SYSCALL_DEFINE3的定义:

#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__)

#define SYSCALL_METADATA(sname, nb, ...)

#define __SYSCALL_DEFINEx(x, name, ...)                                 \

asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \

__attribute__((alias(__stringify(SyS##name))));         \

static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));  \

asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));      \

asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))       \

{                                                               \

long ret = SYSC##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 SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))

原始的语句是这样的,可以发现参数的类型定义和值都是要使用“,”的:

SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)

按照宏展开,得到下面的语句(注意“##”的作用是字符串连接,而__VA_ARGS__则是代表变参):

SYSCALL_DEFINEx(3, _ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)

由于没有定义CONFIG_FTRACE_SYSCALLS,因此SYSCALL_METADATA(sname, nb, ...)的宏展开为空,那么就剩下了下面的__SYSCALL_DEFINEx(x, name, ...),将_ioctl语句按照这个宏再展开:

asmlinkage long sys_ioctl(__MAP(3,__SC_DECL,unsigned int, fd, unsigned int, cmd, unsigned long, arg)) \

__attribute__((alias(__stringify(SyS_ioctl)))); \

static inline long SYSC_ioctl(__MAP(3,__SC_DECL,unsigned int, fd, unsigned int, cmd, unsigned long, arg)); \

asmlinkage long SyS_ioctl(__MAP(3,__SC_LONG,unsigned int, fd, unsigned int, cmd, unsigned long, arg)); \

asmlinkage long SyS_ioctl(__MAP(3,__SC_LONG,unsigned int, fd, unsigned int, cmd, unsigned long, arg)) \

{ \

long ret = SYSC_ioctl(__MAP(3,__SC_CAST,unsigned int, fd, unsigned int, cmd, unsigned long, arg)); \

__MAP(3,__SC_TEST,unsigned int, fd, unsigned int, cmd, unsigned long, arg); \

__PROTECT(3,ret,__MAP(3,__SC_ARGS,unsigned int, fd, unsigned int, cmd, unsigned long, arg)); \

return ret; \

} \

static inline long SYSC_ioctl(__MAP(3,__SC_DECL,unsigned int, fd, unsigned int, cmd, unsigned long, arg))

再来看看__MAP的作用,它是用来组合参数的(现在知道为什么这个是3了吧,因为有3对形参):

__MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to

m(t1, a1), m(t2, a2), ..., m(tn, an)

接下来按照__MAP的含义再来展开:

asklingage long sys_ioctl(__SC_DECL(unsigned int, fd), __SC_DECL(unsigned int, cmd), __SC_DECL(unsigned long, arg)) \

__attribute__((alias(__stringify(SyS_ioctl)))); \

static inline long SYSC_ioctl(__SC_DECL(unsigned int, fd), __SC_DECL(unsigned int, cmd), __SC_DECL(unsigned long, arg)); \

asmlingkage long SyS_ioctl(__SC_LONG(unsigned int, fd), __SC_LONG(unsigned int, cmd), __SC_LONG(unsigned long, arg)); \

asmlingkage long SyS_ioctl(__SC_LONG(unsigned int, fd), __SC_LONG(unsigned int, cmd), __SC_LONG(unsigned long, arg)) \

{ \

long ret = SYSC_ioctl(__SC_CAST(unsigned int, fd), __SC_CAST(unsigned int, cmd), __SC_CAST(unsigned long, arg)); \

__SC_TEST(unsigned int, fd), __SC_TEST(unsigned int, cmd), __SC_TEST(unsigned long, arg); \

__PROTECT(3,ret, __SC_ARGS(unsigned int, fd), __SC_ARGS(unsigned int, cmd), __SC_ARGS(unsigned long, arg)); \

return ret; \

} \

static inline long SYSC_ioctl(__SC_DECL(unsigned int, fd), __SC_DECL(unsigned int, cmd), __SC_DECL(unsigned long, arg))

现在再按照__SC_*的宏定义展开(暂时忽略类型转换的部分,另外__stringify是字符串化的意思):

asklingage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) \

__attribute__((alias("SyS_ioctl"))); \

static inline long SYSC_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); \

asmlingkage long SyS_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)); \

asmlingkage long SyS_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)) \

{ \

long ret = SYSC_ioctl((unsigned int)fd, (unsigned int)cmd, (unsigned long)arg)); \

__SC_TEST(unsigned int, fd), __SC_TEST(unsigned int, cmd), __SC_TEST(unsigned long, arg); \

asmlinkage_protect(3,ret, fd, cmd, arg); \

return ret; \

} \

static inline long SYSC_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)

写到这里我已经在深深的。。。深深的。。。深深的怀疑自己的智商了。。。

中间还是有很多代码不明白啊~~~

不管怎样,这段代码的功能是,定义了sys_ioctl,为了进行Ethernet,需要多次调用它。

https://www.360doc.com/content/09/0517/11/26398_3536647.shtml

===========================================================

这篇文档里面是非常有价值的关于sys_ioctl -> inet_ioctl的说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值