如何在C ++中以独占模式打开文件

时间:2013-04-22 06:49:19

标签: c++ io

我正在用C ++实现一些文件系统。到目前为止,我正在使用fstream,但我意识到无法以独占模式打开它。由于有许多线程我想允许多次读取,并且在写入模式下打开文件时我想以独占模式打开文件?
最好的方法是什么?我认为Boost提供了一些功能。还有其他可能性吗?我还想看一个简单的例子。如果用C ++做起来不容易/好,我也可以用C语言编写。

我正在使用Windows。

5 个答案:

答案 0 :(得分:2)

在许多操作系统上,它根本不可能,所以C ++ 不支持它。你必须自己编写streambuf。 如果你担心的唯一平台是Windows,你可以 可能使用它提供的独家开放模式。 但是,更有可能的是,您会想要使用某种文件 锁定,这是更精确的,如果没有,大多数可用 所有平台(但不是便携式) - 你需要LockFileEx 在Windows下,在Unix下为fcntl

在Posix下,您还可以使用pthread_rwlock。 Butenhof 使用经典互斥体和。来实现这个 条件变量,存在于C ++ 11中,所以你可以 实际上实现了一个便携版本(提供所有的 读者和作者在同一个过程中 - Posix 请求将跨进程边界工作,但事实并非如此 对于C ++线程原语来说是真的。)

答案 1 :(得分:2)

如果您的应用仅适用于Windows,则可以选择win32 API函数“CreateFile()”。

例如:HANDLE hFile = :: CreateFileW(lpszFileFullPathName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);

答案 2 :(得分:1)

如果你愿意使用boost,那么我建议你使用file_lock类。这意味着您要保留打开/关闭的文件的文件名,因为fstream不会为您执行此操作。

它们有两种模式lock(),你可以用它们来写(即一次只有一个这样的锁,可共享的锁也可以阻止这种锁)和你可以用来读取的lock_sharable()(即任意数量的线程都可以获得这样的锁定。)

请注意,您会发现以这种方式管理,读取和写入最终都很复杂。也就是说,如果总有人要阅读,那么可共享锁可能永远不会被释放。在这种情况下,独家锁将永远不会有机会......

// add the lock in your class
#include <boost/interprocess/sync/file_lock.hpp>
class my_files
{
...
private:
    ...
    boost::file_lock     m_lock;
};

现在,当您想要访问某个文件时,可以按照这种方式锁定它。如果线程在他们这样做时负责,您可以为用户添加访问锁的功能。如果my_files中的读写函数的实现是负责的,那么你想得到一个基于堆栈的对象,为你锁定和解锁(RAII):

class safe_exclusive_lock
{
public:
    safe_exclusive_lock(file_lock & lock)
        : m_lock_ref(lock)
    {
        m_lock_ref.lock();
    }
    ~safe_exclusive_lock()
    {
        m_lock_ref.unlock();
    }
private:
    file_lock & m_lock_ref;
};

现在你可以安全地锁定文件(即你锁定,执行可能抛出的东西,你总是在退出当前的{} -block之前解锁):

ssize_t my_files::read(char *buf, size_t len)
{
    safe_exclusive_lock guard(m_lock);
    ...your read code here...
    return len;
} // <- here we get the unlock()

ssize_t my_files::write(char const *buf, size_t len)
{
    safe_exclusive_lock guard(m_lock);
    ...your write code here...
    return len;
} // <- here we get the unlock()

file_lock使用一个文件,因此每当创建file_lock时,您都希望已经创建了fstream文件。如果可能没有在构造函数中创建fstream文件,您可能希望在唯一指针中转换m_lock变量:

private:
    std::unique_ptr<file_lock>  m_lock;

当你引用它时,你现在需要一个星号:

safe_exclusive_lock guard(*m_lock);

请注意,为了安全起见,您应该检查指针是否确实已分配,如果未定义,则表示该文件尚未打开,因此我建议您抛出:

if(m_lock)
{
    safe_exclusive_lock guard(*m_lock);
    ...do work here...
}
else
{
    throw file_not_open();
}
// here the lock was released so you cannot touch the file anymore

在开放状态下,您可以创建锁:

bool open(std::string const & filename)
{
    m_stream.open(...);
    ...make sure it worked...
    m_lock.reset(new file_lock(filename));
    // TODO: you may want a try/catch around the m_lock and
    //       close the m_stream if it fails or use a local
    //       variable and swap() on success...
    return true;
}

不要忘记在关闭时释放锁定对象:

void close()
{
    m_lock.reset();
}

答案 3 :(得分:0)

如果已经在写入模式下打开文件,您可以手动阻止自己打开文件。只需在内部跟踪您在写入模式下打开的文件。

也许您可以对文件名进行哈希处理,并在使用写访问权限打开时将其存储在表中。这将允许快速查找以查看文件是否已被打开。

答案 4 :(得分:0)

您可以重命名该文件,使用新名称对其进行更新,然后将其重命名。我已经做到了,但它有点沉重。