作者:Younger Liu,本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。
为了提高从磁盘读取数据到内存的效率,引入了IO向量机制,IO向量即struct iovec,在API接口在readv和writev中使用,当然其他地方也较多的使用它。抛砖引玉,聊一下自己对iovec的了解。
readv接口:从文件描述符fd所对应的的文件中读去count个数据段到多个buffers中,该buffer用iovec描述,原型:
#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);
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_MAX,count需要大于0,小于IOV_MAX(<limits.h>中),在linux为1024, 否则返回-1,errno设置为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 未本地化版本许可协议进行许可。