欢迎来到天天文库
浏览记录
ID:45566155
大小:65.72 KB
页数:9页
时间:2019-11-14
《Linux内核网络协议栈5-socket端口管理》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、Linux内核网络协议栈5—socket端口管理作者:zhuyoong一.前情回顾上一节《socket地址绑定》中提到,应用程序传递过来的端口在内核中需耍检查端口是否可用:1.if(sk->sk_pr>get_port(sk,snum)){2.inet・>saddr=inercv_saddr=0;3・err=-EADDRINUSE;4.gotoout_release_sock;5・}按照前面的例子来分析,这里是调用了tcp_prot结构变量屮的get_prot函数指针,该函数位于net/ipv4/lnet_connection_s
2、ock.c中;这个函数比较长,也是我们今天要分析的重点;二.端口的管理1、端口管理数据结构Linux内核将所冇socket使用时的端口通过一个哈希表来管理,该哈希表存放在全局变量tcp_hashinfo中,通过tcp_prot变量的h成员引用,该成员是一个联合类型;对于tcp套接字类型,其引用存放在h・hashinfo成员中;卜•面是tcp_hashinfo的结构体类型:1.structinet_hashinfo{2・structinet_ehash_bucket*ehash;3・rwlock_t*ehash_locks;4・un
3、signedintehash_size;5・Aunsignedintehash_locks_mask;O•7・structinet_bind_hashbucket*bhash;//管理端口的哈希农8・unsignedintbhash_size;//端口哈希表的大小9・10.structhlist_headlistening_hash[INET_LHTABLE_SIZE];rwlock_tlhashlockcachelinealigne12・atomic_tlhash_users;wait_queue_head_tlhash_wai
4、t;14.structkmem_cache*bind_bucket_cachep;//哈希表结构高速缓存15.}端口管理相关的,目前可以只关注加注释的这三个成员,其中bhash为已经哈希表结构,bhash_size为哈希表的大小;所有哈希表中的节点内存都是在bindbucketcachep高速缓存中分配;卜而看一下inetbindhashbucket结构体:1・structinet_bind_hashbucket{2・spinlock_tlock;3・structhlist__headchain;4・};5・structhlist
5、_head{6・structhlist_.node*first;7・};8.structhlist_node{9・structhlist_node*next,**pprev;10.};inet_bind_hashbucket是哈希桶结构,lock成员是用于操作时对桶进行•加锁,chain成员是相同哈希值的节点的链表;示意图如下:next2、默认端口的分配当应用程序没有指定端口时(如socket客户端连接到服务端时,会由内核从可用端口中分配一个给该socket);看看卜•面的代码(参见net/ipv4/Inct_conncction
6、_sock・c:inct_csk_gct_port()函数):1.if(!snum){2.intremaining,rover,low,high;3・4.get_local_port_range(&low,&high);5.remaining=(high-low)+1;6.rover=net_random()%remaining+low;7・8.do{9.head=&hashinfo・>bhash[inet_bhashfn(rover,hashinfo・>bhashsize)];10lock);
7、11.inet_bind_bucket_for_each(tb,node,&head・>chain)12.if(tb->ib_net==net&&tb->port==rover)13.gotonext;14.break;15.next:16.spin_unlock(&head・>lock);17.if(++rover>high)18・rover=low;19・}while(--remaining>0);20・21・ret=1;22・if(remaining<=0)23.gotofail;24・25・snum=rover;26・}这
8、里,随机端口的范围是32768^61000;上面代码的逻辑如下:1)从[32768,61000]中随机取一个端口rover;2)计算该端口的hash值,然后从全局变量tcp_hashinfo的哈希表bhash中取出相同哈希值的链表head;3)遍丿
此文档下载收益归作者所有