面试题答案
一键面试具备原子操作特性的文件系统调用
open(O_CREAT | O_EXCL)
:当使用open
函数并指定O_CREAT
(如果文件不存在则创建)和O_EXCL
(如果文件已存在则open
失败)标志时,这两个操作(检查文件是否存在和创建文件)是原子的。这意味着在多线程环境下,不会出现一个线程检查文件不存在,然后在创建文件之前另一个线程也进行同样检查并创建文件的竞态条件。write
:在单个write
调用中,写入操作是原子的(只要写入的数据量小于或等于系统的PIPE_BUF
大小,通常为 4096 字节)。对于大于PIPE_BUF
的写入,内核可能会将其拆分为多个操作,但在每个小于等于PIPE_BUF
的子操作内是原子的。
利用原子操作特性保证数据一致性和完整性的示例
下面是一个使用 open(O_CREAT | O_EXCL)
和 write
来创建并写入文件的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#define FILE_NAME "test.txt"
#define DATA "This is some data to be written.\n"
void* write_to_file(void* arg) {
int fd = open(FILE_NAME, O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd == -1) {
perror("open");
pthread_exit(NULL);
}
ssize_t bytes_written = write(fd, DATA, strlen(DATA));
if (bytes_written == -1) {
perror("write");
}
close(fd);
pthread_exit(NULL);
}
int main() {
pthread_t thread1, thread2;
if (pthread_create(&thread1, NULL, write_to_file, NULL) != 0) {
perror("pthread_create");
return 1;
}
if (pthread_create(&thread2, NULL, write_to_file, NULL) != 0) {
perror("pthread_create");
return 1;
}
if (pthread_join(thread1, NULL) != 0) {
perror("pthread_join");
return 1;
}
if (pthread_join(thread2, NULL) != 0) {
perror("pthread_join");
return 1;
}
return 0;
}
在这个示例中:
- 使用
open(O_CREAT | O_EXCL)
确保文件创建操作的原子性,避免多个线程同时创建同名文件。如果文件已经存在,open
调用会失败,这样可以保证每个线程创建文件的操作是互斥的。 - 使用
write
函数写入数据,由于写入的数据量小于PIPE_BUF
,所以每个write
操作是原子的,不会出现数据部分写入或交错的情况。这样就保证了在多线程环境下文件操作的数据一致性和完整性。