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. springboot拦截中自动注入的组件为null问题解决方法

    一.写SpringUtil类来获取Springh管理的类实例,判断是否注入成功,如果没有注入成功重新获取注入 package com.util; import org.springframework. ...

  2. Ngnx工作原理(1)

    Nginx 是一个轻量级的HTTP 服务程序,相比其他服务器程序如Apache,Nginx占用内存少,稳定性高,并发处理能力强.同时Nginx 还是一个反向代理服务程序,和邮件代理服务程序.Nginx ...

  3. iOS资料大全

    1.创建自己的Xcode 模板类工程 https://mp.weixin.qq.com/s?__biz=MzAxMzE2Mjc2Ng==&mid=2652155923&idx=1&am ...

  4. css3中单位rem与.less结合布局

    rem是CSS3新增的一个相对单位(root em,根em),这个单位引起了广泛关注.这个单位与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素. ...

  5. php函数之strtr和str_replace的区别

    php字符串替换函数 strtr()有两种用法: strtr(string,from,to) 或者strtr(string,array) 首先针对strtr函数第一种方式: 我们看看下面的举例: &l ...

  6. linux下/etc/rc.d目录的介绍及redhat启动顺序

    init inittab rc0 rc1 rc2 rc3 rc5 rc6 rcS init.d init 系统启动超级进程 inittab 进程启动配置文件 rc0 - rc6 各启动级别的启动脚本 ...

  7. Delphi Memo组件

  8. 关于maven的repositories

    在maven repositories视图中,有local repositories和global repositories两种. local repositories是本地的库,默认目录在C:\Us ...

  9. Linux查看端口的连接数

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat | grep -i "80" | wc -l 2)统计ht ...

  10. mysql连接类与ORM的封装

    ORM: - ORM什么是? 类名 ---> 数据库表 对象 ---> 记录 对象.属性 ---> 字段 - ORM的优缺点: 优点: 可跨平台,可以通过对象.属性取值,对象.方法, ...