c++ - 无法获取文件的锁

标签 c++ linux filelock

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 小时里一直坚持这个。

谁能告诉我这有什么问题吗?

最佳答案

您遇到了 POSIX 文件锁中最严重的设计错误之一。您可能不知道这一点,因为您只阅读了 lockf manpage ,而不是fcntl manpage ,所以这是 fcntl 联机帮助页的重要部分:

  • If a process closes any file descriptor referring to a file, then all of the process's locks on that file are released, regardless of the file descriptor(s) on which the locks were obtained.

这意味着,在你的这段代码中

    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 中使用的!

为了安全地使用 POSIX 锁,您必须确保每个进程对要锁定的文件调用 open()一次且仅一次,绝不能重复文件描述符,并且只有在准备释放锁时才必须再次关闭它。因为可能没有任何方法(即使使用不可移植的扩展)从文件描述符构造 iostreams 对象,或从 iostreams 对象提取文件描述符,所以阻力最小的路径是仅使用 操作系统级 I/O 原语(openclosereadwritefcntllseekftruncate)以及需要应用 POSIX 锁的文件。

关于c++ - 无法获取文件的锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40158452/

相关文章:

Java 文件锁 : How to Load Dynamic Library From Locked File?

c++ - 将表示二维数组的 std::vector<std::vector <double>> 转换为 cv::Mat

c++ - 重载函数运算符是否允许创建在语法上像 C++ 中的函数一样工作的对象?

c - 获取用户输入并将其分割成一个结构,以便传回给 execvp

linux - 从另一个脚本运行 bash 脚本并在第二个脚本运行时退出第一个脚本

linux - 在 Web 服务器根目录中使用符号链接(symbolic link)

C++ NOT位运算符二进制char转换

c++ - make_pair 如何知道其参数的类型?

python - 文件锁未按预期工作

perl - 我的 Linux 守护进程如何知道 Windows 程序何时停止写入我通过 SAMBA 访问的文件?