|
原子操作指的是不可被中断或分割的基本操作,它在执行过程中要么完全执行成功,要么完全不执行,不会被其他并发操作所干扰。 原子操作是确保对共享资源进行并发访问时线程安全的关键,通常由硬件或操作系统提供支持,并且能够保证在多线程或多进程环境下的安全性。 常见的原子操作包括原子增加、原子减少、原子交换等。这些操作能够保证在并发执行时不会发生竞争冒险或数据竞争(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
|