Linux文件锁定

时间:2017-08-19 09:44:12

标签: c linux windows locking

问题:在Linux平台上创建新文件或覆盖现有文件,以便其他进程可以打开它进行只读。使用CreateFile可以执行以下操作:

CreateFile("blah.log", GENERIC_WRITE, FILE_SHARE_READ,
           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

如果现有文件由具有类似标志的其他进程打开,则此调用将无法覆盖现有文件。

如何在Linux上实现类似的行为?假设所有程序都遵守咨询锁。

2 个答案:

答案 0 :(得分:0)

使用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锁定,否则作者无法打开。

答案 1 :(得分:0)

您正在寻找flocklockf功能:)

这大部分基于man 2 flockman lockf,因此我衷心建议您阅读。

来自man lockf

#include <unistd.h>

int lockf(int fd, int cmd, off_t len);
     

...

     

说明

     

在打开文件的某个部分上应用,测试或删除POSIX锁。该文件由fd指定,文件描述符打开   写作,cmd的动作,以及该部分   字节位置pos..pos + len-1如果len为正,如果len为负则为pos-len..pos-1,其中pos为当前文件   位置,如果len为零,则该部分从   当前文件位置为无穷大,包含当前和未来的文件结束位置。在所有情况下,该部分可以延长   过去当前的文件结束。

     

在Linux上,lockf()只是fcntl(2)锁定之上的一个接口。许多其他系统以这种方式实现lockf(),   但请注意POSIX.1之间的关系   lockf()fcntl(2)未指定锁定。便携式应用程序应该避免混合调用这些接口。

     

有效操作如下:

     
      
  • F_LOCK在文件的指定部分设置独占锁。如果此部分的(部分)已被锁定,则调用将阻塞,直到释放上一个锁定为止。如果此部分与先前锁定的部分重叠,则两者都会合并。只要持有锁的进程关闭文件的某些文件描述符,就会释放文件锁。子进程不会继承这些锁。
  •   
  • F_TLOCKF_LOCK相同,但如果文件已被锁定,则调用永远不会阻止并返回错误。
  •   
  • F_ULOCK解锁文件的指定部分。这可能导致锁定的部分被分成两个锁定的部分。
  •   
  • F_TEST测试锁定:如果指定的部分被此过程解锁或锁定,则返回0;返回-1,将errno设置为EAGAIN(其他系统上为EACCES),如果其他进程持有锁定。
  •   

但那只是一个独家锁,所以不太适合单个作家,多读者案例。

我查看unix套接字(man unix)。它们像文件或类似套接字一样工作(它们是套接字,但你可以在它们上使用file-io函数),并试图将一个其他人已经拥有的套接字(可以像普通文件一样驻留在文件系统中)关联起来失败。

说实话,你尝试做的事听起来很像IPC(进程间通信),这很好 - 但你可能想看看simlper共享内存协调! shmget和类似的东西将允许您以类似文件的方式打开事物,并且您可以以高性能直接在进程之间交换数据,而不会产生将数据写入磁盘的惩罚。 (你可以非常类似地将memmapping实际文件存储到内存中,但这并不能解决锁定问题)。

但是:这些是解决IPC问题的非常低级的方法。我建议实际使用IPC库。有很多适合不同系统需求的东西 - 从用于大型集群系统的MPI到非常好的基于套接字的系统,或类似套接字的灵活系统(想到零置业)。 / p>