Linux解析内核源代码——传输控制块诞生
原创文章是freas_1990,转载请注明出处:http://blog.csdn.net/freas_1990/article/details/23795587
在Linux 2.6一旦(不包含2.6,对于更详细的调查是不是版本号),控制块的概念,各种协议的状态管理还出于比較混乱的状态。
Linux 2.6以后。传输控制块机制使代码看起来比較规整了。
创建传输控制块:
/* * Create an inet socket. */ static int inet_create(struct socket *sock, int protocol) { struct sock *sk; struct list_head *p; struct inet_protosw *answer; struct inet_opt *inet; int err = -ENOBUFS; sock->state = SS_UNCONNECTED; sk = sk_alloc(PF_INET, GFP_KERNEL, inet_sk_size(protocol), inet_sk_slab(protocol)); if (!sk) goto out; /* Look for the requested type/protocol pair. */ answer = NULL; rcu_read_lock(); list_for_each_rcu(p, &inetsw[sock->type]) { answer = list_entry(p, struct inet_protosw, list); /* Check the non-wild match. */ if (protocol == answer->protocol) { if (protocol != IPPROTO_IP) break; } else { /* Check for the two wild cases. */ if (IPPROTO_IP == protocol) { protocol = answer->protocol; break; } if (IPPROTO_IP == answer->protocol) break; } answer = NULL; } err = -ESOCKTNOSUPPORT; if (!answer) goto out_sk_free; err = -EPERM; if (answer->capability > 0 && !capable(answer->capability)) goto out_sk_free; err = -EPROTONOSUPPORT; if (!protocol) goto out_sk_free; err = 0; sock->ops = answer->ops; sk->sk_prot = answer->prot; sk->sk_no_check = answer->no_check; if (INET_PROTOSW_REUSE & answer->flags) sk->sk_reuse = 1; rcu_read_unlock(); inet = inet_sk(sk); if (SOCK_RAW == sock->type) { inet->num = protocol; if (IPPROTO_RAW == protocol) inet->hdrincl = 1; } if (ipv4_config.no_pmtu_disc) inet->pmtudisc = IP_PMTUDISC_DONT; else inet->pmtudisc = IP_PMTUDISC_WANT; inet->id = 0; sock_init_data(sock, sk); sk_set_owner(sk, THIS_MODULE); sk->sk_destruct = inet_sock_destruct; sk->sk_zapped = 0; sk->sk_family = PF_INET; sk->sk_protocol = protocol; sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; inet->uc_ttl = -1; inet->mc_loop = 1; inet->mc_ttl = 1; inet->mc_index = 0; inet->mc_list = NULL; #ifdef INET_REFCNT_DEBUG atomic_inc(&inet_sock_nr); #endif if (inet->num) { /* It assumes that any protocol which allows * the user to assign a number at socket * creation time automatically * shares. */ inet->sport = htons(inet->num); /* Add to protocol hash chains. */ sk->sk_prot->hash(sk); } if (sk->sk_prot->init) { err = sk->sk_prot->init(sk); if (err) inet_sock_release(sk); } out: return err; out_sk_free: rcu_read_unlock(); sk_free(sk); goto out; }
这里的sk_alloc是重点:
sk = sk_alloc(PF_INET, GFP_KERNEL, inet_sk_size(protocol), inet_sk_slab(protocol));
inet_sk_size定义例如以下:
static __inline__ int inet_sk_size(int protocol) { int rc = sizeof(struct tcp_sock); if (protocol == IPPROTO_UDP) rc = sizeof(struct udp_sock); else if (protocol == IPPROTO_RAW) rc = sizeof(struct raw_sock); return rc; }
它会依据详细的传输层协议定义返回对应的传输控制块的大小。
在socket里,sock指针仅仅是一个“泛型”,它可能指向struct sock,struct tcp_sock,struct udp_sock,根据该协议的细节。
版权声明:本文博客原创文章,博客,未经同意,不得转载。