(转)linux的pread、pwrite、read、write函数(p...也是原子操作)
1 缘由
在阅读seastar
源码时发现有使用pread
函数,这也是第一次认识pread
函数,平时用read
比较多。
2 pread函数
函数原型:
#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);
pread
简单来说就是在指定偏移offset
位置开始读取count
个字节,同理可推``pwrite`。
2.1 使用示例
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int fd = open("test.txt", O_RDONLY);
if(fd < 0)
{
perror("open failed");
return 1;
}
char buf[1024] = {0};
int offset = 5;
ssize_t ret = 0;
int count = 10;
if((ret = pread(fd, buf, count, offset)) == -1)
{
perror("pread failed");
return 1;
}
std::cout << "read buf = " << buf << std::endl;
return 0;
}
2.3 与read和write区别
man手册是这样说的:
The
pread()
andpwrite()
system calls are especially useful in multi‐
threaded applications. They allow multiple threads to perform I/O on
the same file descriptor without being affected by changes to the file
offset by other threads.
就是对于对多线程读写比较有意义,不会相互影响读写文件时的offset
,这也是多线程时读写文件一个头痛的问题。不过我仔细一想。
- 对于
pwrite
来说,多个线程之间即使不影响offset
但还是存在使用上的问题。 - 对于
pread
来说是可以解决多个线程offset
相互影响的问题。
参考链接 文件IO详解(十三)---pread函数和pwrite函数详解里提到pread函数相当于先后调用了lseek和read函数,但是还是有区别的,有以下两点区别:1. pread函数是原子操作,而先后调用两个函数不是原子操作;2. pread函数是不会改变当前文件偏移量的,而read和write函数会改变当前文件偏移量
。第二点是关键,第一点暂时没有核实是否正确。
调用pread相当于顺序调用lseek和read,但pread和这种调用又有重大区别:
- 调用pthread时,无法中断其定位和读操作,(lseek和read相当于一个原子操作)
- 不更新文件指针
调用pwrite相当于调用lseek和write,但也与它们有类似区别
因为历史上有些系统不支持O_APPEND,才定义了pread和pwrite。
因为lseek与read之间,可能会出现非预期的效果,所以定义pread。
随机访问的话,pread/pwrite比较方便。
原文链接:https://blog.csdn.net/dongyu_1989/article/details/78915782作者:dnsir
链接:https://www.jianshu.com/p/a99d6ac4b6eb
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。