>问题:在Linux平台上创建新文件或覆盖现有文件,以便其他进程可以打开它进行读取。使用CreateFile
可以执行以下操作:
CreateFile("blah.log", GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
如果现有文件由具有类似标志的另一个进程打开,则此调用将无法覆盖该文件。
如何在 Linux 上实现类似的行为?假设所有程序都遵循咨询锁。
使用open
和咨询flock
锁定,编写者需要持有LOCK_EX
独占锁。读取器不得持有任何锁,然后他们可能会看到文件被突然截断。
普通fopen
可用于读者。对于表现良好的作家,
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <fcntl.h>
#include <stdio.h>
// never truncates
int fd = open("foo.log", O_CREAT|O_WRONLY /*or O_RDWR */, 0644 /* mode */);
if (flock(fd, LOCK_EX|LOCK_NB) != 0) {
perror("Locking failed - I am not an exclusive writer");
exit(1);
}
// I hold the exclusive lock - now, truncate the file to 0 bytes
ftruncate(fd, 0);
(为简洁起见,省略了其他错误检查(
如果您希望从那里对文件使用<stdio.h>
例程,您可以使用fdopen
:
// "w" will not truncate!
FILE *f = fdopen(fd, "w"); // or `r+` for O_RDWR...
请注意,读取器不得在文件上设置LOCK_SH
锁,否则编写器无法打开该文件。
您正在寻找flock
和lockf
功能:)
其中大部分都是基于man 2 flock
和man lockf
,所以我衷心推荐阅读它。
这是来自man lockf
#include <unistd.h> int lockf(int fd, int cmd, off_t len);
。
描述
在打开的文件的某个部分应用、测试或删除 POSIX 锁定。 该文件由 fd 指定,一个打开的文件描述符 写作,CMD的行动,该部分包括 字节位置位置。POS+len-1 如果 len 为正,则 pos-len..POS-1 如果 len 为负数,则 pos 是当前文件 位置,如果 len 为零,则截面从 当前文件位置到无穷大,包括当前和将来的文件结束位置。 在所有情况下,该部分都可能扩展 过去的当前文件结尾。
在 Linux 上,
lockf()
只是 fcntl(2( 锁定之上的一个接口。 许多其他系统以这种方式实现lockf()
, 但请注意,POSIX.1 留下了 未指定lockf()
和fcntl(2)
锁。 可移植应用程序可能应避免混合调用这些接口。有效操作如下:
F_LOCK
在文件的指定部分设置独占锁。 如果此部分(部分(已被锁定,则调用将阻止,直到释放上一个锁定。 如果此部分与较早锁定的部分重叠,则两者将合并。 一旦持有锁的进程关闭文件的某些文件描述符,文件锁就会释放。 子进程不会继承这些锁。F_TLOCK
与F_LOCK
相同,但如果文件已锁定,则调用永远不会阻止并返回错误。F_ULOCK
解锁文件的指定部分。 这可能会导致锁定部分拆分为两个锁定部分。F_TEST
测试锁:如果指定的部分被此进程解锁或锁定,则返回 0;如果另一个进程持有锁,则返回-1
,将errno
设置为EAGAIN
(在其他一些系统上EACCES
(。
但这只是一个独占锁,所以不太适合单写机、多读卡器的情况。
我会看看 unix 套接字 (man unix
(。它们的工作方式类似于文件或套接字(它们是套接字,但您可以在它们上使用 file-io 函数(,并且尝试关联其他人已经拥有的套接字(可以像普通文件一样驻留在文件系统中(将失败。
老实说,您尝试做的事情听起来很像IPC(进程间通信(,这很好 - 但您可能想看看simlper共享内存协调!shmget
和类似的东西将允许您以非常类似文件的方式打开内容,并且您可以以高性能直接在进程之间交换数据,而不会招致将数据写入磁盘的损失。(非常相似地,您可以将实际文件映射到内存中做同样的事情,但这并不能解决锁定问题(。
但是:这些是解决IPC问题的非常低层次的方法。我建议实际使用 IPC 库。有很多可以满足不同系统的需求 - 从大型集群类系统的MPI,到非常好的基于套接字的系统,或类似套接字的灵活系统(想到zeroMQ(。