《unix高级环境编程》高级 I/O—— readv 和 writev 函数

时间:2022-12-31 08:35:05

       当我们想要一次性对一个文件进行读、写多个非连续的缓冲区时,readv 和 writev 函数能够实现该功能。这两函数也称为散布读和聚集写。其定义如下:

/* 读、写多个非连续的缓冲区 */

/*
* 函数功能:读取数据到多个非连续的缓冲区,或从多个非连续缓冲区写数据到文件;
* 返回值:若成功则返回已读、写的字节数,若出错则返回-1;
* 函数原型:
*/
#include <sys/uio.h>
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
/*
* 说明:
* iovec的指针结构如下:
*/
struct iovec
{
void *iov_base; /* starting address of buffer */
size_t iov_len; /* size of buffer */
};

       下图说明了 readv 和 writev 的参数和 iovec 结构:

《unix高级环境编程》高级 I/O—— readv 和 writev 函数

        writev 以顺序 iov[0],iov[1] 至 iov[iovcnt-1] 从缓冲区中聚集输出数据。writev 返回输出的字节总数。readv 则将读入的数据按照上述同样顺序散布到缓冲区中,readv 总是先填满一个缓冲区,然后再填写下一个。readv 返回读到的总字节数。如果遇到文件结尾,已无数据可读,则返回0。

测试程序:

#include "apue.h"
#include <sys/uio.h>
#include <stdlib.h>
int main(void)
{
struct iovec iov[2];
char *buf1 = (char *)malloc(5);
char *buf2 = (char *)malloc(1024);
memset(buf1, 0, 5);
memset(buf2, 0, 1024);
iov[0].iov_base = buf1;
iov[1].iov_base = buf2;
iov[0].iov_len = 5;
iov[1].iov_len = 1024;

ssize_t nread, nwrite;
nread = readv(STDIN_FILENO, iov, 2);
if(nread == -1)
err_sys("readv error");
else
{
printf("readv:\n");
printf("buf1 is: %s\t length is: %d\n",buf1, strlen(buf1));
printf("buf2 is: %s\t length is: %d\n",buf2, strlen(buf2));
}
printf("writev:\n");
nwrite = writev(STDOUT_FILENO, iov, 2);
if(nwrite == -1)
err_sys("writev error");

free(buf1);
free(buf2);
exit(0);

}

输出结果:

readv writev and apue
readv:
buf1 is: readv length is: 5
buf2 is: writev and apue
length is: 17
writev:
readv writev and apue

参考资料:

《UNIX高级环境编程》