zoukankan      html  css  js  c++  java
  • 套接字之recvmsg系统调用

    recvmsg系统调用允许用户指定msghdr结构来接收数据,可以将数据接收到多个缓冲区中,并且可以接收控制信息;接收信息过程与其他接收系统调用核心一致,都是调用传输层的接收函数进行数据接收;

     1 SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
     2         unsigned int, flags)
     3 {
     4     /* 不支持64位采用32位兼容标记 */
     5     if (flags & MSG_CMSG_COMPAT)
     6         return -EINVAL;
     7 
     8     /* 接收消息 */
     9     return __sys_recvmsg(fd, msg, flags);
    10 }
     1 /*
     2  *    BSD recvmsg interface
     3  */
     4 
     5 long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
     6 {
     7     int fput_needed, err;
     8     struct msghdr msg_sys;
     9     struct socket *sock;
    10 
    11     /* 获取socket */
    12     sock = sockfd_lookup_light(fd, &err, &fput_needed);
    13     if (!sock)
    14         goto out;
    15 
    16     /* 接收信息 */
    17     err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
    18 
    19     fput_light(sock->file, fput_needed);
    20 out:
    21     return err;
    22 }
     1 static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
     2              struct msghdr *msg_sys, unsigned int flags, int nosec)
     3 {
     4     struct compat_msghdr __user *msg_compat =
     5         (struct compat_msghdr __user *)msg;
     6     struct iovec iovstack[UIO_FASTIOV];
     7     struct iovec *iov = iovstack;
     8     unsigned long cmsg_ptr;
     9     int len;
    10     ssize_t err;
    11 
    12     /* kernel mode address */
    13     struct sockaddr_storage addr;
    14 
    15     /* user mode address pointers */
    16     struct sockaddr __user *uaddr;
    17     int __user *uaddr_len = COMPAT_NAMELEN(msg);
    18 
    19     msg_sys->msg_name = &addr;
    20     
    21     /* 需要做64位采用32位兼容 */
    22     if (MSG_CMSG_COMPAT & flags)
    23         /* 从64位消息头拷贝到32位消息头 */
    24         err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
    25     else
    26         /* 拷贝消息头 */
    27         err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
    28     if (err < 0)
    29         return err;
    30 
    31     /* 控制信息 */
    32     cmsg_ptr = (unsigned long)msg_sys->msg_control;
    33     msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
    34 
    35     /* We assume all kernel code knows the size of sockaddr_storage */
    36     msg_sys->msg_namelen = 0;
    37 
    38     /* 设置非阻塞标记 */
    39     if (sock->file->f_flags & O_NONBLOCK)
    40         flags |= MSG_DONTWAIT;
    41 
    42     /* 调用读取函数 */
    43     err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
    44     if (err < 0)
    45         goto out_freeiov;
    46     len = err;
    47 
    48     /* 拷贝地址到用户空间 */
    49     if (uaddr != NULL) {
    50         err = move_addr_to_user(&addr,
    51                     msg_sys->msg_namelen, uaddr,
    52                     uaddr_len);
    53         if (err < 0)
    54             goto out_freeiov;
    55     }
    56 
    57     /* 拷贝标志到用户空间 */
    58     err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
    59              COMPAT_FLAGS(msg));
    60     if (err)
    61         goto out_freeiov;
    62 
    63     /* 拷贝控制信息长度到用户空间 */
    64     if (MSG_CMSG_COMPAT & flags)
    65         err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
    66                  &msg_compat->msg_controllen);
    67     else
    68         err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
    69                  &msg->msg_controllen);
    70     if (err)
    71         goto out_freeiov;
    72     err = len;
    73 
    74 out_freeiov:
    75     kfree(iov);
    76     return err;
    77 }

    TCP层的recvmsg系统调用的实现函数为tcp_recvmsg,具体分析请移步<TCP层recvmsg系统调用的实现分析>;

  • 相关阅读:
    Educational Codeforces Round 88 (Rated for Div. 2) D. Yet Another Yet Another Task(枚举/最大连续子序列)
    Educational Codeforces Round 88 (Rated for Div. 2) A. Berland Poker(数学)
    Educational Codeforces Round 88 (Rated for Div. 2) E. Modular Stability(数论)
    Educational Codeforces Round 88 (Rated for Div. 2) C. Mixing Water(数学/二分)
    Codeforces Round #644 (Div. 3)
    Educational Codeforces Round 76 (Rated for Div. 2)
    Educational Codeforces Round 77 (Rated for Div. 2)
    Educational Codeforces Round 87 (Rated for Div. 2)
    AtCoder Beginner Contest 168
    Codeforces Round #643 (Div. 2)
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11749336.html
Copyright © 2011-2022 走看看