TCP建立socket的第一步,是调用socket函数,先看socket函数的实现。
socket系统调用调用sys_socketcall, 最终会调用sys_socket函数(这部分后续需要补充完整的跟踪过程)
sys_socket的实现在socket.c中,但是在3.5.3的内核源码中已经找不到这个函数了。这个函数的定义是下面这个SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol),函数头(sys_socket)是通过宏SYSCALL_DEFINE3展开得到的。
先看下这个宏是怎么实现的,因为接下来还会看到好多这种宏
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#ifdef CONFIG_FTRACE_SYSCALLS
#define SYSCALL_DEFINEx(x, sname, ...) \
static const char *types_##sname[] = {\
__SC_STR_TDECL##x(__VA_ARGS__)\
}; \
static const char *args_##sname[] = {\
__SC_STR_ADECL##x(__VA_ARGS__)\
}; \
SYSCALL_METADATA(sname, x);\
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#else
#define SYSCALL_DEFINEx(x, sname, ...) \
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#endif
不管是否定义宏CONFIG_FTRACE_SYSCALLS(做什么用的),最终都会执行宏__SYSCALL_DEFINEx
#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
#define __SYSCALL_DEFINEx(x, name, ...) \
asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));\
static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__));\
asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))\
{ \
__SC_TEST##x(__VA_ARGS__);\
return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));\
} \
SYSCALL_ALIAS(sys##name, SyS##name);\
static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))
#else /* CONFIG_HAVE_SYSCALL_WRAPPERS */
#define SYSCALL_DEFINE(name) asmlinkage long sys_##name
#define __SYSCALL_DEFINEx(x, name, ...) \
asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))
#endif /* CONFIG_HAVE_SYSCALL_WRAPPERS */
宏(CONFIG_HAVE_SYSCALL_WRAPPERS)(to trace),最后按红色部分展开,__SC_DECL##x宏有以下几种:
#define __SC_DECL1(t1, a1) t1 a1
#define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)
#define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)
#define __SC_DECL4(t4, a4, ...) t4 a4, __SC_DECL3(__VA_ARGS__)
#define __SC_DECL5(t5, a5, ...) t5 a5, __SC_DECL4(__VA_ARGS__)
#define __SC_DECL6(t6, a6, ...) t6 a6, __SC_DECL5(__VA_ARGS__) (这种方式还是有点用的,可以把__VA_ARGS__展开)
这个宏,最终把参数按定义的原封不动的展开,类似的还有 __SC_CAST,__SC_LONG,但是他们会对参数进行变换,比如int a会被__SC_CAST变成(int) a, __SC_LONG变成long a
到此为止,一切都明朗了,但是有个问题,为什么要使用宏来定义,搞的如此复杂,为什么不直接定义一个函数sys_socket这样又简单,又清晰
网上搜了下,有如下原因:
1. 寄存器高32位未清0的内核漏洞,可以看这里http://blog.csdn.net/yeyuangen/article/details/7309692