inet_hashinfo:
这是一个类型为tcp_hashinfo的全局变量,保存当前系统的各种状态的tcp_sock(包括established,listen和bind).
这是一个类型为tcp_hashinfo的全局变量,保存当前系统的各种状态的tcp_sock(包括established,listen和bind).
内核初始化调用tcp_init函数时会对该变量进行初始化.结构为:
struct inet_hashinfo {
struct inet_ehash_bucket *ehash; //established状态的tcp_sock<span style="font-family: Arial, Helvetica, sans-serif;">散列表</span>
struct inet_bind_hashbucket *bhash; //bind状态的tcp_sock<span style="font-family: Arial, Helvetica, sans-serif;">散列表</span>
unsigned int ehash_size //established状态的tcp_sock<span style="font-family: Arial, Helvetica, sans-serif;">散列表</span>
unsigned int bhash_size; //bind状态的tcp_sock<span style="font-family: Arial, Helvetica, sans-serif;">散列表</span>长度
struct kmem_cache *bind_bucket_cachep; //bind类型的tcp_sock的slab
struct hlist_head listening_hash[INET_LHTABLE_SIZE] //listen状态的tcp_sock<span style="font-family: Arial, Helvetica, sans-serif;">散列表</span>
rwlock_t lhash_lock ____cacheline_aligned; //访问listening_hash的读写锁
atomic_t lhash_users; //有进程写该结构时加1,这时其他进程会放入lhash_wait等待
wait_queue_head_t lhash_wait;
};
当内核创建一个sock,并绑定端口之后,该套接字会被加到bhash中。接下来调用listen之后,该sock进入listen状态。内核调用inet_hash将该套接字放入
listening_hash散列表,这样可以快速的找到处于监听状态的套接字。最后,经过三步握手完成一个连接之后,套接字会被加入到ehash哈希表。
上述结构中三个哈希表看过去结构有点不同,listening_hash是一个数组,ehash和bhash只是一个指针。实际上三者的实现几乎是一样的,ehash和bhash
都是指向了一个长度分别为ehash_size和bhash_size的数组。这些数组就是一个哈希表。每一项都是一个链表,存储值相同的tcp_sock(这些sock可能是端口复用的)。
具体结构如下图所示: