ARM技术论坛
直播中

嵌入式小能手

2年用户 1499经验值
擅长:嵌入式技术
私信 关注
[经验]

飞凌嵌入式ElfBoard-文件I/O的了解探究之原子操作

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

更多回帖

发帖
×
20
完善资料,
赚取积分