为了了解该怎么办#include <sys/mman.h>
没有定义MAP_UNINITIALIZED
,这有助于理解如何定义内核接口。
要构建内核模块,您将需要用于构建内核的内核头文件,以适应您希望为其构建模块的确切内核版本。由于您希望在用户空间中运行,因此不需要这些。
为用户空间定义内核 API 的头文件主要位于/usr/include/linux
and /usr/include/asm
(see this https://www.kernel.org/doc/Documentation/kbuild/headers_install.txt了解它们是如何生成的)。这些头文件的更重要的使用者之一是 C 标准库,e.g., glibc
,它必须针对这些标头的某些版本构建。由于 Linux 内核 API 是向后兼容的,因此您可能有一个 glibc(或其他库实现)是针对这些标头的旧版本(而不是您正在运行的内核)构建的。我绝不是各种发行版如何分发 glibc 的专家,但我的印象是,定义其用户空间 API 的内核头文件通常是 glibc 构建的版本。
最后,glibc 通过同样安装在下面的标头定义了它的 API/usr/include
例如/usr/include/sys
。我不知道为使用较旧或较新的 glibc 标头构建的应用程序提供了哪些向后或向前兼容性(如果有),但我猜测当向后可比性被破坏时,库 .so 版本号会受到影响。
所以现在我们可以理解你的问题是 glibc 头实际上并没有定义MAP_UNINITIALIZED
对于您尝试过的发行版/版本。
然而,linux内核API已经暴露了MAP_UNINITIALIZED
, as 这个补丁 https://patchwork.kernel.org/patch/7149071/演示。如果 glibc 头文件没有为您定义它,您可以使用 linux 内核 API 头文件并#include <linux/mman.h>
如果这定义了它。请注意,您仍然需要#include <sys/mman.h>
除其他外,为了获得 mmap 的原型。
如果你的Linux内核API头没有定义MAP_UNINITIALIZED
但你有一个实现它的内核版本,你可以自己定义它:
#define MAP_UNINITIALIZED 0x4000000
您不必担心您正在有效地使用比构建 glibc 时使用的“更新”标头,因为 glibc 实现mmap
很薄:
#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)
它只是将您的标志直接传递到内核。