IO流程中IO向量iovec

作者:Younger Liu,本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。

为了提高从磁盘读取数据到内存的效率,引入了IO向量机制,IO向量即struct iovec,在API接口在readvwritev中使用,当然其他地方也较多的使用它。抛砖引玉,聊一下自己对iovec的了解。

 

readv & writev

     readv接口:从文件描述符fd所对应的的文件中读去count个数据段到多个buffers中,该bufferiovec描述,原型:

#include <sys/uio.h>

 

ssize_t readv(int fd,const struct iovec *iov, int count);

     writev接口:把count个数据buffer(使用iovec描述)写入到文件描述符fd所对应的的文件中,原型:

#include <sys/uio.h>

 

ssize_t writev(int fd,const struct iovec *iov, int count);

 

 

iovec说明

struct iovec成为IO向量,其结构如下;

#include <sys/uio.h>

 

struct iovec{

      void *iov_base; /* pointer to the start of buffer */

      size_t iov_len; /* size of buffer in bytes */

}

很明显,iov_base作为一个指针,用于记录buffer地址(一般为用户态地址)iov_len表示buffer的大小。

 

在用户态或内核态中使用时,一般均采用指针的形式:struct iovec *iov。当然一般也给出其元素的个数count

如何读写哪?将按照iov[0]iov[1]、…、iov[count-1]的顺序依次读写,并且他们在文件中的地址是连续的。

返回值:(1) 成功,返回读写的字节数,这个字节数是所有iovec结构中iov_len的总和;(2)失败返回-1,并设置好errno

iov_len的总和不能超过SSIZE_MAXcount需要大于0,小于IOV_MAX(<limits.h>),在linux1024 否则返回-1errno设置为EINVAL 

 

实例

 writev:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/uio.h>

int main(){
	struct iovec iov[3];
	ssize_t nr;
	int fd,i;
	
	char *buf[] = {
		"The term buccaneer comes from the word boucan.\n",
		"A boucan is a wooden frame used for cooking meat.\n",
		"Buccaneer is the West Indies name for a pirate.\n" 
	};
	
	fd = open("buccaneer.txt",O_WRONLY | O_CREAT | O_TRUNC);
	if( fd == -1 ){
		perror("open");
		return 1;
	}

	for(i = 0; i < 3; i++){
		iov[i].iov_base = buf[i];
		iov[i].iov_len = strlen(buf[i]);
	}
	
	nr = writev(fd,iov,3);
	if(nr == -1){
		perror("writev");
		return 1;
	}
	printf("wrote %d bytes\n",nr);

	if(close(fd)){
		perror("close");
		return 1;
	}
	return 0;
}


readv:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>

int main(){
	char foo[48],bar[51],baz[49];
	struct iovec iov[3];
	ssize_t nr;
	int fd,i;

	fd = open("buccaneer.txt",O_RDONLY);
	if(fd == -1){
		perror("open");
		return 1;
	}

	iov[0].iov_base = foo;
	iov[0].iov_len = sizeof(foo);
	iov[1].iov_base = bar;
	iov[1].iov_len = sizeof(bar);
	iov[2].iov_base = baz;
	iov[2].iov_len = sizeof(baz);

	nr = readv(fd,iov,3);
	if(nr == -1){
		perror("readv");
		return 1;
	}

	for(i = 0; i < 3; i++){
		printf("%d: %s",i,(char *)iov[i].iov_base);
	}

	if(close(fd)){
		perror("close");
		return 1;
	}
	return 0;
}

 

致谢

http://fuliang.iteye.com/blog/652297

 

作者:Younger Liu,本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。

posted on   YoungerChina  阅读(4943)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示