函数原型
// 最基本的read,write函数,读写一个buffer的数据
// read, write - read from or write to a file descriptor
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
// 在read,write函数基础上,可指定位置偏移量,从fd指定的文件offset处进行读写
// pread, pwrite - read from or write to a file descriptor at a given offset
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
// readv,writev系列函数,可一次性读写多个不连续的buffer,把buffer数组中的内容写入到文件或者从一个文件读取内容到buffer数组
// 注意第二个参数是struct iovec指针,可以传入指针或数组。每个struct iovec都是一段固定长度的buffer。
// 这些函数定义在头文件<sys/uio.h>中
// readv, writev, preadv, pwritev, preadv2, pwritev2 - read or write data into multiple buffers
#include <sys/uio.h>
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
// 在readv/writev基础上,增加了指定位置偏移量的参数
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
// 在preadv/pwritev基础上,增加了flag,如RWF_DSYNC, RWF_SYNC, RWF_HIPRI, RWF_NOWAIT, RWF_APPEND等,
// 控制读写时同步、优先级等行为
ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
// struct iovec定义,起始地址和长度
struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};
示例程序
read/write/pread/pwrite函数比较直观,这里仅示例readv/writev函数用法。
把程序中定义的buf通过writev函数输出到屏幕上。
#include <sys/uio.h>
#include <string.h>
#include <unistd.h>
int main() {
char* buf1 = "hello ";
char* buf2 = "world\n";
struct iovec vec[2]; // iovec数组,输出buf
vec[0].iov_base = buf1; // 赋值方式1
vec[0].iov_len = strlen(buf1);
// vec[1].iov_base = buf2;
// vec[1].iov_len = strlen(buf2);
vec[1] = { // 赋值方式2
.iov_base = buf2,
.iov_len = strlen(buf2)
};
writev(STDOUT_FILENO, vec, 2); // writev输出到指定文件,这里是标准输出
char* buf3 = "Hi ";
char* buf4 = "barbie!\n";
struct iovec *pv; // 使用iovec指针
pv = new iovec[] { // 为iovec指针赋值
{.iov_base = buf3, .iov_len = strlen(buf3)},
{.iov_base = buf4, .iov_len = strlen(buf4)},
};
writev(STDOUT_FILENO, pv, 2); // 把iovec指针指向的buf内容输出到stdout
return 0;
}
分析
读写多个缓冲区,有几种策略:
-
调用read、write分别操作多次
这种方式多次切换内核态,效率最低。 -
把多个缓冲区复制合并到同一个大的缓冲区中,一次read、write操作
调用一次系统调用,切换一次内核态,调用开销低。
效率主要取决于复制操作,当数据量比较小,复制开销不大时,效率和readv/writev接近。文章来源:https://www.toymoban.com/news/detail-655178.html -
调用readv、writev一次性操作多个缓冲区
系统调用一次,开销低。
当多块缓冲区数据较多,赋值开销增大时,这种方式比上述第二种方法更高效。文章来源地址https://www.toymoban.com/news/detail-655178.html
到了这里,关于C语言读写文件函数:read/write,pread/pwrite,readv/writev,preadv/pwritev,preadv2/pwritev2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!