mmap 标志 MAP_UNINITIALIZED 未定义

mmap flag MAP_UNINITIALIZED not defined

mmap() 文档提到标志 MAP_UNINITIALIZED,但该标志似乎未定义。 在 Centos7 和 Xenial 上试过,这两个发行版都没有在 sys/mman.h 中定义的标志。
令人惊讶的是,互联网似乎并没有意识到这一点。有什么故事?

编辑:我从文档中了解到该标志仅在嵌入式或低安全性设备上有效,但这并不意味着不应定义该标志...如何在可移植代码中使用它? Google 揭示了在不受支持的情况下定义为 0 的代码,但在我的情况下它根本没有定义。

内核通常需要清除内存,以保护内核space和其他进程内存的隐私。

继续阅读:

This flag is honored only if the kernel was configured with the CONFIG_MMAP_ALLOW_UNINITIALIZED option. Because of the security implications, that option is normally enabled only on embedded devices (i.e., devices where one has complete control of the contents of user memory).

为了理解如何处理 #include <sys/mman.h> 没有定义 MAP_UNINITIALIZED 的事实,了解内核接口是如何定义的是有帮助的。

要构建内核模块,您需要用于构建内核的内核 headers 用于构建内核的确切版本,您希望为其构建模块。正如您希望在用户空间中 运行,您将不需要这些。

为用户空间定义内核 API 的 headers 主要在 /usr/include/linux/usr/include/asm 中(有关它们的生成方式,请参阅 this)。这些 headers 更重要的消费者之一是 C 标准库,例如 glibc,它必须针对这些 [=56= 的某些版本构建].由于 linux 内核 API 是向后兼容的,您可能有一个 glibc(或其他库实现)是针对这些 headers 的旧版本构建的,而不是您使用的内核 运行宁。我绝不是所有各种发行版如何分发 glibc 的专家,但我的印象是定义其用户空间 API 的内核 headers 通常是构建 glibc 的版本。

最后glibc通过headers定义了它的API也安装在/usr/include下比如/usr/include/sys。我不确切知道为使用较旧或较新的 glibc headers 构建的应用程序提供了向后或向前兼容性(如果有的话),但我猜测库 .so 版本号在向后可比性为坏了。

所以现在我们可以理解您的问题是 glibc headers 实际上没有为您尝试的 distros/versions 定义 MAP_UNINITIALIZED

然而,linux 内核 API 暴露了 MAP_UNINITIALIZED,如 this patch 所示。如果 glibc headers 没有为你定义它,你可以使用 linux 内核 API headers 和 #include <linux/mman.h> 如果它定义了它。请注意,您仍然需要 #include <sys/mman.h> 才能获得 mmap 的原型等。

如果你的linux内核APIheaders没有定义MAP_UNINITIALIZED但是你有实现它的内核版本,你可以自己定义它:

 #define MAP_UNINITIALIZED 0x4000000    

你不必担心你使用 "newer" headers 比构建 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)

它只是将您的标志直接传递给内核。