mmap()
是否应该能够创建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_WRONLY
替换open-flag O_RDWR
会产生成功的映射。
Linux mmap
手册页将errno记录为:
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
)
答案 0 :(得分:4)
IEEE Std 1003.1, 2004 Edition (POSIX.1 2004)似乎禁止它。
实施可能允许除
prot
指定的访问以外的访问;但是,如果支持Memory Protection选项,则实现不允许写入在未设置PROT_WRITE
的情况下成功,或者不允许任何仅在PROT_NONE
设置的情况下进行访问。实现应至少支持prot
:PROT_NONE
,PROT_READ
,PROT_WRITE
的以下值以及PROT_READ
和{{1}的按位包含OR }}。如果不支持“内存保护”选项,则任何与指定保护冲突的访问结果都是未定义的。 无论指定的保护选项如何,都应以读取权限打开文件描述符PROT_WRITE
。如果指定了fildes
,则应用程序应确保已使用写入权限打开文件描述符PROT_WRITE
,除非fildes
参数中指定了MAP_PRIVATE
,如下所述。
(强调补充)
此外,在x86上,不可能具有只写内存,这是页表条目的限制。页面可以标记为只读或读写,并且可以是可执行的或不可执行的,但不能是只写的。此外,flags
的手册页说:
mprotect()
是否具有与PROT_EXEC
不同的任何效果,取决于体系结构和内核版本。在某些硬件体系结构(例如,i386)上,PROT_READ
暗示PROT_WRITE
。
在这种情况下,您已经打开了一个没有读访问权限的文件描述符,但PROT_READ
会绕过mmap()
,但会授予您O_WRONLY
权限。相反,它将完全拒绝PROT_READ
。
答案 1 :(得分:4)
我不认为x86硬件支持只写页面,因此写访问意味着读取。但它似乎是一个比x86更普遍的要求 - mm/mmap.c
在do_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;
我认为这可以解释您所看到的内容。