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

 SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
unsigned int, flags)
{
/* 不支持64位采用32位兼容标记 */
if (flags & MSG_CMSG_COMPAT)
return -EINVAL; /* 接收消息 */
return __sys_recvmsg(fd, msg, flags);
}
 /*
* BSD recvmsg interface
*/ long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
{
int fput_needed, err;
struct msghdr msg_sys;
struct socket *sock; /* 获取socket */
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out; /* 接收信息 */
err = ___sys_recvmsg(sock, msg, &msg_sys, flags, ); fput_light(sock->file, fput_needed);
out:
return err;
}
 static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
struct msghdr *msg_sys, unsigned int flags, int nosec)
{
struct compat_msghdr __user *msg_compat =
(struct compat_msghdr __user *)msg;
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack;
unsigned long cmsg_ptr;
int len;
ssize_t err; /* kernel mode address */
struct sockaddr_storage addr; /* user mode address pointers */
struct sockaddr __user *uaddr;
int __user *uaddr_len = COMPAT_NAMELEN(msg); msg_sys->msg_name = &addr; /* 需要做64位采用32位兼容 */
if (MSG_CMSG_COMPAT & flags)
/* 从64位消息头拷贝到32位消息头 */
err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
else
/* 拷贝消息头 */
err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
if (err < )
return err; /* 控制信息 */
cmsg_ptr = (unsigned long)msg_sys->msg_control;
msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); /* We assume all kernel code knows the size of sockaddr_storage */
msg_sys->msg_namelen = ; /* 设置非阻塞标记 */
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT; /* 调用读取函数 */
err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
if (err < )
goto out_freeiov;
len = err; /* 拷贝地址到用户空间 */
if (uaddr != NULL) {
err = move_addr_to_user(&addr,
msg_sys->msg_namelen, uaddr,
uaddr_len);
if (err < )
goto out_freeiov;
} /* 拷贝标志到用户空间 */
err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
COMPAT_FLAGS(msg));
if (err)
goto out_freeiov; /* 拷贝控制信息长度到用户空间 */
if (MSG_CMSG_COMPAT & flags)
err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
&msg_compat->msg_controllen);
else
err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
&msg->msg_controllen);
if (err)
goto out_freeiov;
err = len; out_freeiov:
kfree(iov);
return err;
}

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

套接字之recvmsg系统调用的更多相关文章

  1. 套接字之recv系统调用

    recv系统调用对sys_recvfrom进行了简单的封装,只是其中不包含地址信息,其只需要从建立连接的另一端接收信息: /* * Receive a datagram from a socket. ...

  2. 套接字之send系统调用

    send系统调用只是对sendto系统调用进行了封装,传递的参数不包含目的地址信息,数据会发送到已经建立连接的另一端的地址: /* * Send a datagram down a socket. * ...

  3. 套接字之close系统调用

    close系统调用用于关闭文件描述符,其系统调用实现如下所示: / * Careful here! We test whether the file pointer is NULL before * ...

  4. 套接字之recvfrom系统调用

    recvfrom系统调用通过用户传入的接收空间构造msghdr,并且调用sock_recvmsg,该函数调用socket操作的recvmsg函数sock->ops->recvmsg,ipv ...

  5. 套接字之sendmsg系统调用

    sendmsg系统调用允许在用户空间构造消息头和控制信息,用此函数可以发送多个数据缓冲区的数据,并支持控制信息:当调用进入内核后,会将用户端的user_msghdr对应拷贝到内核的msghdr中,然后 ...

  6. 套接字之sendto系统调用

    sendto系统调用用于向指定的目的地址发送数据,其系统调用的流程比较容易理解,如下面所示,其主要完成 (1)将用户数据组织成msghdr,(2)而后调用socket操作的sendmsg:ipv4对应 ...

  7. 套接字之select系统调用

    select是IO多路复用的一种方式,用来等待一个列表中的多个描述符的可读可写状态: SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_ ...

  8. 套接字之msghdr结构

    用户端在使用sendmsg/recvmsg发送或者接收数据时,会使用msghdr来构造消息,其对应的内核结构为user_msghdr:其中msg_iov向量指向了多个数据区,msg_iovlen标识了 ...

  9. 【 Linux 】Linux套接字简要说明

    Linux套接字    源IP地址和目的IP地址以及源端口和目标端口号的组合称为套接字.其作用于标识客户端请求的服务器和服务. 套接字,支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间 ...

随机推荐

  1. gitlab操作笔记

    基本命令 准备 1. 安装所需命令 sudo yum install curl openssh-server openssh-clients postfix cronie -y2. 安装SSH sud ...

  2. 帝国cms 描述和关键词动态获取

    之前列表页首页和内容页调用的关键词和描述的字段不一样,所以说需要写好几套模板. 下边这个判断就不用像之前做几套模板了,通过判断获取不一样的字段. $GLOBALS[navinfor] 这个判断的是此页 ...

  3. Vue实例:vue2.0+ElementUI框架开发pc项目

    开发前准备 vue.js2.0中文,项目所使用的js框架 vue-router,vue.js配套路由 vuex,状态管理 Element,UI框架 1,根据官方指引,构建项目框架 安装vue npm ...

  4. Linu目录结构和创建用户

    具体目标结构 ./bin [重点] (/usr/bin./usr/local/bin) ●是Binary的速写,这个目录存放着最经常使用的命令. ./sbin (/usr/sbin./usr/loca ...

  5. mysql alter 语句用法,添加、修改、删除字段、索引、主键等

    修改表名: ALTER  TABLE admin_user RENAME TO a_use //增加主键 [sql] view plaincopy alter table tabelname add  ...

  6. Jenkins+GitHub 项目环境搭建和发布脚本(二)

    Jenkins+gitHub项目搭建配置 项目发布脚本 profilesScript.sh (支持不同环境配置文件) #!/bin/bash ACTIVE=$ JENKINS_PATH=/var/li ...

  7. 修改Anaconda启动时默认路径

    1.找到Anoconda启动快捷方式,入下图: 2.右击点击属性,进入下图: 3.将第三行的 目标(T):  ......D:\Anoconda\Scripts\jupyter-notebook-sc ...

  8. 织梦网站dedecms防止挂马的思路

    DedeCms做为国内使用最为广泛使用人数最多的CMS之一,经常爆出漏洞,每个漏洞的爆出,影响都是一大片,轻则被人挂广告.弹框,重则服务器成为肉机,宝贵数据丢失.那么有什么办法可以提高DedeCms的 ...

  9. 介绍知道的http返回的状态码

    100    Continue    继续.客户端应继续其请求 101    Switching Protocols    切换协议.服务器根据客户端的请求切换协议.只能切换到更高级的协议,例如,切换 ...

  10. gson转换问题

    list集合中integer问题 List<Integer> lists= gson.fromJson(params.get("lists"), new TypeTok ...