使用 mmzone.h 函数构建内核模块

问题描述

我正在尝试制作一个内核模块,该模块为我提供有关内存的一些基本信息,例如节点、区域、页面等。我无法构建该模块,存在一些错误。我正在使用 Ubuntu 20.04内核 5.8.0-55-generic。

代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/mmzone.h>

static int __init hello_entry(void){

    pg_data_t* pgdat;

    for_each_online_pgdat(pgdat){

        printk("KERN_ALERT" "Number of Zones: %d\n",pgdat->nr_zones);

    }

    printk("KERN_ALERT" "Hello World Entry!\n");
    return 0;
} 

static void __exit hello_exit(void){
    printk("KERN_ALERT" "Hello World Exit!\n");
}

module_init(hello_entry);
module_exit(hello_exit);

制作文件输出

root@madhur-VivoBook:/media/madhur/CommonSpace/Work/Linux/KernelModule# make
make -C /lib/modules/5.8.0-55-generic/build M=/media/madhur/CommonSpace/Work/Linux/KernelModule modules
make[1]: Entering directory '/usr/src/linux-headers-5.8.0-55-generic'
  MODPOST /media/madhur/CommonSpace/Work/Linux/KernelModule/Module.symvers
WARNING: modpost: missing MODULE_LICENSE() in /media/madhur/CommonSpace/Work/Linux/KernelModule/hello.o
ERROR: modpost: "next_online_pgdat" [/media/madhur/CommonSpace/Work/Linux/KernelModule/hello.ko] undefined!
ERROR: modpost: "first_online_pgdat" [/media/madhur/CommonSpace/Work/Linux/KernelModule/hello.ko] undefined!
make[2]: *** [scripts/Makefile.modpost:111: /media/madhur/CommonSpace/Work/Linux/KernelModule/Module.symvers] Error 1
make[2]: *** Deleting file '/media/madhur/CommonSpace/Work/Linux/KernelModule/Module.symvers'
make[1]: *** [Makefile:1698: modules] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.8.0-55-generic'
make: *** [Makefile:5: all] Error 2

next_online_pgdat 和 first_online_pgdat 已在 mmzone.h 文件中定义,但有一条消息表明它们未定义。

我是第一次尝试编写一个模块,所以如果有人可以为 Linux 内核模块编程推荐一些资源,特别是内存管理,那将会非常有帮助。我实际上想分配和访问物理内存页面并用它们做一些事情。

更新: 感谢@Tsyvarev。现在我的代码看起来像这样:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/mmzone.h>
#include <asm/cacheflush.h>

static int __init hello_entry(void){
    printk(KERN_ALERT "Hello World Entry!\n");

    printk(KERN_ALERT "Page Size: %ld\n",PAGE_SIZE);
    printk(KERN_ALERT "Cache Line Size: %ld\n",cache_line_size());

    int i;

    int number_of_pages = 3;

    int* pages = (int *)alloc_pages_exact(number_of_pages * PAGE_SIZE,__GFP_DMA);

    int *prev_page,*rowhammer_page,*next_page;

    prev_page = pages;
    rowhammer_page = prev_page + PAGE_SIZE;
    next_page = rowhammer_page + PAGE_SIZE;


    for(i = 0; i < PAGE_SIZE / sizeof(int); i++){
        prev_page[i] = i;
        rowhammer_page[i] = i;
        next_page[i] = i;
    }


    clflush_cache_range(rowhammer_page,PAGE_SIZE);//Flush rowhammer_page from cache(Will this flush from all cache?)
        
    int read_midvalue = rowhammer_page[PAGE_SIZE / (sizeof(int) * 2)]; //Reading the middle value present in the page
    
    if(read_midvalue != PAGE_SIZE / (sizeof(int) * 2)){
        printk(KERN_ALERT "Rowhammer Fault on access number %d\n",i);
    }



    return 0;
} 

static void __exit hello_exit(void){
    printk(KERN_ALERT "Hello World Exit!\n");
}

module_init(hello_entry);
module_exit(hello_exit);

这编译得很好,但是当我执行 insmod hello.ko 时,日志显示 clflush_cache_range一个未知符号。 这是日志:

[ 1246.489806] hello: loading out-of-tree module taints kernel.
[ 1246.489812] hello: module license 'unspecified' taints kernel.
[ 1246.489814] disabling lock debugging due to kernel taint
[ 1246.489903] hello: module verification Failed: signature and/or required key missing - tainting kernel
[ 1246.490039] hello: UnkNown symbol clflush_cache_range (err -2)

我使用的是 x86 机器。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)