linux-kernel 3.5.3Tcp系统调用,源码分析1-宏SYSCALL_DEFINE
2012-09-11 20:28
531 查看
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的内核漏洞,可以看这里/article/2793828.html
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的内核漏洞,可以看这里/article/2793828.html
相关文章推荐
- linux-kernel 3.5.3Tcp系统调用,源码分析6-bind系统调用
- linux-kernel 3.5.3Tcp系统调用,源码分析2-sys_socket & sock_create
- linux-kernel 3.5.3Tcp系统调用,源码分析4-inet_init
- linux-kernel 3.5.3Tcp系统调用,源码分析5-原子操作
- linux-kernel 3.5.3Tcp系统调用,源码分析7-listen系统调用
- linux-kernel 3.5.3Tcp系统调用,源码分析3-inet_create
- 【转】Linux-2.6.25 select系统调用源码分析
- 《第一篇 从linux 0.11系统初始化main.c的fork()函数调用分析内核源码》
- Linux-2.6.25 select系统调用源码分析
- Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理
- linux2.6.9 poll系统调用源码分析
- Linux-2.6.25 select系统调用源码分析
- linux系统调用SYSCALL_DEFINE
- linux嵌入式系统开发之触摸屏---驱动篇(下/源码分析)
- Linux的IO系统常用系统调用及分析
- linux内核剖析---Linux系统调用详解(实现机制分析)
- linux系统调用实现代码分析
- Linux系统调用的实现机制分析
- linux内存源码分析 - 伙伴系统(初始化和申请页框)
- Linux网络协议源代码分析 之 系统调用