我正在用C ++实现一些文件系统。到目前为止,我正在使用fstream
,但我意识到无法以独占模式打开它。由于有许多线程我想允许多次读取,并且在写入模式下打开文件时我想以独占模式打开文件?
最好的方法是什么?我认为Boost
提供了一些功能。还有其他可能性吗?我还想看一个简单的例子。如果用C ++做起来不容易/好,我也可以用C语言编写。
我正在使用Windows。
答案 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)
您可以重命名该文件,使用新名称对其进行更新,然后将其重命名。我已经做到了,但它有点沉重。