无法获取文件锁定
Posted
技术标签:
【中文标题】无法获取文件锁定【英文标题】:can't acquire a lock on a file 【发布时间】:2017-03-02 16:35:13 【问题描述】:FileLocker_wo.h
#include <string>
namespace Utils
namespace FileLocker
bool lock_file(std::string aFileName, int& aFileDescriptor);
bool unlock_file(int& aFileDescriptor);
bool is_file_locked(std::string aFileName);
;
FileLocker_wo.cpp
namespace Utils
namespace FileLocker
bool lock_file(std::string aFileName, int& aFileDescriptor)
aFileDescriptor = open(aFileName.c_str(), O_RDWR);
if (aFileDescriptor != -1)
if (lockf(aFileDescriptor, F_TLOCK, 0) == 0)
return true;
std::cout << strerror(errno) << std::endl;
return false;
bool unlock_file(int& aFileDescriptor)
if (lockf(aFileDescriptor, F_ULOCK, 0) == 0)
std::cout << "unloced file" << std::endl;
close(aFileDescriptor);
return true;
close(aFileDescriptor);
return false;
bool is_file_locked(std::string aFileName)
int file_descriptor = open(aFileName.c_str(), O_RDWR);
if (file_descriptor != -1)
int ret = lockf(file_descriptor, F_TEST, 0);
if (ret == -1 && (errno == EACCES || errno == EAGAIN))
std::cout << "locked by another process" << std::endl;
close(file_descriptor);
return true;
if (ret != 0)
std::cout << "return value is " << ret << " " << strerror(errno) << std::endl;
close(file_descriptor);
return false;
p1.cpp
#include <iostream>
#include <fstream>
#include "FileLocker_wo.h"
int main()
int fd = -1;
if (Utils::FileLocker::lock_file("hello.txt", fd))
std::ofstream out("hello.txt");
out << "hello ding dong" << std::endl;
out.close();
std::cout << "locked" << std::endl;
sleep(5);
if (Utils::FileLocker::unlock_file(fd))
std::cout << "unlocked" << std::endl;
return 0;
p2.cpp
#include "FileLocker_wo.h"
#include <iostream>
#include <fstream>
int main()
int max_trys = 2;
int trys = 0;
bool is_locked = false;
do
is_locked = Utils::FileLocker::is_file_locked("hello.txt");
if (!is_locked)
std::cout << "not locked" << std::endl;
break;
std::cout << "locked" << std::endl;
sleep(1);
++trys;
while(trys < max_trys);
if (!is_locked)
std::string s;
std::ifstream in("hello.txt");
while(getline(in,s))
std::cout << "s is " << s << std::endl;
return 0;
我正在尝试在一个进程中获取文件锁定,并使用 lockf (p1.cpp, p2.cpp) 检查其他进程中是否对该文件有任何锁定。
在 p1.cpp 我锁定文件 hello.txt 并等待 5 秒。同时我启动 p2.cpp 并检查其他进程是否有任何锁,但总是没有锁>我在过去的 2 个小时里都被这个卡住了。
谁能告诉我这有什么问题?
【问题讨论】:
将您的程序更改为在lockf
刚刚返回非零值的每个地方 打印strerror(errno)
。再次运行它们。告诉我们他们打印的内容。
它没有返回非零值。我有日志,但它们没有被打印,因为它总是返回 0。现在将这些日志更改编辑到代码中。
您不应该创建某种对象,这样您就不必一直打开文件吗?在is_file_locked()
中,您打开但不关闭文件描述符;您将用完文件描述符。您不会关闭lock_file()
或unlock_file()
中的文件描述符,但这会让储物柜有责任关闭文件(从而解锁文件)。我相信,析构函数和 RAII 会让生活变得更简单。
添加了关闭更改但仍然无法正常工作...我们是否应该关闭 lock_file 中的文件而不解锁?我只关闭了 unlock_file 和 is_file_locked。更新了代码。
作为信息,我也有一个类版本的文件柜,但它也不起作用。
【参考方案1】:
您在 POSIX 文件锁中遇到了一个更严重的设计错误。您可能不知道这一点,因为您只阅读了lockf
manpage,而不是fcntl
manpage,所以这是fcntl
手册页的重要部分:
如果进程关闭任何引用文件的文件描述符,则 所有进程对该文件的锁定都被释放,无论 获得锁的文件描述符。
这意味着,在你的这段代码中
if (Utils::FileLocker::lock_file("hello.txt", fd))
std::ofstream out("hello.txt");
out << "hello ding dong" << std::endl;
out.close();
当您调用 out.close()
时,您会失去对文件的锁定,即使 out
是不同于您在 lock_file
中使用的操作系统级别的“打开文件描述”! p>
为了安全地使用 POSIX 锁,您必须确保在要锁定的文件上调用 open()
每个进程一次且仅一次,您绝不能复制文件描述符,并且您必须仅当您准备好放下锁时再将其关闭。因为可能没有任何方法(甚至使用不可移植的扩展)来从文件描述符构造 iostreams 对象,或者从 iostreams 对象中提取文件描述符,所以阻力最小的路径是只使用操作系统级 I/O 原语(open
、close
、read
、write
、fcntl
、lseek
、lseek
、ftruncate
)以及需要对其应用 POSIX 锁的文件。
【讨论】:
在这种情况下我还有一个问题,将 close(fd) 将关闭 ofstream 使用的所有描述符(如果它用于打开同一个文件并且我没有调用 ofstream.close( ))? 不,ofstream 有自己的“打开文件描述”,close(fd) 不会影响它。但是,锁将在ofstream.close()
和close(fd)
的第一个 处被释放,因为锁与进程 相关联,而不是与打开的文件相关联。
好的,我想问的是,如果我调用close(fd),还需要调用ofstream.close()吗?
是的,我就是这么说的。请注意,我还说过您可能需要完全停止使用 iostream。以上是关于无法获取文件锁定的主要内容,如果未能解决你的问题,请参考以下文章