如何为我的 64 位 linux 内核找到 task_size?

How can I find the task_size for my 64-bit linux kernel?

我想知道有多少space留给内核,多少留给用户进程

0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
hole caused by [48:63] sign extension
ffff800000000000 - ffff87ffffffffff (=43 bits) guard hole, reserved for hypervisor
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
... unused hole ...
ffffec0000000000 - fffffc0000000000 (=44 bits) kasan shadow memory (16TB)
... unused hole ...
ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks
... unused hole ...
ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space
ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls
ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole

直接映射覆盖系统中的所有内存,最高可达 内存地址(这意味着在某些情况下它还可以包括 PCI 内存 洞)。

vmalloc space懒同步到不同的PML4页面 使用页面错误处理程序的进程,其中 init_level4_pgt 作为 参考。

当前的 X86-64 实现仅支持 40 位地址 space, 但我们最多支持 46 位。这在页表中扩展为 MBZ space。

所以,简而言之,用户 space 获得 247 字节 = 128TiB,内核获得 512MiB。地址的其余部分 space 与一些无法使用的漏洞一起进入系统的各个部分。

您还可以在此处阅读有关 64 位系统的信息。 x86_64 Canonical address space

TASK_SIZE定义在https://elixir.bootlin.com/linux/v4.16.7/source/arch/arm/include/asm/memory.h#L40中,可以通过以下代码访问。请将其编译为内核模块。


TASK_SIZE.c

#include <linux/module.h>
#include <linux/memory.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Open Source");
MODULE_DESCRIPTION("Module for TASK_SIZE");

static int __init find_task_size_init(void);
static void __exit find_task_size_exit(void);

static int
__init find_task_size_init(void)
{
    printk(KERN_INFO "Memory TASK_SIZE: 0x%lx\n", TASK_SIZE);
    return 0;
}

static void
__exit find_task_size_exit(void)
{
    printk(KERN_INFO "module exits ok !\n");
}

module_init(find_task_size_init);
module_exit(find_task_size_exit);

生成文件

ifneq ($(KERNELRELEASE),)
    # call from kernel build system
    lifo-objs := main.o
    obj-m     := TASK_SIZE.o
else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD       := $(shell pwd)
modules:
    echo $(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules
    $(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules
endif

clean:  
    rm -rf *.o *~ core .depend *.mod.o .*.cmd *.ko *.mod.c .tmp_versions *.markers *.symvers modules.order

depend .depend dep:
    $(CC) $(CFLAGS) -M *.c > .depend

ifeq (.depend,$(wildcard .depend))
    include .depend
endif

# dmesg -k -w          # In the first console shell

[ 2570.156990] Memory TASK_SIZE: 0x7ffffffff000
[ 2573.164671] module exits ok !

# make                 # In the second console shell
# insmod TASK_SIZE.ko
# rmmod TASK_SIZE