原子操作指的是不可被中断或分割的基本操作,它在执行过程中要么完全执行成功,要么完全不执行,不会被其他并发操作所干扰。
原子操作是确保对共享资源进行并发访问时线程安全的关键,通常由硬件或操作系统提供支持,并且能够保证在多线程或多进程环境下的安全性。
常见的原子操作包括原子增加、原子减少、原子交换等。这些操作能够保证在并发执行时不会发生竞争冒险或数据竞争(Data Race),从而确保数据的一致性和完整性。
在并发编程中,原子操作通常用于保护共享资源的访问和修改,以防止多个线程同时访问或修改同一共享资源而导致的竞争冒险。使用原子操作能够简化并发编程的同步机制,并且能够提高程序的性能和效率。
例如:有两个应用程序 AB,都对同一个文件进行写操作,进程A先写入,那么后写入的进程B就会把A写入的数据覆盖掉。
解决办法就是将“先定位到文件末尾,然后写”这两个步骤组成一个原子操作,由此引入preadpwrite函数。
1.pread
用于带偏移量的从文件中读取数据,无法中断其定位和读操作,不更新文件表中当前的位置偏移量。
1)头文件
#include <unistd.h>
2)函数原型
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
3)参数
fd:表示要操作文件的文件描述符。
buf:表示读出数据存放的位置(缓冲区地址)。
count:表示读出的字节数。
offset:表示当前需要进行读的位置偏移量
4)返回值
若读取成功则返回实际读到的字节数,若已到文件结尾则返回0,若出错则返回-1
5)示例:(带偏移量的从文件中读取特定数据,查看读取后的文件偏移量)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
int main(){
char bufwrite[30] = "HELLO WORLD!!!\n";
char bufread[30];
int fd, lk;
fd = open("./test", O_RDWR | O_CREAT | O_TRUNC, 0666);  //打开文件test
if (fd < 0) {
printf("error: test open\n");
return -1;
}
if ( write(fd, bufwrite, strlen(bufwrite)) < 0 ) {           //向文件test写入特定内容
printf("error: test write\n");
close(fd);
return -1;
}
if (pread(fd, bufread, 3, 2) < 0) {                //读取2字节后的3字节内容
printf("error: test pread\n");
close(fd);
return -1;
}
lk = lseek(fd, 0,SEEK_CUR);                //获取当前偏移量位置
if (lk < 0) {
printf("error: test lseek\n");
close(fd);
return -1;
}
printf("pread fd:%s", bufread);
printf("lseek fd:%d\n", lk);
close(fd);
return 0;
}
6)编译运行并查看测试结果
pread fdLO                   //读取到2字节后的3字节内容
lseek fd:15                     //第一次写入后的偏移量,而不是pread读取的位置
2.pwrite
用于带偏移量的向文件中写入数据,无法中断其定位和写操作,不更新文件表中当前的位置偏移量。
1)头文件
#include <unistd.h>
2)函数原型
ssize_t pwrite(intfd, const void *buf, size_tcount, off_toffset)
3)参数
fd:表示要操作文件的文件描述符。
buf:表示要写的数据(缓冲区地址)。
count:表示写入的字节数。
offset:表示当前需要进行的位置偏移量
4)返回值
成功,返回写入到文件中的字节数;失败,返回-1
5)示例:(带偏移量的向文件写入特定数据,查看写入后的文件偏移量)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main()
{
char bufwrite[30] = "HELLO WORLD!!!\n";
char bufWrite[30] = "pwrite test!\n";
char bufread[30];
int fd, lk;
fd = open("./test", O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
printf("error: test open\n");
return -1;
}
if ( write(fd, bufwrite, strlen(bufwrite)) < 0 ) {     //向文件test写入特定内容
printf("error: test write\n");
close(fd);
return -1;
}
if (pwrite(fd, bufWrite, strlen(bufWrite), 15) < 0) {
//带偏移量向文件test写入特定内容
printf("error: test pread\n");
close(fd);
return -1;
}
if (pread(fd, bufread, 30, 5) < 0) {              //带偏移量读取test特定内容
printf("error: test pread\n");
close(fd);
return -1;
}
lk = lseek(fd, 0, SEEK_CUR);
if(lk < 0) {
printf("error: test lseek\n");
close(fd);
return -1;
}
printf("pread fd: %s", buf);
printf("lseek fd: %d\n", lk);
close(fd);
return 0;
}
6)编译运行并查看测试结果
pread fd: WORLD!!!
pwrite test!
lseek fd: 15

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    Powered by Discuz! X3.5  © 2001-2013 Comsenz Inc.