是否mmap()应该能够为O_WRONLY打开的文件创建只写映射?
mmap()
O_WRONLY
我问是因为在Linux 4.0.4 x86-64系统(strace日志)上以下操作失败:
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。
errno
EACCESS
更换开放标志O_WRONLY与O_RDWR收益率成功的映射。
O_RDWR
Linux mmap手册页将errno记录为:
mmap
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.
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.
因此,第二句记录了该行为。
但是其背后的原因是什么?
POSIX允许吗?
是内核还是库限制?(快速浏览,我在中找不到任何明显的东西Linux/mm/mmap.c)
Linux/mm/mmap.c
在 IEEE标准1003.1,2004年版 (2004年POSIX.1)似乎禁止它。
一个实现可能允许除规定以外的访问prot; 但是,如果支持“内存保护”选项,则该实现将不允许PROT_WRITE未设置的地方成功写入,或者PROT_NONE单独设置的地方不允许任何访问。实现应支持至少以下值prot:PROT_NONE,PROT_READ,PROT_WRITE,和按位包括OR的PROT_READ和PROT_WRITE。如果不支持“内存保护”选项,则与指定保护冲突的任何访问的结果都是不确定的。 无论指定了什么保护选项,都应在具有读取许可的情况下打开 文件描述符fildes。如果PROT_WRITE如果指定了,则应用程序应确保它已打开了fildes具有写许可权的文件描述符,除非MAP_PRIVATE在flags如下所述的参数中指定。
prot
PROT_WRITE
PROT_NONE
PROT_READ
fildes
MAP_PRIVATE
flags
(添加了重点)
同样,在x86上,不可能有只写存储器,这是页表项的限制。页面可以标记为只读或读写,并且可以独立地是可执行的或不可执行的,但不能是只写的。此外,的手册页mprotect()还说:
mprotect()
是否PROT_EXEC有任何不同之处PROT_READ取决于体系结构和内核版本。在某些硬件体系结构(例如i386)上,PROT_WRITE暗含PROT_READ。
PROT_EXEC
在这种情况下,您已经打开了没有读取访问权限的文件描述符,但是mmap()将O_WRONLY通过赋予您PROT_READ权限来绕过文件描述符。相反,它将完全拒绝EACCESS。