网络子系统78_inet套接字创建
// inet协议族控制块 // 1.在inet_init中,由sock_register(&inet_family_ops)注册给系统 // 2.在sys_socket系统调用中,通过协议族号查找对应的协议控制块,然后由 // 具体协议控制块的create函数创建套接字 1.1 static const struct net_proto_family inet_family_ops = { .family = PF_INET, .create = inet_create, .owner = THIS_MODULE, }; // 创建inet协议族的socket套接字 // 步骤: // 1.更具套接字类型,协议号,查找指定协议 // 2.初始化套接字操作集合(socket->ops) // 3.分配sock结构,初始化sock->sk_prot指向inet_protosw->prot // 4.初始化sock,建立struct sock与struct socket的连接 1.2 static int inet_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; struct inet_protosw *answer; struct inet_sock *inet; struct proto *answer_prot; int err; //未连接状态 sock->state = SS_UNCONNECTED; lookup_protocol: err = -ESOCKTNOSUPPORT; rcu_read_lock(); //同一协议族下边具有相同套接字类型的多个不同协议 list_for_each_entry_rcu(answer, &inetsw[sock->type], list) { err = 0; if (protocol == answer->protocol) { if (protocol != IPPROTO_IP) break; } else { //指定IPPROTO_IP表示匹配默认的套接字类型 if (IPPROTO_IP == protocol) { protocol = answer->protocol; break; } //套接字类型的协议号为IPPROTO_IP,表示可以与任何协议匹配 if (IPPROTO_IP == answer->protocol) break; } err = -EPROTONOSUPPORT; } //如果模块没有加载,加载协议模块 ... //初始化套接字操作,协议类型 sock->ops = answer->ops; // (struct proto_ops) answer_prot = answer->prot; // (struct proto) answer_no_check = answer->no_check; answer_flags = answer->flags; rcu_read_unlock(); err = -ENOBUFS; //分配sock结构 sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot); if (sk == NULL) goto out; ... //建立struct sock与struct socket的联系 sock_init_data(sock, sk); ... out: return err; out_rcu_unlock: rcu_read_unlock(); goto out; } // struct sock结构初始化 // 1.分配sock的队列 // 2.初始化sock各字段 // 3.设置sock->sk_socket字段指向socket 1.3 void sock_init_data(struct socket *sock, struct sock *sk) { //分配sock的队列 skb_queue_head_init(&sk->sk_receive_queue); skb_queue_head_init(&sk->sk_write_queue); skb_queue_head_init(&sk->sk_error_queue); #ifdef CONFIG_NET_DMA skb_queue_head_init(&sk->sk_async_wait_queue); #endif sk->sk_send_head = NULL; init_timer(&sk->sk_timer); sk->sk_allocation = GFP_KERNEL; //接收,发送缓存的大小 sk->sk_rcvbuf = sysctl_rmem_default; sk->sk_sndbuf = sysctl_wmem_default; sk->sk_state = TCP_CLOSE; //sk->sk_socket = socket sk_set_socket(sk, sock); sock_set_flag(sk, SOCK_ZAPPED); if (sock) { sk->sk_type = sock->type; sk->sk_wq = sock->wq; sock->sk = sk; } else sk->sk_wq = NULL; sk->sk_state_change = sock_def_wakeup; sk->sk_data_ready = sock_def_readable; sk->sk_write_space = sock_def_write_space; sk->sk_error_report = sock_def_error_report; sk->sk_destruct = sock_def_destruct; sk->sk_frag.page = NULL; sk->sk_frag.offset = 0; sk->sk_peek_off = -1; sk->sk_peer_pid = NULL; sk->sk_peer_cred = NULL; sk->sk_write_pending = 0; sk->sk_rcvlowat = 1; sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_stamp = ktime_set(-1L, 0); smp_wmb(); atomic_set(&sk->sk_refcnt, 1); atomic_set(&sk->sk_drops, 0); }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。