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)
它只是将您的标志直接传递给内核。
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)
它只是将您的标志直接传递给内核。