简体   繁体   English

无法获取文件锁定

[英]can't acquire a lock on a file

FileLocker_wo.h 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 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 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 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;
}

I am trying to get a file lock in one process and checking whether there is any lock on that file in other process using lockf (p1.cpp, p2.cpp). 我正在尝试在一个进程中获取文件锁,并使用lockf(p1.cpp,p2.cpp)检查在另一个进程中该文件是否有任何锁。

In p1.cpp I am locking the file hello.txt and waiting for 5 seconds. 在p1.cpp中,我锁定了hello.txt文件并等待5秒钟。 Meanwhile I start p2.cpp and checking whether any lock is there by other process, but always getting there is no lock> I am stuck with this for last 2 hours. 同时,我启动p2.cpp并通过其他进程检查是否有任何锁定,但始终没有锁定>我在最近2个小时中一直停留在此状态。

Can anybody tell what is wrong in this? 谁能告诉我这是什么问题?

You've tripped over one of the nastier design errors in POSIX file locks. 您已经克服了POSIX文件锁中最棘手的设计错误之一。 You probably didn't know about this because you only read the lockf manpage , not the fcntl manpage , so here's the important bit of the fcntl manpage: 你可能不知道这一点,因为你只读过lockf手册页 ,而不是fcntl手册页 ,所以这里的重要位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. 如果某个进程关闭了引用该文件的任何文件描述符,则该进程对该文件的所有锁定都将被释放,无论在哪个文件描述符上获得了锁定。

What this means is, in this bit of your code 这意味着在这段代码中

    if (Utils::FileLocker::lock_file("hello.txt", fd))
    {
            std::ofstream out("hello.txt");
            out << "hello ding dong" << std::endl;
            out.close();

you lose your lock on the file when you call out.close() , even though out is a different OS-level "open file description" than you used in lock_file ! 即使 out是与lock_file使用的操作系统级别的“打开文件描述”,您在调用out.close()也会丢失对文件的锁定!

In order to use POSIX locks safely you must ensure that you call open() on the file to be locked once and only once per process, you must never duplicate the file descriptor, and you must only close it again when you are ready to drop the lock. 为了安全地使用POSIX锁,您必须确保对要锁定的文件调用一次open()并且每个进程调用一次 ,不得复制文件描述符,并且仅在准备删除时才再次关闭它锁。 Because there may not be any way (even using unportable extensions) to construct an iostreams object from a file descriptor, or to extract a file descriptor from an iostreams object, the path of least resistance is to use only OS-level I/O primitives ( open , close , read , write , fcntl , lseek , ftruncate ) with files that you need to apply POSIX locks to. 因为可能没有任何方法(甚至使用不可移植的扩展名)从文件描述符构造iostreams对象,或从iostreams对象提取文件描述符,所以阻力最小的途径是使用OS级I / O原语( openclosereadwritefcntllseekftruncate )包含您需要对其应用POSIX锁的文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM