我试图理解为什么你可以在一个只读取权限的文件上以读写方式在NFSv3的fortran上打开一个OPEN-call的区别,而如果你在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(权限被拒绝)”, 但是在我们看到另一个打开的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(不允许操作)”,而没有其他任何东西(即应用程序失败)。
在一个小的testing程序中使用C进行相同的testing时,它将无法在两种情况下打开文件(也就是说,在NFSv3上获取“EACCES”后,将不会尝试以“只读模式”打开文件)。
所以对于这些问题,
我假设上述行为是由于fortran中的OPEN调用的实现引起的,如果fortran在试图打开文件时得到“EACCES(Permission denied)”,它将自动尝试以只读方式打开文件(O_RDONLY)。 这个假设是否正确?
我也假设Fortran在尝试打开文件时没有获得“EPERM(操作不允许)”的“后备方法”。 这个假设是正确的,还是我错过了什么?
C似乎并没有在“EACCES”和“EPERM”中实现“后备方法”。 这对我来说似乎是正确的,因为这没有任何混淆的余地。 如果您尝试以无权执行的方式打开文件,该程序会失败 – 我的意见。
我知道“权限被拒绝”和“不允许的操作”有明显的区别。 而且我猜测,在Kerberos上安装NFSv4时,有一个原因是“拒绝权限”而不是“操作不允许”,但是对这个区域的一些澄清是很好的。
当然,在open-call(ACTION = READ)中添加适当的标志可以解决这个问题。 我只是好奇我的假设,如果他们是正确的。
为了回答你的问题,按顺序:
如果遇到EACCES(或EROFS),gfortran会尝试以只读模式重新打开文件,这是正确的。
EPERM不是这样处理的,你也是正确的,它在libgfortran源代码树中根本没有提到。
正如你所说,这是一个意见的问题。 Gfortran很早以前就做出这样的决定,而且似乎很适合用户。
我不明白为什么NFS v4在这种情况下返回EPERM。 这似乎与我可以访问的open(2)Linux联机帮助页上的文档至少不一致,在那里只有在指定了O_NOATIME(libgfortran没有这样做)的情况下才提到。 至少,这种行为似乎不是可移植的。