分类: LINUX
2014-11-30 00:11:30
[前言]
一直想好好研究linux的网络实现,又不知从何入手,总是片面的学习,形不成体系。最近发现秦健老师的《追踪Linux TCP/IP 代码运行》,觉得是个不错的入口点,于是决定借此一来整合一下自己零碎的知识,二来希望对节后的工作有些帮助,何乐而不为。本文仅仅是介绍从调用socket函数到成功返回一个socket文件描述符之间所涉及到的重要函数以及其调用关系、代码位置等,该过程涉及的重要数据结构以及相关知识会有专门的介绍。
我们平常在网络编程中调用的socket()函数,实为GLIBC封装的库函数,该库函数实际功能采用汇编语言实现,最后通过0x80号软中断陷入内核,调用真正的系统调用程序。
|>> socket() :
|创建一个socket套接字
|int socket(int domain, int type, int protocol);
|glibc-2.20/sysdeps/unix/sysv/linux/i386/socket.S[43]
---|>> int $0x80 :
---|0x80号软中断用来陷入内核,然后调用系统调用的总入口system_call
---|---|>> system_call() :
---|---|系统调用的总入口,完全用汇编语言实现
---|---|asmlinkage int system_call(void);
---|---|linux-3.10.25/arch/x86/kernel/entry_64.S[608]
---|---|---|>> sys_socketcall() :
---|---|---|内核提供给socket通信的总入口
---|---|---|asmlinkage long sys_socketcall(int call, unsigned long __user *args);
---|---|---|linux-3.10.25/net/socket.c[2456]
点击(此处)折叠或打开
[二] 调用sys_socket创建socket和sock结构体
在Linux-3.10.25中socket系列函数(sys_xxx)在内核源码中都是用DEFINEX宏来定义,关于DEFINEX的定义请查看linux-3.10.25/include/linux/syscalls.h[170],至于为什么这样做不是我们关心的重点,使用这些宏转换后,这些函数的真面目与2.6系列内核中的定义没有什么不同,或者我们也可以直接查看这些函数在头文件中的声明来确定这些函数的原型。
|>>sys_socket() :
|asmlinkage long sys_socket(int family, int type, int protocol);
|SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
|linux-3.10.25/net/socket.c[1361]
---|>> sock_create() :
---|直接调用__scok_create()函数执行创建任务
---| int sock_create(int family, int type, int protocol, struct socket **res)
---|linux-3.10.25/net/socket.c[1349]
---|---|>> __sock_create() :
---|---|创建socket和sock结构体
---|---|int __sock_create(struct net *net, int family, int type, int protocol, struct socket **res, int kern)
---|---| linux-3.10.25/net/socket.c[1236]
---|---|---|>> sock_alloc() :
---|---|---|创建socket结构体
---|---|---|static struct socket *sock_alloc(void)
---|---|---|linux-3.10.25/net/socket.c[531]
---|---|---|>>inet_create() :
---|---|---|创建scok结构体 ,在__scok_create函数中的1311行被调用
---|---|---|static int inet_create(struct net *net, struct socket *sock, int protocol, int kern)
---|---|---|linux-3.10.25/net/ipv4/af_inet.c[275]
在__sock_create()函数中linux系统创建了两个重要的数据结构,socket和sock结构体。Sock结构体根据使用的具体协议挂入socket结构体中,同时sock结构体中又包含了指向sk_buff结构的指针。sk_buff这个结构相信大家并不陌生,每个协议都是用该结构体来封装、运载数据包,也就说每一个数据包都用一个sk_buff结构体来表示。
|>> sock_alloc() :
|创建socket结构体
|static struct socket *sock_alloc(void)
|linux-3.10.25/net/socket.c[531]
---|>> new_inode_pseudo() :
---|给指定的超级块结构申请一个inode
---|struct inode *new_inode_pseudo(struct super_block *sb)
---| linux-3.10.25/fs/inode.c[904]
---|---|>> alloc_inode() :
---|---|给指定的超级块结构申请一个inode
---|---|static struct inode *alloc_inode(struct super_block *sb)
---|---|linux-3.10.25/fs/inode.c[202]
---|---|---|>>sock_alloc_inode() :
---|---|---|给指定的超级块结构申请一个inode,在alloc_inode函数中207行被调用
---|---|---|static struct inode *sock_alloc_inode(struct super_block *sb)
---|---|---|linux-3.10.25/net/socket.c[241]
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
|>> inet_create() :
|创建并设置sock结构体,在__sock_create函数中1311行被调用
| static int inet_create(struct net *net, struct socket *sock, int protocol, int kern)
| linux-3.10.25/net/ipv4/af_inet.c[275]
---|>>sk_alloc() :
---|创建并初始化sock结构体
---|struct sock *sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot)
---| linux-3.10.25/core/scok.c[1314]
---|---|>>sk_prot_alloc() :
---|---|创建socket结构体
---|---|static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, int family)
---|---|linux-3.10.25/core/scok.c[1225]
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开