套接字的绑定、监听、连接和断开(2)

上面函数中先调用fget_light函数通过文件描述符返回对应的文件结构,然后调用函数sock_from_file函数返回该文件对应的套接字结构体地址,它存储在file->private_data属性中。

再回到sys_bind函数,在返回了对应的套接字结构之后,调用move_addr_to_kernel将用户地址空间的socket拷贝到内核空间。

然后调用INET协议族的操作集中bind函数inet_bind函数将socket地址(内核空间)和socket绑定。

int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)   {       struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;       struct sock *sk = sock->sk;       struct inet_sock *inet = inet_sk(sk);       unsigned short snum;       int chk_addr_ret;       int err;          //RAW类型套接字若有自己的bind函数,则使用之        if (sk->sk_prot->bind) {           err = sk->sk_prot->bind(sk, uaddr, addr_len);           goto out;       }       err = -EINVAL;       .....................           //地址合法性检查        chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);          /* Not specified by any standard per-se, however it breaks too       * many applications when removed.  It is unfortunate since       * allowing applications to make a non-local bind solves       * several problems with systems using dynamic addressing.       * (ie. your servers still start up even if your ISDN link       *  is temporarily down)       */       err = -EADDRNOTAVAIL;       if (!sysctl_ip_nonlocal_bind &&           !(inet->freebind || inet->transparent) &&           addr->sin_addr.s_addr != htonl(INADDR_ANY) &&           chk_addr_ret != RTN_LOCAL &&           chk_addr_ret != RTN_MULTICAST &&           chk_addr_ret != RTN_BROADCAST)           goto out;          snum = ntohs(addr->sin_port);       err = -EACCES;       if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))           goto out;          /*      We keep a pair of addresses. rcv_saddr is the one       *      used by hash lookups, and saddr is used for transmit.       *       *      In the BSD API these are the same except where it       *      would be illegal to use them (multicast/broadcast) in       *      which case the sending device address is used.       */       lock_sock(sk);          /* Check these errors (active socket, double bind). */       err = -EINVAL;       if (sk->sk_state != TCP_CLOSE || inet->inet_num)//如果sk的状态是CLOSE或者本地端口已经被绑定            goto out_release_sock;          inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;//设置源地址        if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)           inet->inet_saddr = 0;  /* Use device */          /* Make sure we are allowed to bind here. */       if (sk->sk_prot->get_port(sk, snum)) {           inet->inet_saddr = inet->inet_rcv_saddr = 0;           err = -EADDRINUSE;           goto out_release_sock;       }          if (inet->inet_rcv_saddr)           sk->sk_userlocks |= SOCK_BINDADDR_LOCK;       if (snum)           sk->sk_userlocks |= SOCK_BINDPORT_LOCK;       inet->inet_sport = htons(inet->inet_num);//设置源端口号,标明该端口已经被占用        inet->inet_daddr = 0;       inet->inet_dport = 0;       sk_dst_reset(sk);       err = 0;   out_release_sock:       release_sock(sk);   out:       return err;   }  

这样套接字绑定结束。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/740fb7ef0265377c907f15bce4328232.html