// 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);
}
网络子系统78_inet套接字创建,布布扣,bubuko.com
网络子系统78_inet套接字创建