在Linux系统中,readdir
函数用于读取目录的内容。当多个进程或线程并发地调用readdir
时,可能会出现竞争条件,导致读取到不一致或不完整的数据。为了确保数据的一致性和完整性,需要实施适当的并发控制策略。以下是一些常见的并发控制策略:
文件锁是一种通过操作系统提供的机制来控制对文件的访问的方法。可以使用fcntl
系统调用来实现文件锁。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
void lock_file(int fd) {
struct flock fl;
fl.l_type = F_WRLCK; // 写锁
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0; // 锁定整个文件
fcntl(fd, F_SETLKW, &fl);
}
void unlock_file(int fd) {
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0; // 解锁整个文件
fcntl(fd, F_SETLK, &fl);
}
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
lock_file(fd);
// 执行目录读取操作
DIR *dir = opendir(".");
if (dir == NULL) {
perror("opendir");
close(fd);
return 1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
unlock_file(fd);
close(fd);
return 0;
}
互斥锁是一种同步机制,用于保护共享资源,确保同一时间只有一个线程可以访问该资源。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <dirent.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *read_directory(void *arg) {
pthread_mutex_lock(&mutex);
DIR *dir = opendir(".");
if (dir == NULL) {
perror("opendir");
pthread_mutex_unlock(&mutex);
return NULL;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t threads[5];
for (int i = 0; i < 5; ++i) {
if (pthread_create(&threads[i], NULL, read_directory, NULL) != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < 5; ++i) {
pthread_join(threads[i], NULL);
}
return 0;
}
读写锁允许多个读取者同时访问共享资源,但只允许一个写入者访问。这适用于读操作远多于写操作的场景。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <dirent.h>
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
void *read_directory(void *arg) {
pthread_rwlock_rdlock(&rwlock);
DIR *dir = opendir(".");
if (dir == NULL) {
perror("opendir");
pthread_rwlock_unlock(&rwlock);
return NULL;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
pthread_rwlock_unlock(&rwlock);
return NULL;
}
void *write_directory(void *arg) {
pthread_rwlock_wrlock(&rwlock);
// 执行写操作
FILE *file = fopen("example.txt", "w");
if (file == NULL) {
perror("fopen");
pthread_rwlock_unlock(&rwlock);
return NULL;
}
fprintf(file, "Writing to file\n");
fclose(file);
pthread_rwlock_unlock(&rwlock);
return NULL;
}
int main() {
pthread_t read_threads[5];
pthread_t write_thread;
for (int i = 0; i < 5; ++i) {
if (pthread_create(&read_threads[i], NULL, read_directory, NULL) != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
if (pthread_create(&write_thread, NULL, write_directory, NULL) != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
for (int i = 0; i < 5; ++i) {
pthread_join(read_threads[i], NULL);
}
pthread_join(write_thread, NULL);
return 0;
}
选择合适的并发控制策略取决于具体的应用场景和需求。文件锁适用于跨进程的同步,互斥锁适用于单进程内的线程同步,而读写锁则适用于读多写少的场景。在实际应用中,可能需要结合多种策略来确保数据的一致性和完整性。