我有不同的进程同时访问Linux中的命名管道,我想让这个访问互斥。
我知道可以使用放置在共享内存区域中的互斥锁来实现这一点,但作为一种家庭作业,我有一些限制。
因此,我想到的是在文件上使用锁定原语来实现互斥;我做了一些尝试,但我无法让它发挥作用。
这是我试过的:
flock(lock_file, LOCK_EX)
// critic section
flock(lock_file, LOCK_UN)
不同的项目将使用不同的文件描述符,但引用相同的文件。 是否有可能实现这样的目标?你能提供一些例子。
答案 0 :(得分:4)
标准锁文件技术在O_EXCL
调用上使用open()
等选项来尝试创建文件。使用锁存储进程的PID,以便确定进程是否仍然存在(使用kill()
进行测试)。你必须担心并发 - 很多。
步骤:
open()
和O_EXCL
创建它。atexit()
?)删除锁定文件。担心如果打开锁定文件并且没有读取PID会发生什么...是否是另一个进程刚刚创建它并且还没有将PID写入其中,或者在执行此操作之前它已经死了?可能最好退回 - 关闭文件并重试(可能在随机nanosleep()
之后)。如果你多次获得空文件(比如说连续3个),则认为进程已经死了并删除了锁文件。
您可以考虑让拥有该文件的进程在FIFO打开时对文件保持建议锁定。如果没有锁,则该过程已经死亡。在打开文件和应用锁定之间仍有一个TOCTOU(检查时间,使用时间)窗口。
仔细查看系统上的open()
手册页,了解是否还有其他选项可以帮助您。有时,进程使用目录(mkdir()
)而不是文件,因为即使root也无法创建给定目录名的第二个实例,但是如果知道如何在资源打开的情况下知道进程的PID,等
答案 1 :(得分:4)
我绝对建议使用实际的互斥锁(正如评论中所建议的那样);例如,pthread库提供an implementation。但是如果你想自己使用一个文件用于教育目的,我建议你看一下前一段时间发布的this answer,它描述了在Python中这样做的方法。转换为C,它应该看起来像这样(警告:未经测试的代码,使用风险自负;我的C也生锈):
// each instance of the process should have a different filename here
char* process_lockfile = "/path/to/hostname.pid.lock";
// all processes should have the same filename here
char* global_lockfile = "/path/to/lockfile";
// create the file if necessary (only once, at the beginning of each process)
FILE* f = fopen(process_lockfile, "w");
fprintf(f, "\n"); // or maybe write the hostname and pid
fclose(f);
// now, each time you have to lock the file:
int lock_acquired = 0;
while (!lock_acquired) {
int r = link(process_lockfile, global_lockfile);
if (r == 0) {
lock_acquired = 1;
}
else {
struct stat buf;
stat(process_lockfile, &buf);
lock_acquired = (buf.st_nlink == 2);
}
}
// do your writing
unlink(global_lockfile);
lock_acquired = 0;
答案 2 :(得分:3)
您的示例与您使用flock (2)
一样好(毕竟,这只是一个“建议”锁定(也就是说不是锁定) ,真的))。我的Mac OS X系统上的手册页有几个可能很重要的附带条件:
锁定在文件上,而不是文件描述符。也就是说,通过dup(2)或fork(2)复制的文件描述符不会导致a的多个实例 锁定,而是对单个锁的多个引用。如果一个进程对文件分支进行锁定并且子进程明确地解锁了该文件,那么 父母将失去锁定
和
阻止等待锁定的进程可能会被信号唤醒。
两者都提出了失败的方法。
//本来是评论,但我想引用一些长度的手册页