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_RDWR
replace开放标志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_NONE
,PROT_READ
,PROT_WRITE
,以及PROT_READ
和PROT_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.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;
我认为这解释了你所看到的。