介绍
由于tcp过于复杂,取个巧,全篇以udp连接来说明一下,内核版本对应2.6.32。
select说到底是和网络套接字打交到的,从网络套接字创建的过程(socket和bind系统调用),来了解一下socket、sock、inet_sock等数据结构之间的联系,以及创建一个监听套接字之后到底发生了哪些变化。
储备知识点
此处是一些琐碎的知识点,以便更好的理解select系统调用用到的数据结构与调用函数,想了解select的朋友也可直接跳到select部分阅读。
一些初始化操作
af_inet.c文件,既ipv4的网络处理模块,在inet_init函数中,进行了ipv4协议相关的各类数据结构初始化操作。
- proto_register将udp_prot通过其节点node挂载到全局的proto_list链表上。使用kmem_cache_create对prot->slab创建了slab缓存区,其每一个slab空间大小为struct udp_sock的结构大小。在udp_sock结构中,其inet成员为inet_sock结构,其中的第一个参数为struct sock sk,通常可直接将sock结构的指针强转为udp_sock来使用。
struct udp_sock {
struct inet_sock inet;
int pending;
__u16 len;
}
- 使用sock_register函数,将inet_family_ops全局变量(struct net_proto_family结构类型)放到全局数组net_families中去,使用协议族值作为下标,此处为AF_INET。 inet_family_ops中包括了create函数,既inet_create。
- 使用inet_add_protocol将udp_protocol全局变量(struct net_protocol结构类型)放到全局数组inet_protos中去,使用协议类型IPPROTO_UDP计算哈希值作为下标。
struct net_protocol udp_protocol = {
.handler = udp_rcv,
.gso_send_check = udp4_ufo_send_check,
.gso_segment = udp4_ufo_fragment,
};
- 初始化inetsw 链表头数组,其结构为 struct list_head数组,以协议类型为下标,如SOCK_DGRAM。
- 初始化inetsw_array数组,其结构为struct inet_protosw数组。
struct inet_protosw inetsw_array[] =
{
........
{
.type = SOCK_DGRAM,
protocol = IPPROTO_UDP,
prot = udp_prot,(struct prot结构)
ops = inet_dgram_ops, (struct proto_ops结构)
},
........
}
- 进行inet_protosw注册,既将inetsw_array中的每个元素,通过protocol下标(如SOCK_DGRAM)挂载到对应的inetsw链表中去,挂载节点为inet_protos