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的说明。