热度 15
2015-2-13 20:53
1160 次阅读|
0 个评论
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,需要多次调用它。 http://www.360doc.com/content/09/0517/11/26398_3536647.shtml =========================================================== 这篇文档里面是非常有价值的关于sys_ioctl - inet_ioctl的说明。