readv和writev特点在于允许单个系统调用读入到或者写出自一个或多个缓冲区。这些操作分别称为分散读和集中写。
因为来自读操作的输入数据被分散到多个应用缓冲区中,而来自多个应用缓冲区的输出数据则被集中提供给单个写操作。
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
这两个函数的第二个参数是指向iovec结构数组的一个指针,iov是一个结构数组,它的每个元素指明存储器中的一个缓冲区:
struct iovec{
void *iov_base; //starting address of buffer
size_t iov_len; //size of buffer
}
writev以顺序iov[0],iov[1]至iov[iovcnt-1]从缓冲区中聚集输出数据。
readv则将读入的数据按照上述同样顺序散布到缓冲区中,readv总是先填满一个缓冲区,然后再填写下一个。
有了这两个函数,当想要集中写出某张链表时,只需让iov数组的各个元素包含链表中各个表项的地址和其长度,然后将iov和它的元素个数作为参数传递给writev(),这些数据便可一次写出。
函数实现:
体会 分散读出 和 集中写入 的含义:
#include <stdio.h>
#include <sys/uio.h>
#include <fcntl.h>
#define IOVENT 3
#define PER_IOVENT 5
int main(void)
{
char buf1[PER_IOVENT],buf2[PER_IOVENT],buf3[PER_IOVENT];
struct iovec iov[IOVENT];//分配3个结构体共同存储 abcdefghijklnmo
iov[0].iov_base = buf1;
iov[0].iov_len = PER_IOVENT;
iov[1].iov_base = buf2;
iov[1].iov_len = PER_IOVENT;
iov[2].iov_base = buf3;
iov[2].iov_len = PER_IOVENT;
int fd = open("a.txt",O_RDWR);
if(fd < 0){
perror("open");
return -1;
}
int rsize = readv(fd, iov, IOVENT);//a.txt的内容 分散读出 到三个结构体中
printf("buf1 = %s\n",buf1);
printf("buf2 = %s\n",buf2);
printf("buf3 = %s\n",buf3);
close(fd);
fd = open("b.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if(fd < 0){
perror("open");
return -1;
}
int wsize = writev(fd,iov,IOVENT);//三个结构体中的内容 集中写入 b.txt中
close(fd);
return 0;
}
#if 0
函数执行:
toney@sw2:~/study/network$ ./a.out
buf1 = abcdefghijklnmo
buf2 = fghijklnmo
buf3 = klnmo
toney@sw2:~/study/network$ cat a.txt
abcdefghijklnmo
toney@sw2:~/study/network$ cat b.txt
abcdefghijklnmotoney@sw2:~/study/network$
toney@sw2:~/study/network$
#endif