【发布时间】:2021-02-17 19:50:20
【问题描述】:
我想看看Linux内核函数mmap()是如何实现的,所以我从GNU page下载了GNU C库(glibc)源码。 (我下载了glibc-2.27 因为ldd --version 告诉我我正在使用GLIBC 2.27)
现在要找到mmap() 的定义,我做了grep -r "mmap(void" *,它什么也没返回,所以我尝试了grep -r "mmap (void" *,它返回了以下内容:
conform/data/sys/mman.h-data:function {void*} mmap (void*, size_t, int, int, int, off_t)
include/sys/mman.h:extern void *__mmap (void *__addr, size_t __len, int __prot,
malloc/memusage.c:mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset)
manual/llio.texi:@deftypefun {void *} mmap (void *@var{address}, size_t @var{length}, int @var{protect}, int @var{flags}, int @var{filedes}, off_t @var{offset})
misc/sys/mman.h:extern void *mmap (void *__addr, size_t __len, int __prot,
misc/mmap.c:__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
support/xunistd.h:void *xmmap (void *addr, size_t length, int prot, int flags, int fd);
support/xmmap.c:xmmap (void *addr, size_t length, int prot, int flags, int fd)
sysdeps/unix/sysv/linux/mmap.c:__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
sysdeps/mach/hurd/dl-sysdep.c:__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
sysdeps/mach/hurd/mmap.c:__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
在所有关于mmap() 而不是__mmap() 的结果中,我发现mmap() 的定义在malloc/memusage.c 中,它定义mmap() 如下:
/* `mmap' replacement. We do not have to keep track of the size since
`munmap' will get it as a parameter. */
void *
mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset)
{
void *result = NULL;
/* Determine real implementation if not already happened. */
if (__glibc_unlikely (initialized <= 0))
{
if (initialized == -1)
return NULL;
me ();
}
/* Always get a block. We don't need extra memory. */
result = (*mmapp)(start, len, prot, flags, fd, offset);
...
/* Return the pointer to the user buffer. */
return result;
}
我认为result = (*mmapp)(start, len, prot, flags, fd, offset); 才是最重要的,在这个文件中还有另外两个部分处理这个mmapp 函数指针,它们是:
- 声明:
static void *(*mmapp) (void *, size_t, int, int, int, off_t); - 在一些名为
me()的函数中初始化:mmapp = (void *(*)(void *, size_t, int, int, int, off_t))dlsym (RTLD_NEXT, "mmap");
根据the manual,dlsym()函数采用 dlopen() 返回的动态库的“句柄”和以 null 结尾的符号名称,返回该符号加载到内存中的地址。
因此,整个过程可以总结如下:
-
mmap()调用指针mmapp指向的函数 -
mmapp设置为指向加载到内存中的动态库中的符号"mmap"
但我找不到任何关于带有符号"mmap" 的动态库的信息。
我在代码分析过程中做错了吗?我在代码分析方面没有太多经验,更不用说研究系统调用函数或内核代码了,所以任何建议或朝着正确的方向推进都将不胜感激。
提前致谢!
【问题讨论】:
-
这些对你来说都不是很有趣,因为在底部,你将在库中看到的只是一个系统调用。这里真正的动作都在内核中。参见例如github.com/torvalds/linux/blob/master/mm/mmap.c。但是您可能更愿意查看一些较旧的或“玩具”操作系统,其中代码可能更简单且更具可读性。
-
@NateEldredge 嘿,我认为这实际上可能很有帮助。但我想你可以从我的问题中看出我对 Linux 内核的东西不是很熟悉 - 我想问一下,在 mmap 的手册中它说我们需要包含
但没有名为的目录git 中的 sys (有 linux/include/linux/mman.h 但它没有 mmap 定义或声明)......我在这里误解了什么吗? -
这个故事太长了,无法评论。问一个单独的问题。
标签: linux linux-kernel operating-system system-calls mmap