所有的socket系统调用的总入口是sys_socketcall(),在include/linux/Syscalls.h中定义
其中,
@param call 标识接口编号,
@param args 是接口参数指针
接口编号的定义在 include/uapi/linux/net.h中定义
接口编号对应的参数个数在net/socket.c文件中的nargs数组中定义
在net/socket.c中有一个函数SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)便是socket调用的入口。
其中SYSCALL_DEFINE2是一个宏,定义在include/linux/syscall.h中
下面我们来展开展开SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args):
展开第一步得到:
SYSCALL_DEFINEx(2, _##socketcall, int, call, unsigned long __user *, args)
继续展开SYSCALL_DEFINEx,
SYSCALL_METADATA(_socketcall,2,int, call, unsigned long __user *, args) \
__SYSCALL_DEFINEx(2, _socketcall, int, call, unsigned long __user *, args)
SYSCALL_METADATA定义是空,忽略
继续展开__SYSCALL_DEFINEx,
asmlinkage long sys_socketcall(__MAP(2,__SC_DECL,__VA_ARGS__));\
static inline long SYSC_socketcall(__MAP(2,__SC_DECL,__VA_ARGS__)); \
asmlinkage long SyS_socketcall(__MAP(2,__SC_LONG,__VA_ARGS__))\
{\
long ret = SYSC_socketcall(__MAP(2,__SC_CAST,__VA_ARGS__));\
__MAP(2,__SC_TEST,__VA_ARGS__);\
__PROTECT(x, ret,__MAP(2,__SC_ARGS,__VA_ARGS__));\
return ret;\
} \
SYSCALL_ALIAS(sys_socketcall, SyS_socketcall);\
static inline long SYSC_socketcall(__MAP(2,__SC_DECL,__VA_ARGS__))
这时候的宏包括__MAP(),__SC_DECL 将其展开得到,其中__MAP是一个降维的过程,继续展开得到:
asmlinkage long sys_socketcall (int call, unsigned long __user *args);
static inline long SYSC_socketcall(int call, unsigned long __user *args);
asmlinkage long SyS_socketcall(int call, unsigned long __user *args)
{
long ret = SYSC_socketcall (call, ( unsigned long __user *)args);
return ret;
}
SYSCALL_ALIAS(sys_socketcall, SyS_socketcall);
static inline long SYSC_socketcall((int call, unsigned long __user *args)
到目前为止,sys_socketcall似乎并没有定义,原因是还有一个宏未展开,SYSCALL_ALIAS,在include/linux/linkage.h中定义,
在include/linux/export.h中定义,
将 SYSCALL_ALIAS(sys_socketcall, SyS_socketcall) 展开得到:
asm (".globl" sys_socketcall
".set" sys_socketcall, SyS_socketcall)
即sys_socketcall是SyS_socketcall的别名。
所以:展开之后是:
那内核为什么要这样呢?可以参考 http://blog.csdn.net/hxmhyp/article/details/22619729