系统调用入口:
int __sys_socket(int family, int type, int protocol)// net/socket.c
{
retval = sock_create(family, type, protocol, &sock);//
if (retval < 0)
return retval;
return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
}
第一个函数:
int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
}
__sock_create函数:
int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
{
err = pf->create(net, sock, protocol, kern);
}
pf->create:
// 对于ipv6
static const struct net_proto_family inet6_family_ops = { // net/ipv6/af_inet6.c
.family = PF_INET6,
.create = inet6_create,
.owner = THIS_MODULE,
};
static int inet6_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot, kern);// 创建sock 结构体
if (inet->inet_num) {
/* It assumes that any protocol which allows
* the user to assign a number at socket
* creation time automatically shares.
*/
inet->inet_sport = htons(inet->inet_num);
err = sk->sk_prot->hash(sk);// hash:
if (err) {
sk_common_release(sk);
goto out;
}
}
if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk);//
if (err) {
sk_common_release(sk);
goto out;
}
}
}
继续 hash函数,把套接字管理起来!!!
struct proto tcpv6_prot = { // tcp_ipv6.c
...
.hash = inet6_hash,
}
int inet6_hash(struct sock *sk)
{
...
err = __inet_hash(sk, NULL);
...
继续:
int __inet_hash(struct sock *sk, struct sock *osk)
{
struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
struct inet_listen_hashbucket *ilb;
int err = 0;
if (sk->sk_state != TCP_LISTEN) {// 两种套接字,监听、已连接套接字。
inet_ehash_nolisten(sk, osk);
return 0;
}
WARN_ON(!sk_unhashed(sk));
ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
spin_lock(&ilb->lock);
if (sk->sk_reuseport) {
err = inet_reuseport_add_sock(sk, ilb);
if (err)
goto unlock;
}
if (IS_ENABLED(CONFIG_IPV6) && sk->sk_reuseport &&
sk->sk_family == AF_INET6)
hlist_add_tail_rcu(&sk->sk_node, &ilb->head);
else
hlist_add_head_rcu(&sk->sk_node, &ilb->head);
inet_hash2(hashinfo, sk);
ilb->count++;
sock_set_flag(sk, SOCK_RCU_FREE);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
unlock:
spin_unlock(&ilb->lock);
return err;
}