我不知道为什么这个代码在 NFS4 下不起作用,使用 NFS3 可以完美运行。这个想法是为了避免在进程仍在读取文件时写入文件。
我想调试,但我们的系统管理员无法调试。这可能是原因。在我们的 NFS4 安装下,我总是遇到这种情况
if ( flock(fp,LOCK_EX) == -1)
printf("Error: file %s is already locked\n", fileName);
整个程序如下:
#include <sys/file.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv){
if (argc<2){
printf("Usage:\n a.out fileName\n");
return 1;
}
char *fileName=argv[1];
int fp;
/* block the file, I know a process can write
rendering my information useless*/
fp=open(fileName,O_RDONLY);
if ( flock(fp,LOCK_EX) == -1){
printf("Error: file %s is already locked\n", fileName);
}
else{
printf("OK: file %s was locked\n",fileName );
}
/* read and parse the fileName
another process should not be able to write or
modify the fileName while I am reading it
*/
return 0;
}
编辑:我想澄清一下。这是我正在使用的代码片段。fileName 应该是一个有效的现有文件
我正在读取一个文件名并进行复制,编辑一些部分。我知道,当我这样做时,外部进程可以更新文件名。我想使用信号量来避免修改此文件,直到我完成它。这个程序运行正常,直到停止这样做。唯一的区别是文件名所在的文件系统。它从 NFS3 更新到 NFS4。甚至操作系统 (SLE15.2) 与内核 5.3.18 相同,使用 strerror(errno) 会在 NFS4 上产生段错误。当我执行 print("%d",error) 时,唯一的提示是 9,应该是“错误的文件描述符”
感谢您的帮助
朱莉娅
答案1
我刚刚检查了 flock 的手册页,在 NOTES 部分有重要部分:
NFS details
In Linux kernels up to 2.6.11, flock() does not lock files over NFS (i.e., the scope of locks was limited to the local system). Instead, one could use fcntl(2) byte-range locking, which does
work over NFS, given a sufficiently recent version of Linux and a server which supports locking.
Since Linux 2.6.12, NFS clients support flock() locks by emulating them as fcntl(2) byte-range locks on the entire file. This means that fcntl(2) and flock() locks do interact with one
another over NFS. It also means that in order to place an exclusive lock, the file must be opened for writing.
Since Linux 2.6.37, the kernel supports a compatibility mode that allows flock() locks (and also fcntl(2) byte region locks) to be treated as local; see the discussion of the local_lock
option in nfs(5).
您仅打开文件进行读取,这就是 flock 调用失败的原因。
答案2
这段代码:
if ( flock(fp,LOCK_EX) == -1){
printf("Error: file %s is already locked\n", fileName);
}
else{
printf("OK: file %s was locked\n",fileName );
}
实际上只能告诉您锁定失败或成功,但不能告诉您原因。您应该修改它以报告errno
失败的原因,因为它可能表明锁定存在更根本的问题 - 例如尝试打开您无权访问或不存在的文件。
if ( flock(fp,LOCK_EX) == -1){
printf("Error: file %s is already locked: %s\n", fileName, strerror(errno));
}
else{
printf("OK: file %s was locked\n",fileName );
}
您可能还希望将其包含errno.h
在包含列表中,以确保您找到正确的变量。
答案3
NFS v3 在协议层面不支持锁定。此功能由附加功能(nfs 协议外部)提供锁管理器另一方面,NFS v4 将锁定作为规范的一部分。此外,有两种类型的锁。一种是字节范围锁,第二个是访问共享。虽然后者是您要寻找的,但是 POSIX API 并未公开它,因此不适用于 linux 和 unix。
要使锁定与 nfs v4 和 v3 配合使用,您需要使用字节范围锁定可用作函数或者锁功能。
检查 nfs 开发人员(包括我自己)使用的锁定测试代码,以验证与协议版本无关的客户端/服务器行为。