我有以下c ++代码,在管理文件锁时将"Line from #"
写入文件。我在两台不同的计算机上运行此代码,这些计算机至少共享一些内存。那是我可以通过登录这些计算机来访问我的文件。
在第一台计算机上,我将程序作为./test 1
运行(例如,它将打印Line from 1
20,000次),在第二台计算机上,我将程序作为./test 17
运行。我正在及时启动这些程序,以便file.txt
的写入应该由文件锁交错和控制。
问题是我丢失了输出,因为该文件有22,770个换行符,但它应该有40,000个换行符。
wc file.txt
22770 68310 276008 file.txt
此外,
cat -n file.txt | grep 18667
18667 ne from 17
我的问题是为什么我的文件锁定不会阻止文件覆盖,以及如何修复我的代码以便多个进程可以写入同一个文件而不会丢失文件。
#include <unistd.h>
#include <fcntl.h>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
void inline Set_Lck(struct flock &flck, const int fd)
{
flck.l_type = F_WRLCK;
if (fcntl(fd, F_SETLKW, &flck) == -1) {
perror("fcntl");
exit(1);
}
}
void inline Release_Lck(struct flock &flck, const int fd)
{
flck.l_type = F_UNLCK;
if (fcntl(fd,F_SETLK,&flck) == -1) {
perror("fcntl");
exit(1);
}
}
void Print_Spec(fstream &fout, ostringstream &oss,struct flock &flck, const int fd)
{
Set_Lck(flck,fd);
fout.seekp(0,ios_base::end);
fout << oss.str() << endl;
flush(fout);
Release_Lck(flck,fd);
}
int main(int argc, char **argv)
{
int fd_cd;
struct flock flock_cd;
ostringstream oss;
fstream comp_data;
const string s_cd_lck = "file_lock.txt";
const string s_cd = "file.txt";
int my_id;
if (argc == 1) {
my_id = 0;
} else if (argc == 2) {
my_id = atoi(argv[1]);
} else {
fprintf(stderr,"error -- usage ./test [my_id]\n");
exit(1);
}
/* Open file computed_data.txt for writing; create it if non-existent.*/
comp_data.open(s_cd.c_str(),ios::app|ios::out);
if (comp_data.fail()) {
perror("comp_data.open");
exit(1);
}
/* Open file that we will be locking. */
fd_cd = open(s_cd_lck.c_str(),O_CREAT|O_WRONLY,0777);
if (fd_cd == -1) {
perror("fd_cd = open");
exit(1);
}
/* Set up the lock. */
flock_cd.l_type = F_WRLCK;
flock_cd.l_whence = SEEK_SET;
flock_cd.l_start = 0;
flock_cd.l_len = 0;
flock_cd.l_pid = getpid();
for (int i = 0; i < 20000; ++i) {
oss.str(""); /* Yes, this can be moved outside the loop. */
oss << "Line from " << my_id << endl;
Print_Spec(comp_data,oss,flock_cd,fd_cd);
}
return 0;
}
我正在使用c ++,此程序正在Red Hat Enterprise Linux Server release 7.2 (Maipo).
我的研究
我不确定部分答案是否来自以下Stackoverflow帖子(https://stackoverflow.com/a/2059059/6417898),其中他们声明“锁定绑定到进程”。
在此网站(http://perl.plover.com/yak/flock/samples/slide005.html),作者不鼓励LOCK_UN
使用flock
并建议每次关闭文件并根据需要重新打开,以便刷新文件缓冲区。我不知道这是否会继续fcntl
,或者如果手动刷新文件缓冲区,甚至是必要的。