c - 为什么我的模块无法处理内核分页请求?

标签 c memory-management linux-kernel kernel-module virtual-memory

这是我使用 dequeue_huge_page_vma() 和 alloc_buddy_huge_page() 分配一个大页面的模块。为了使它们独立于 vma,我从 __get_vm_area_node() 获取可用的 vm 区域,然后获取其虚拟地址。我想分配一个 2MB 的页面,但是内核说:

[   84.944634] BUG: unable to handle kernel paging request at ffffc90013d02000
[   84.944641] IP: [<ffffffffa0ac9063>] vma_null_test+0x63/0xa3 [vma_null_test]
[   84.944650] PGD bd019067 PUD bd01a067 PMD b35c0067 PTE 0
[   84.944657] Oops: 0000 [#1] SMP 

我的代码:

/*
 * vma_null_test.c - Cindy: to test if vma can be set to NULL in alloc_huge_page() 
 */

 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/hugetlb.h>
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <asm/page.h>
 #include <linux/nodemask.h>
 #include <linux/gfp.h>
 #include <linux/mm_types.h>
 #include <asm-generic/pgtable.h>
 #include <linux/err.h>
 #include <linux/vmalloc.h>
 #define TWO_MB 0x200000

struct hstate *h;

struct vm_struct *__get_vm_area_node(unsigned long size,
            unsigned long align, unsigned long flags, unsigned long start,
            unsigned long end, int node, gfp_t gfp_mask, void *caller);

struct page *dequeue_huge_page_vma(struct hstate *,struct vm_area_struct *,
            unsigned long, int);

struct page *alloc_buddy_huge_page(struct hstate *,struct vm_area_struct *,
                            unsigned long);

struct page *alloc_huge_page_node_mod(unsigned long vaddr)
{
struct page *page;

page = dequeue_huge_page_vma(h, NULL, vaddr, 0);

if (!page)
    page = alloc_buddy_huge_page(h, NULL, vaddr);

return page;
}

static int __init vma_null_test(void)
{
  struct vm_struct *area;
  h=&default_hstate;
  unsigned long *address;
  struct page *page;
  int ret;

  area=__get_vm_area_node(TWO_MB, 1, VM_ALLOC, VMALLOC_START, VMALLOC_END, -1,   GFP_KERNEL|__GFP_HIGHMEM, __builtin_return_address(0));
  address=(unsigned long *)area->addr;
  page=alloc_huge_page_node_mod(*address);
  if(IS_ERR(page)){
  ret=-PTR_ERR(page);
  printk(KERN_ERR "Cannot allocate page\n");

  }
  else{
  ret=0;
  printk(KERN_ERR "Allocate one huge page at virtual address:%x\n",*address);
  }

  return ret;
}

static void __exit vma_null_exit(void)
{
  printk(KERN_ERR ".............Exit..........\n");
}

module_init(vma_null_test);
module_exit(vma_null_exit);
MODULE_LICENSE("GPL");

最佳答案

这是一个非常老的问题,但到底是什么......

__get_vm_area_node() 可能由于多种原因返回 NULL,您无条件地遵循其返回值。这是不明智的。

关于c - 为什么我的模块无法处理内核分页请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8238065/

相关文章:

java - java 为什么要等这么久才能运行垃圾收集器?

linux-kernel - Linux内核崩溃报告中 "(OF)"或 "(OF+)"的含义

linux - Linux 内核中实现 open ("/proc/self/fd/NUM"的代码在哪里?

c++ - 在 Visual Studio 2012 中调试 C DLL 文件时无法单步执行代码

c - 如何避免定时器堆栈

c - 多线程处理来自同一文件的数据

python - 在不同机器上分配大 ndarray 时出现 MemoryError 与 "ValueError: array is too big"

c++ - C语言程序被检测为病毒

c++ - 为什么C++可以使用未初始化的成员变量(引用或指针*NOT value copy*)来初始化其父类的成员变量

linux - linux 内核中的 kmalloc() 功能