只写映射O_WRONLY打开的文件应该工作?

mmap()应该能够创build一个O_WRONLY打开文件的只写映射?

我问,因为以下在Linux 4.0.4 x86-64系统( strace日志)上失败:

 mkdir("test", 0700) = 0 open("test/foo", O_WRONLY|O_CREAT, 0666) = 3 ftruncate(3, 11) = 0 mmap(NULL, 11, PROT_WRITE, MAP_SHARED, 3, 0) = -1 EACCES (Permission denied) 

errno等于EACCESS

O_RDWRreplace开放标志O_WRONLY产生一个成功的映射。

Linux mmap手册页将errnologging为:

  EACCES A file descriptor refers to a non-regular file. Or a file map‐ ping was requested, but fd is not open for reading. Or MAP_SHARED was requested and PROT_WRITE is set, but fd is not open in read/write (O_RDWR) mode. Or PROT_WRITE is set, but the file is append-only. 

因此,第二句话logging了这种行为。

但背后的原因是什么?

POSIX允许吗?

这是一个内核还是一个库限制? (瞥一眼,我在Linux/mm/mmap.c找不到任何明显的东西)

编辑

IEEE Std 1003.1,2004版 (POSIX.1 2004)似乎禁止它。

一个实现可能允许除prot指定的访问以外的访问; 但是,如果支持“存储器保护”选项,那么在PROT_WRITE尚未设置的情况下,实现将不允许写入成功,或者不允许任何单独设置了PROT_NONE访问。 该实现应至少支持下面的prot值: PROT_NONEPROT_READPROT_WRITE ,以及PROT_READPROT_WRITE的按位包含的OR。 如果不支持内存保护选项,则与指定保护冲突的任何访问的结果都是未定义的。 无论指定的保护选项如何,文件描述符fildes应该以读取权限打开 。 如果指定了PROT_WRITE ,那么应用程序应确保它已经用写权限打开了文件描述符fildes ,除非在flags参数中指定了MAP_PRIVATE ,如下所述。

(强调加)

此外,在x86上,不可能拥有只写内存,这是页表项的限制。 页面可能被标记为只读或读写,并且独立可能是可执行的或不可执行的,但不能是只写的。 此外, mprotect()说:

PROT_READ是否具有与PROT_READ不同的效果取决于体系结构和内核版本。 在某些硬件体系结构上(例如i386), PROT_WRITE意味着PROT_READ

在这种情况下,你已经打开了一个没有读访问权限的文件描述符,但是mmap()会通过给你PROT_READ权限绕过O_WRONLY 。 相反,它会拒绝与EACCESS彻底。

我不认为x86硬件支持只写页面,所以写访问意味着读取。 但是它似乎是一个比x86更为普遍的要求 – mm/mmap.cdo_mmap_pgoff()包含了这个代码:

  case MAP_SHARED: if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) return -EACCES; .... /* fall through */ case MAP_PRIVATE: if (!(file->f_mode & FMODE_READ)) return -EACCES; 

我认为这解释了你所看到的。