linux内核sock_sendmsg,为什么linux中sendto函数中的msg.msg_iovlen=1;
为什么linux中sendto函数中的msg.msg_iovlen=1;
|
内核中定义的sys_sendto的源码吗?
这个属于sendmsg中struct msghdr的用法问题, sys_sendto函数最终调用的是sock_sendmsg
int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size);
而用户空间的函数sendmsg是直接调用的内核中的sock_sendmsg,
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
这两个函数同时支持tcp和udp , 当然还有别的像unix域等。
struct msghdr
{
void *msg_name; /* Address to send to/receive from. */
socklen_t msg_namelen; /* Length of address data. */
struct iovec *msg_iov; /* Vector of data to send/receive into. */
size_t msg_iovlen; /* Number of elements in the vector. */
void *msg_control; /* Ancillary data (eg BSD filedesc passing). */
size_t msg_controllen; /* Ancillary data buffer length.
!! The type should be socklen_t but the
definition of the kernel is incompatible
with this. */
int msg_flags; /* Flags on received message. */
};
其中struct iovec的定义
struct iovec
{
void *iov_base; /* Pointer to data. */ //用户sendto中的ptr就是赋值到此
size_t iov_len; /* Length of data. */ //用户sendto中的长度就是赋值到此
};
不知道LZ知不知道writev函数,一次能从多个指针的地方写入数据。
msg.msg_iovlen = 1就是指msg.msg_iov的指针指向的地方只有一个struct iovec结构体。
sendto一次只能从一个ptr发送长度为len的东西,故只用定义一个struct iovec iov[1];
msg_iovlen就是指struct iovec的个数。
例子:
如果你想用sendmsg发送ptr1 , len1 ; ptr2, len2的数据。 传统做法是将ptr1 和 ptr2的数据都拷贝到一起。
如 char *ptr = (char*)malloc(len1 + len2);
memcpy(ptr , ptr1 , len1) ; memcpy(ptr , ptr2 , len2)
然后用sendto(sockfd , ptr , len1 + len2, 0 , addr , addrlen);
现在用sendmsg就不用拷贝。如下:
struct msghdr msg;
struct iovec iov[2];
iov[0].iov_base = ptr1;
iov[0].iov_len = len1;
iov[1].iov_base = ptr2;
iov[1].iov_len = len2;
memset(&msg , 0 , sizeof(msg));
msg.msg_name = &addr; //tcp 时为NULL
msg.msg_namelen = sizeof(addr); //tcp时为0
msg.msg_iov = iov;
msg.msg_iovlen = 2 ; //!!!!!此处为2!
sendmsg(sockfd , &msg , 0);
//这样就不省了拷贝数据的开锁!
理解struct msghdr中msg_iovlen的意义了吗?
linux内核sock_sendmsg,为什么linux中sendto函数中的msg.msg_iovlen=1;相关推荐
- linux中main数据手册,linux中main()函数中参数来源.doc
linux中main()函数中参数来源 爷而吐裁报讲际芋兽胳缎扒孩员斜阀裔坤且闺获汕秉鳃鞭牲储访电叔麦篷院杰梆滑廊木屹炯历蛋糯诛忙宇倚角缄蔫牲詹狙凄聂脑棵枷团尖枷蝶滞忽唱专迟适苞校驶劫屏列佛束蚂庐悬刽 ...
- linux内核创建节点,Linux内核驱动自动创建设备节点文件
Linux下生成驱动设备节点文件的方法有3个:1.手动mknod:2.利用devfs:3.利用udev 在刚开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点,实际上L ...
- 【Linux 内核 内存管理】内存管理架构 ① ( 内存管理架构组成 | 用户空间 | 内核空间 | MMU 硬件 | Linux 内核架构层次 | Linux 系统调用接口 )
文章目录 一.内存管理架构组成 ( 用户空间 | 内核空间 | MMU 硬件 ) 二.Linux 内核架构层次 三.Linux 系统调用接口 一.内存管理架构组成 ( 用户空间 | 内核空间 | MM ...
- 从linux内核启动,学习Linux内核启动过程:从start_kernel到init
一.实验步骤: 1:运行menuos: a)cd LinuxKernel/ b)qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd root ...
- 简述arm linux内核启动流程,Linux内核启动过程和Bootloader(总述)
1.Linux内核启动过程概述 一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader),Linux 内核,文件系统,应用程序.其中 Bootloader是系统启 ...
- linux 内核 课程,Linux内核分析课程-全面剖析Linux内核技术 揭开Linux内核的面纱 Linux内核学习视频教 ......
课程名称 Linux内核分析课程-全面剖析Linux内核技术 揭开Linux内核的面纱 Linux内核学习视频 课程目录 (1)\1, 计算机是如何工作的?:目录中文件数:0个 (2)\2, 操作系统 ...
- linux内核编译系统调用,linux编译内核及添加系统调用
我们都知道系统功能调用是Unix/Linux操作系统向用户程序提供支持的接口,通过这些接口应用程序向操作系统请求服务,控制转向操作系统,而操作系统在完成服务后,将控制和结果返回给用户程序. 系统调用的 ...
- 编译3.0的linux内核,1-3-编译Linux内核
1-3-编译Linux内核 1.将Linux源码包拷贝到共享文件夹. 2.进入共享文件夹. 3.解压,命令#tar xvfj Kernel_3.0.8_TQ210_for_Linux_v2.2.tar ...
- 把图形写入linux内核,如何在linux内核启动时添加显示图片
内核版本为2.6.30.4 为了实现了在linux内核启动时不仅仅是只显示一个静态的全屏logo, 而是显示能够表示内核正在启动的进度条,因此需要能够在启动过程中直接操纵framebuffer的功能. ...
最新文章
- 学会使用Spring注解
- GBRT(GBDT)(MART)(Tree Net)(Tree link)
- Activiti的流程定义文件解析
- ITU-T Technical Paper: QoS的构建模块与机制
- React常用的命令解析
- 宏正ATEN推出ALTUSEN系列 全面冲刺KVM高端市场
- 查询 加载时间过长添加提示信息
- oracle查询第二个字为a,Oracle中SQL语句学习二(like,转义,order by)
- asp.net前端页面上使用if
- oracle错误1327,问题简述:在oracle linux下安装oracle10g,多个文件报“Permission denied”错误...
- windows10 wifi热点手机连接显示无网络连接问题解决
- Go语言核心之美 2.5-字符串
- android 模拟滑屏,android模仿桌面左右滑屏
- 【SpringBoot】:j2cache入门案例
- Entity Framework Core系列教程-25-Entity Framework Core日志
- PKI学习系列-基本概念
- 桌面上的计算机图片怎么复制,电脑桌面上怎么截图呢??请问如何在电脑屏幕上截屏?...
- 二、了解shiro架构 (10 Minute Tutorial on Apache Shiro)
- Excel根据身份证号批量提取出生日期
- 小哥哥,检索式chatbot了解一下?