在linux内核中分配可交换内存

时间:2017-07-14 22:13:56

标签: linux-kernel

Linux内核中的内存通常是不可替换的(Do Kernel pages get swapped out?)。但是,有时允许换出内存很有用。是否可以在Linux内核中显式分配可交换内存?我想到的一种方法是创建用户空间进程并使用其内存。还有什么更好的吗?

2 个答案:

答案 0 :(得分:2)

您可以在内部shm共享内存文件系统中创建文件。

const char *name = "example";
loff_t size = PAGE_SIZE;
unsigned long flags = 0;
struct file *filp = shmem_file_setup(name, size, flags);
/* assert(!IS_ERR(filp)); */

文件实际上并未链接,因此名称不可见。标志可以包括VM_NORESERVE以预先跳过会计,而不是在分配页面时进行计费。现在您有一个shmem文件。您可以像这样映射页面:

struct address_space *mapping = filp->f_mapping;
pgoff_t index = 0;
struct page *p = shmem_read_mapping_page(mapping, index);
/* assert(!IS_ERR(filp)); */
void *data = page_to_virt(p);
memset(data, 0, PAGE_SIZE);

还有shmem_read_mapping_page_gfp(..., gfp_t)来指定页面的分配方式。完成后不要忘记把页面放回去。

put_page(p);

与文件同上。

fput(filp);

答案 1 :(得分:0)

问题的答案是简单的“否”或“是”,但对内核源代码进行了复杂的修改。

首先,要启用换出,您必须问自己,kswapd换出时发生了什么。本质上,它将遍历所有过程并确定是否可以换出其内存。而且所有这些内存的硬件模式都为ring3。因此,SMAP本质上禁止将其作为数据读取或作为程序在内核(ring 0)中执行:

https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention

并检查您的发行版“ CONFIG_X86_SMAP”,对于我的Ubuntu,默认情况下为“ y”,这在过去几年中一直存在。

但是,如果将内存保留为内核地址(0环),则可能需要考虑更改kswapd操作以触发内核地址换出。鞭打内核地址先走?如果地址是kswapd内核操作的一部分,该怎么办?涉及的复杂性很大。

接下来要考虑的是操作中的交换:尝试读取内存并且启用它的“不存在”位时,硬件异常将触发linux内核内存故障处理程序(即__do_page_fault())。

enter image description here

并查看__do_page_fault:

https://elixir.bootlin.com/linux/latest/source/arch/x86/mm/fault.c#L1477

以及如何处理内核地址(do_kern_address_fault()):

https://elixir.bootlin.com/linux/latest/source/arch/x86/mm/fault.c#L1174

实质上只是报告可能情况下的错误。如果要启用内核地址页面错误,则必须修改此路径。

还要注意,SMAP检查(在smap_violation内部)是在用户地址页面错误(do_usr_addr_fault())中完成的。