linux多线程编程中IO读写的安全函数,pread/pwrite和read/write有什么区别和联系,实例代码对比
发表于: 2018-10-25 20:24:15 | 已被阅读: 40 | 分类于: C语言
pread 和 pwrite 函数
所需头文件和函数原型
#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);
函数说明
如果是读,读出的内容通过buf
传出。如果是写,写入的内容由buf
传入。
它俩的返回值与
pread/pwrite 和 read/write 函数的联系和区别
以写入函数为例,
pwrite(fd, buf, len, offset);
/** 相当于 */
lseek(fd, offset, SEEK_SET);
write(fd, buf, len);
只不过,在
另外,很重要的一点是,
pread/pwrite 和 read/write 函数的实例demo对比
下面这段代码的功能很简单,就是创建了两个线程,一个线程负责顺序往
lseek
和read/write
的组合在多线程同时读写中的表现
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int fd;
#define MAX 255
#define filename "test.bin"
void* r_thread(void* p)
{
int i = 0, j = 0;
for(i=0; i<MAX; i++){
usleep(100);
lseek(fd, i, SEEK_SET);
read(fd, &j, 1);
// pread(fd, &j, 1, i);
printf("%s: %d\n", __FUNCTION__, j);
}
return NULL;
}
void* w_thread(void* p)
{
int i = 0, j = 0;
for(i=0; i<MAX; i++){
usleep(100);
lseek(fd, i, SEEK_SET);
write(fd, &i, 1);
// pwrite(fd, &j, 1, i);
printf("%s: %d\n", __FUNCTION__, j);
}
return NULL;
}
int main(int argc, char* argv[])
{
pthread_t ppid;
fd = open(filename, O_RDWR|O_CREAT, 0777);
if(argc<2){
printf("\n usage: %s [1(read),2(write),3(both read and write)]\n\n", argv[0]);
exit(1);
}
switch(atoi(argv[1])){
case 1:
pthread_create(&ppid, NULL, r_thread, NULL);
break;
case 2:
pthread_create(&ppid, NULL, w_thread, NULL);
break;
case 3:
pthread_create(&ppid, NULL, r_thread, NULL);
pthread_create(&ppid, NULL, w_thread, NULL);
break;
default:
printf("\n usage: %s [1(read),2(write),3(both read and write)]\n\n", argv[0]);
break;
}
getchar();
return 0;
}
我们编译,执行,发现有些数字并没有被顺序写入。
$ gcc pread_vs_read.c -lpthread
$ ./a.out 3
w_thread: 0
r_thread: 0
r_thread: 254
...
$ ./a.out 1
...
r_thread: 43
r_thread: 211
r_thread: 210
r_thread: 46
r_thread: 208
r_thread: 48
r_thread: 52
r_thread: 202
r_thread: 54
...
原因上面已经分析,就是因为
pread/pwrite
在多线程同时读写中的表现
现在来试试
...
// lseek(fd, i, SEEK_SET);
// read(fd, &j, 1);
pread(fd, &j, 1, i);
...
// lseek(fd, i, SEEK_SET);
// write(fd, &i, 1);
pwrite(fd, &i, 1, i);
...
再编译,做相同的测试:
$ gcc pread_vs_read.c -lpthread
lcc@lcc-vm:/lccRoot/xx_test/tmp/pread_vs_read$ ./a.out 3
w_thread: 0
r_thread: 0
w_thread: 1
r_thread: 1
...
$ ./a.out 1
r_thread: 0
r_thread: 1
r_thread: 2
r_thread: 3
r_thread: 4
r_thread: 5
...
发现数据被正确写入了。
总结
可以看出,