尝试让不同的 Linux节点上的多个进程写入Windows共享文件夹中的共享CSV文件。
我通过在不同节点上启动2个进程来测试它是否有效,每个节点都向文件追加10k行。然后我检查行数是否为20k。不幸的是,行数几乎总是小于那个。我正在使用Linux 3.0.51和Windows Server 2008 R2。但是,锁定多个进程在 1节点内的确可以使用flock(),但不能用于fcntl()。
以下是我尝试过的其他一些事情:
使用NFS - 确实有效! (有时行数是19999)
使用Linux内核4.10并挂载为SMB 3.02 - 不起作用
使用Samba作为服务器 - 即使使用严格锁定= yes也不起作用 如下所述:
https://www.samba.org/samba/docs/man/Samba-HOWTO-Collection/locking.html
有没有人让它工作或知道无法完成(以及配置)?这是我的测试程序:
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/file.h>
#include <boost/interprocess/sync/file_lock.hpp>
// method 0: fcntl() - works for NFS and across multiple nodes, but not for CIFS/SMB
// method 1: flock() - works for SMB within 1 node, but not accross multiple nodes
// method 2: Boost (internally uses fcntl)
#define METHOD 1
using namespace std;
class FileLock
{
public:
#if METHOD == 2
FileLock(const char *path) : lock(path)
{
}
#else
FileLock(int f)
{
file = f;
#if METHOD == 0
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
#endif
}
#endif
bool Lock()
{
#if METHOD == 0
lock.l_type = F_WRLCK;
return fcntl(file, F_SETLKW, &lock) == 0;
#elif METHOD == 1
return flock(file, LOCK_EX) == 0;
#elif METHOD == 2
lock.lock();
return true;
#endif
}
bool Unlock()
{
#if METHOD == 0
lock.l_type = F_UNLCK;
return fcntl(file, F_SETLKW, &lock) == 0;
#elif METHOD == 1
return flock(file, LOCK_UN) == 0;
#elif METHOD == 2
lock.unlock();
return true;
#endif
}
int file;
#if METHOD == 0
struct flock lock;
#elif METHOD == 2
boost::interprocess::file_lock lock;
#endif
};
int main(int argc, char **argv)
{
int repeats = 100;
double interval = 0.1;
char message[256];
sprintf(message, "testing 123\n");
if (argc >= 2)
repeats = atoi(argv[1]);
if (argc >= 3)
interval = atof(argv[2]);
if (argc >= 4)
{
sprintf(message, "%s\n", argv[3]);
}
FILE *f = fopen("a.txt", "a");
if (f == NULL)
{
cout << "can't open" << endl;
return 1;
}
#if METHOD == 2
FileLock lock("a.txt");
#else
FileLock lock(fileno(f));
#endif
for (int i = 0; i < repeats; ++i)
{
if (!lock.Lock())
cout << "error locking " << strerror(errno) << "\n";
// file in append mode will automatically write to end, but does it work when there are multiple writers?
fseek(f, 0, SEEK_END);
fwrite(message, 1, strlen(message), f);
if (!lock.Unlock())
cout << "error unlocking\n";
usleep(interval * 1000000);
}
fclose(f);
return 0;
}