分散/聚集I/O是一种可以在单词系统调用对多个缓冲区输入输出的方法,可以把多个缓冲区的数据写到单个数据流中,也可以把单个数据流读到多个缓冲区中。其命名的原因在于数据会被分散到指定缓冲区向量,或者从指定缓冲区向量中聚集数据。这种输入输出方法也称为向量I/O(vector I/O)。标准读写系统调用可以称为线性I/O(linear I/O)。
Linux中定义了一组实现满足上述所有特性的分散/聚集I/O的系统调用。它们分别为:
// readv()函数从文件描述符fd中读取count个段到参数iov所指定的缓冲区中。// 返回读取的字节个数#include <sys/uio.h>ssize_t readv (int id, const struct iovec *iov, int count);// writev()函数将iov指定的缓冲区中读取count个段的数据,并写入fd中。// 返回写入的字节个数#include <sys/uio.h>ssize_t writev (int id, const struct iovec *iov, int count);其中结构体iovec的定义如下:
struct iovec { void *iov_base; size_t iov_len;};每个段描述了内存中所要读写的缓冲区的地址和长度。readv()函数在处理下一个缓冲区之前,会填满当前缓冲区的iov_len个字节。writev()函数在处理下一个缓冲区之前,会把当前缓冲区的iov_len个字节数据输出。这两个函数都会顺序处理向量中的段,从0到count-1。
注意:
由于返回值类型是ssize_t,如果所有count个iov_len的和超过SSIZE_MAX,则不会处理任何数据,返回-1,并把errno值设为EINVAL。POSIX指出count的值必须大于0,且小于IOV_MAX(在文件#include <iostream>#include <unistd.h>#include <fcntl.h>#include <sys/uio.h>#include <sys/types.h>#include <sys/stat.h>#include <limits.h>#include <cstdio>using namespace std;int main(int argc, char *argv[]){ struct iovec iov[3]; int count = 3; string buffer[3] = { "The term buccaneer comes from the Word boucan./n", "A boucan is a wooden frame used for cooking meat./n", "Buccaneer is the West Indives name for a pirate./n" }; int fd; fd = open("buccaneer.txt", O_WRONLY | O_CREAT); if (-1 == fd) { perror("open failed"); return 1; } for (int i=0; i<3; i++) { iov[i].iov_len = buffer[i].size() + 1; iov[i].iov_base = const_cast<char *> (buffer[i].c_str()); cout << iov[i].iov_len << endl; } ssize_t nr; nr = writev(fd, iov, 3); if (-1 == nr) { perror("writev error"); return 1; } cout << "wrote " << nr << " bytes" << endl; if (close(fd)) { perror("close"); return 1; } return 0;}#include <iostream>#include <cstdio>#include <sys/types.h>#include <sys/uio.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>using namespace std;int main(int argc, char *argv[]){ struct iovec iov[3]; ssize_t nr; int fd; fd = open("buccaneer.txt", O_RDONLY); if (-1 == fd) { perror("open error"); return 1; } iov[0].iov_base = new char[48]; iov[0].iov_len = 48; iov[1].iov_base = new char[51]; iov[1].iov_len = 51; iov[2].iov_base = new char[50]; iov[2].iov_len = 50; // read into the structure nr = readv(fd, iov, 3); if (-1 == nr) { perror("readv error"); return 1; } for (int i=0; i<3; i++) cout << i << ": " << static_cast<char *> (iov[i].iov_base) << endl; if (close(fd)) { perror("close error"); return 1; } return 0;}新闻热点
疑难解答