Linux线程中的文件段/节/记录锁
我有一个多线程进程,其中一个文件由多个线程共享(读写)。一个线程是否有办法锁定一个文件段,使其他线程无法访问它?Linux线程中的文件段/节/记录锁,linux,c,locking,concurrency,multithreading,Linux,C,Locking,Concurrency,Multithreading,我有一个多线程进程,其中一个文件由多个线程共享(读写)。一个线程是否有办法锁定一个文件段,使其他线程无法访问它? 我已经尝试过fcntl(fd、F_SETLKW和flock),但是这个锁只适用于进程,而不适用于线程(一个进程中的所有线程都共享一个锁)。如果不同进程之间不需要文件锁,请避免使用文件锁(这是POSIXAPI中设计最差的部分之一)只需使用互斥锁或其他共享内存并发原语。如果不同进程之间不需要文件锁,请避免使用文件锁(这是POSIX API设计最差的部分之一),只需使用互斥锁或其他共享内存
我已经尝试过
fcntl(fd、F_SETLKW和flock)
,但是这个锁只适用于进程,而不适用于线程(一个进程中的所有线程都共享一个锁)。如果不同进程之间不需要文件锁,请避免使用文件锁(这是POSIXAPI中设计最差的部分之一)只需使用互斥锁或其他共享内存并发原语。如果不同进程之间不需要文件锁,请避免使用文件锁(这是POSIX API设计最差的部分之一),只需使用互斥锁或其他共享内存并发原语。有两种方法可以做到这一点:
有两种方法可以做到这一点:
是-但不是用相同的机制。您必须使用pthread互斥体之类的东西,并自己记录簿记 如何使这项工作可行的大纲
- 等待并在簿记结构上声明进程级互斥
- 确保进程中没有其他线程试图使用该段
- 将自己标记为使用文件段
- 释放进程级互斥锁
- 抓取过程的fnctl锁(如有必要)
- 做你的写作
- 释放fnctl锁以允许其他进程使用该段(如有必要)
- 在进程级簿记结构互斥体上再次等待(如果您可以以原子方式将其标记为未使用,则可能不需要)
- 在流程中将段标记为未使用
- 释放进程级互斥
- 等待并在簿记结构上声明进程级互斥
- 确保进程中没有其他线程试图使用该段
- 将自己标记为使用文件段
- 释放进程级互斥锁
- 抓取过程的fnctl锁(如有必要)
- 做你的写作
- 释放fnctl锁以允许其他进程使用该段(如有必要)
- 在进程级簿记结构互斥体上再次等待(如果您可以以原子方式将其标记为未使用,则可能不需要)
- 在流程中将段标记为未使用
- 释放进程级互斥
#include <stdbool.h>
#include <pthread.h>
#include <sys/types.h>
// A record indicating an active lock.
struct threadlock {
int fd; // or -1 for unused entries.
off_t start;
off_t length;
};
// A table of all active locks (and the unused entries).
static struct threadlock all_locks[100];
// Mutex housekeeping.
static pthread_mutex_t mutex;
static pthread_cond_t some_lock_released;
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
static void threadlock_init(void) {
for (int i = 0; i < sizeof(all_locks)/sizeof(all_locks[0]); ++i)
all_locks[i].fd = -1;
pthread_mutex_init(&mutex, (pthread_mutexattr_t *)0);
pthread_cond_init(&some_lock_released, (pthread_condattr_t *)0);
}
// True iff the given region overlaps one that is already locked.
static bool region_overlaps_lock(int fd, off_t start, off_t length) {
for (int i = 0; i < sizeof(all_locks)/sizeof(all_locks[0]); ++i) {
const struct threadlock *t = &all_locks[i];
if (t->fd == fd &&
t->start < start + length &&
start < t->start + t->length)
return true;
}
return false;
}
// Returns a pointer to an unused entry, or NULL if there isn't one.
static struct threadlock *find_unused_entry(void) {
for (int i = 0; i < sizeof(all_locks)/sizeof(all_locks[0]); ++i) {
if (-1 == all_locks[i].fd)
return &all_locks[i];
}
return 0;
}
// True iff the lock table is full.
static inline bool too_many_locks(void) {
return 0 == find_unused_entry();
}
// Wait until no thread has a lock for the given region
// [start, start+end) of the given file descriptor, and then lock
// the region. Keep the return value for threadunlock.
// Warning: if you open two file descriptors on the same file
// (including hard links to the same file), this function will fail
// to notice that they're the same file, and it will happily hand out
// two locks for the same region.
struct threadlock *threadlock(int fd, off_t start, off_t length) {
pthread_once(&once_control, &threadlock_init);
pthread_mutex_lock(&mutex);
while (region_overlaps_lock(fd, start, length) || too_many_locks())
pthread_cond_wait(&some_lock_released, &mutex);
struct threadlock *newlock = find_unused_entry();
newlock->fd = fd;
newlock->start = start;
newlock->length = length;
pthread_mutex_unlock(&mutex);
return newlock;
}
// Unlocks a region locked by threadlock.
void threadunlock(struct threadlock *what_threadlock_returned) {
pthread_mutex_lock(&mutex);
what_threadlock_returned->fd = -1;
pthread_cond_broadcast(&some_lock_released);
pthread_mutex_unlock(&mutex);
}
#包括
#包括
#包括
//一种指示活动锁的记录。
结构螺纹锁{
int fd;//或-1表示未使用的条目。
关闭启动;
离体长度;
};
//所有活动锁(和未使用项)的表。
静态结构线程锁所有_锁[100];
//互斥管理。
静态pthread_mutex_t mutex;
静态pthread条件下释放一些锁;
静态pthread_once_t once_control=pthread_once_INIT;
静态void螺纹锁紧_init(void){
对于(int i=0;ifd==fd&&
t->开始<开始+长度&&
开始开始+t->长度)
返回true;
}
返回false;
}
//返回指向未使用项的指针,如果没有,则返回NULL。
静态结构线程锁*查找未使用项(无效){
对于(int i=0;i