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系统调用的实现分析>;

  • 相关阅读:
    & 微信支付对比
    # MySQL性能优化技巧
    & mysql简单定时增量全量备份
    & Mysql高级总结
    python面向对象
    django虚拟环境的安装
    Python 内置函数
    Python列表解析式
    函数练习
    Python装饰器
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11749336.html
Copyright © 2011-2022 走看看