Fortran OPEN 调用在 NFSv3 和 NFSv4 上有所不同

Fortran OPEN-call differs on NFSv3 vs NFSv4

我试图理解为什么你可以在 NFSv3 上以读写模式对你只有读权限的文件进行 OPEN 调用,而如果你做同样的事情在 NFSv4 上,OPEN 调用将失败。

让我解释一下,下面是一个简单的 fortran 程序,它以读写模式打开给定文件(程序的参数),

PROGRAM test_open

 IMPLICIT NONE

 ! Parameters

 INTEGER,            PARAMETER :: lunin = 10
 CHARACTER(LEN=100) :: fname

 ! Local

 INTEGER :: i,ierr,siteid,nstation
 REAL :: lat, lon, asl
 CHARACTER(len=15) :: name

 !----------------------------------------------------------------
 !
 ! Open input file
 !

 CALL getarg(1,fname)

 OPEN(lunin,file=fname,STATUS='OLD',IOSTAT=ierr)

 IF ( ierr /= 0 ) THEN
    WRITE(6,*)'Could not open ',TRIM(fname),ierr
    STOP
 ENDIF

 WRITE(6,*)'Opened OK'

 CLOSE(lunin)


END PROGRAM test_open

将以上内容保存在 test_open.f90 中并使用

进行编译
gfortran -o fortran test_open.f90 

现在,使用 NFSv3 在挂载点上执行以下命令,

strace -eopen ./fortran file-with-only-read-permissions 

您应该会看到以下几行(以及许多其他输出),

> open("file-with-only-read-permissions", O_RDWR)  = -1 EACCES (Permission denied)
> open("file-with-only-read-permissions", O_RDONLY) = 3

所以,我们可以清楚地看到我们在 'O_RDWR' 中尝试打开时得到一个 "EACCES (Permission denied)" (打开读写), 紧随其后我们看到另一个 open O_RDONLY (以只读方式打开)并且成功了。

运行 NFSv4 共享文件上的相同程序,我们得到以下内容,

strace -eopen ./fortran file-with-only-read-permissions-on-nfsv4-share 
> open("file-with-only-read-permissions-on-nfsv4-share", O_RDWR)  = -1 EPERM (Operation not permitted) 

所以,这里我们在尝试打开 'O_RDWR' 中的文件(打开读写)时得到一个 "EPERM (Operation not permitted)",仅此而已(即应用程序失败)。

用一个小的测试程序在 C 中做同样的测试,在这两种情况下都无法打开文件(也就是说,在获取 "EACCES" 在 NFSv3 上)。

所以对于问题,

当然,在打开调用 (ACTION=READ) 中添加适当的标志可以解决问题。我只是好奇我的假设以及它们是否正确。

回答你的问题,顺序是:

  • 你说得对,当遇到 EACCES(或 EROFS)时,gfortran 会尝试以只读模式重新打开文件。

  • EPERM 没有以这种方式处理也是正确的,libgfortran 源代码树中根本没有提到它。

  • 如你所说,见仁见智。 Gfortran 很早以前就决定这样做了,看起来很适合用户。

  • 我不明白为什么 NFS v4 returns EPERM 会出现这种情况。这似乎至少与我有权访问的 open(2) Linux 联机帮助页中的文档不一致,其中仅在指定 O_NOATIME 时提及(libgfortran 不这样做)。至少,这种行为似乎不可移植。