天天看點

核心中的UDP socket流程(6)——sendto

核心中的UDP socket流程(6)——sendto作者:[email protected]

現在開始新的API sendto,那麼就重新回到了socket.c檔案。

SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,

          unsigned, flags, struct sockaddr __user *, addr,

          int, addr_len)

{

     struct socket *sock;

     struct sockaddr_storage address;

     int err;

     struct msghdr msg;

     struct iovec iov;

     int fput_needed;

     sock = sockfd_lookup_light(fd, &err, &fput_needed);

     if (!sock)

          goto out;

通過函數sockfd_lookup_light和參數fd,來得到對應的sock。sockfd_lookup_light的實作比較簡單,fd就是程序的fdtable的索引。通過這個fd索引就可以得到對應的file指針,然後在從file指針中,得到sock的位址。

     iov.iov_base = buff;

     iov.iov_len = len;

     msg.msg_name = NULL;

     msg.msg_iov = &iov;

     msg.msg_iovlen = 1;

     msg.msg_control = NULL;

     msg.msg_controllen = 0;

     msg.msg_namelen = 0;

初始化iov和msg,因為這裡的消息傳遞方式采用的是4.4 BSD的消息傳遞方式。

struct msghdr {

     void * msg_name; /* Socket name */

     int msg_namelen; /* Length of name */

     struct iovec * msg_iov; /* Data blocks */

     __kernel_size_t msg_iovlen; /* Number of blocks */

     void * msg_control; /* Per protocol magic (eg BSD file descriptor passing) */

     __kernel_size_t msg_controllen; /* Length of cmsg list */

     unsigned msg_flags;

};

通過檢視msghdr結構體的定義,可以很容易的了解上述代碼。

    if (addr) {

          err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);

          if (err 0)

               goto out_put;

          msg.msg_name = (struct sockaddr *)&address;

          msg.msg_namelen = addr_len;

     }

     if (sock->file->f_flags & O_NONBLOCK)

          flags |= MSG_DONTWAIT;

     msg.msg_flags = flags;

如果sendto指定了addr,那麼首先将使用者空間的位址addr複制到kernel空間的address中,并用核心空間的address來初始化msg;如果該socket指定了O_NONBLOCK,那麼将flags設定上MSG_DONTWAIT,并将flags賦給msg.msg_flags。

err = sock_sendmsg(sock, &msg, len);

最後調用sock_sendmsg,将msg發送出去。

今天的sendto比較簡單,就這麼幾行代碼。明天學習sock_sendmsg。

繼續閱讀