Fortran OPEN 调用在 NFSv3 和 NFSv4 上有所不同
Posted
技术标签:
【中文标题】Fortran OPEN 调用在 NFSv3 和 NFSv4 上有所不同【英文标题】:Fortran OPEN-call differs on NFSv3 vs NFSv4 【发布时间】:2015-02-24 13:01:55 【问题描述】:我试图了解为什么您可以在 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(权限被拒绝)”,但是在我们看到另一个打开的 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(不允许操作)”,仅此而已(即应用程序失败)。
使用小型测试程序在 C 中进行相同的测试,在两种情况下都将无法打开文件(也就是说,在获得“EACCES”后,它不会尝试以“只读模式”打开文件“在 NFSv3 上)。
所以问题,
我假设上述行为是由于在 fortran 中实现了 OPEN 调用,并且如果 fortran 在尝试打开文件时收到“EACCES(权限被拒绝)”,它将自动尝试打开只读文件 (O_RDONLY)。这个假设正确吗?
我还假设在尝试打开文件时获得“EPERM(不允许操作)”时,fortran 没有这种“回退方法”。这个假设是正确的,还是我错过了什么?
C 似乎没有在“EACCES”或“EPERM”中实现“回退方法”。这对我来说似乎是正确的,因为这不会留下任何混淆的余地。如果您尝试以您无权执行的方式打开文件,则程序应该失败 - 我的意见。
我知道“权限被拒绝”和“操作不允许”之间有明显的区别。而且我猜想在 kerberos 上安装 NFSv4 时,有理由获得“Permission denied”而不是“Operation not allowed”,但是关于这个领域的一些澄清会很好。
当然,在 open-call (ACTION=READ) 中添加适当的标志可以解决问题。我只是对我的假设以及它们是否正确感到好奇。
【问题讨论】:
【参考方案1】:回答你的问题,按顺序:
当遇到 EACCES(或 EROFS)时,gfortran 将尝试以只读模式重新打开文件,这是正确的。
EPERM 没有以这种方式处理也是正确的,libgfortran 源代码树中根本没有提到它。
正如您所说,这是一个见仁见智的问题。 Gfortran 很久以前就决定这样做了,它似乎很适合用户。
我不明白为什么 NFS v4 在这种情况下会返回 EPERM。这似乎至少与我可以访问的 open(2) Linux 联机帮助页中的文档不一致,其中仅在指定 O_NOATIME 时才提到它(libgfortran 没有这样做)。至少,这种行为似乎不可移植。
【讨论】:
感谢您彻底的解释。我仍然不得不说,gfortran 的这种行为是有问题的,如果不是,它是不一致的。如果 gfortran 想要这种回退行为,我认为它应该在“所有情况下”回退当打开文件出现问题时” - 我的两分钱 =) 我已经为此问题提交了gcc.gnu.org/bugzilla/show_bug.cgi?id=65203。以上是关于Fortran OPEN 调用在 NFSv3 和 NFSv4 上有所不同的主要内容,如果未能解决你的问题,请参考以下文章