mmap()docs提到标志MAP_UNINITIALIZED,但标志似乎没有被定义。
试图在Centos7和Xenial上,两个发行版都没有sys/mman.h
中所定义的标志
令人惊讶的是,互联网似乎并没有意识到这一点。这是什么故事?
编辑:我从文档中了解到,该标志仅在嵌入式或低安全性设备上受到尊重,但这并不意味着该标志不应被定义......您如何使用它便携代码?在不支持的情况下,Google已将代码定义为0
,但在我的情况下,它根本没有定义。
答案 0 :(得分:1)
内核通常需要清除内存,以保护内核空间和其他进程内存的隐私。
继续阅读:
仅当内核配置了CONFIG_MMAP_ALLOW_UNINITIALIZED选项时,才会使用此标志。由于安全隐患,该选项通常仅在嵌入式设备上启用(即,可以完全控制用户内存内容的设备)。
答案 1 :(得分:1)
为了理解如何处理#include <sys/mman.h>
未定义MAP_UNINITIALIZED
这一事实,了解如何定义内核接口是有帮助的。
要构建内核模块,您将需要用于构建内核的内核头,以用于您希望为其构建模块的内核的确切版本。如果您希望在用户空间中运行,您将不再需要这些。
为用户空间定义内核API的标头主要位于/usr/include/linux
和/usr/include/asm
(有关如何生成它们,请参阅this)。这些标头中最重要的消费者之一是C标准库,例如,glibc
,它必须针对这些标头的某些版本构建。由于Linux内核API是向后兼容的,因此您可能有一个glibc(或其他库实现)针对这些标头的旧版本而不是您运行的内核构建。我并不是所有各种发行版分发glibc的专家,但我的印象是定义其用户空间API的内核头文件通常是glibc构建的版本。
最后,glibc通过也安装在/usr/include
下的标头(例如/usr/include/sys
)来定义其API。我不确切知道为使用较旧或较新的glibc标头构建的应用程序提供了什么(如果有的话)向后或向前兼容性,但我猜测当向后可比性时,库.so版本号会受到影响碎。
现在我们可以理解您的问题是glibc标头实际上没有为您尝试过的发行版/版本定义MAP_UNINITIALIZED
。
然而,正如this patch所示,Linux内核API已经公开了MAP_UNINITIALIZED
。如果glibc标头没有为您定义它,您可以使用linux内核API标头和#include <linux/mman.h>
(如果这定义它)。请注意,为了获得mmap的原型,您仍然需要#include <sys/mman.h>
。
如果你的linux内核API标题没有定义MAP_UNINITIALIZED
但你有一个实现它的内核版本,你可以自己定义它:
#define MAP_UNINITIALIZED 0x4000000
您不必担心自己有效地使用&#34;更新&#34;标头比你的glibc构建的,因为mmap
的glibc实现非常薄:
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sysdep.h>
#ifndef MMAP_PAGE_SHIFT
#define MMAP_PAGE_SHIFT 12
#endif
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
if (offset & ((1 << MMAP_PAGE_SHIFT) - 1))
{
__set_errno (EINVAL);
return MAP_FAILED;
}
return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
offset >> MMAP_PAGE_SHIFT);
}
weak_alias (__mmap, mmap)
只是将你的旗帜直接传递给内核。