• 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,根据该协议的细节。

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    学习之Struts2框架实现原理----个人理解
    The import java.util cannot be resolved The import javax.servlet cannot be resolved
    谈谈HashSet的存储原理
    RabbitMQ的问题
    剑指Offer:合并列表(25)
    剑指Offer:反转列表(24)
    剑指Offer:链表中倒数第 K 个结点(22)
    剑指Offer:调整数组顺序使奇数位于偶数前面(21)
    剑指Offer:机器人的运动范围(13)
    剑指Offer:变态跳台阶(10.4)
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4708634.html
Copyright © 2020-2023  润新知