发新话题
打印

内存空间探测

内存空间探测

让参与Linux内核毕业设计的学生写一个内核模块,能够对Linux启动以后的内存分布情况进行探测,用到内核数据结构E820
例如,能够显示如下信息:
BIOS-e820: 0000000000000000 - 000000000009fc00 (usable)
BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved)
BIOS-e820: 00000000000e0000 - 0000000000100000 (reserved)
BIOS-e820: 0000000000100000 - 000000001f7d0000 (usable)

BIOS-e820: 000000001f7d0000 - 000000001f7e5600 (reserved)
BIOS-e820: 000000001f7e5600 - 000000001f7f8000 (ACPI NVS)
BIOS-e820: 000000001f7f8000 - 000000001f800000 (reserved)
BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved)
BIOS-e820: 00000000fed20000 - 00000000fed9b000 (reserved)
BIOS-e820: 00000000feda0000 - 00000000fedc0000 (reserved)
BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved)
BIOS-e820: 00000000ffb00000 - 00000000ffc00000 (reserved)
BIOS-e820: 00000000fff00000 - 0000000100000000 (reserved)

很快,木天的程序写出来了,但还不完善:

E820.c中的void __init print_memory_map(char *who)改写成了f();
手工从/proc/kallsyms中查出e820的地址


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/e820.h>


struct e820map e820;
void __init f()
{
        int i;
        for (i = 0; i < e820.nr_map; i++) {
                printk("BIOS-e820: %016Lx - %016Lx ",
                e820.map.addr,
                e820.map.addr + e820.map.size);
                switch (e820.map.type) {
                        case E820_RAM: printk("(usable)\n");
                        break;
                        case E820_RESERVED:
                        printk("(reserved)\n");
                        break;
                        case E820_ACPI:
                        printk("(ACPI data)\n");
                        break;
                        case E820_NVS:
                        printk("(ACPI NVS)\n");
                        break;
                        default: printk("type %u\n", e820.map.type);
                        break;
                }
        }


}


static int __init m1_init(void)
{
        e820=*(struct e820map *)(0xc04411e0);
        f();
        return 0;


}


static void __exit m1_cleanup(void)
{
        printk("<1>Goodbye!\n");


}


module_init(m1_init);
module_exit(m1_cleanup);



以下是他机器上运行的结果(1G RAM):


[49987.576000] BIOS-e820: 0000000000000000 - 000000000009fc00 (usable)
[49987.576000] BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved)
[49987.576000] BIOS-e820: 00000000000e4000 - 0000000000100000 (reserved)
[49987.576000] BIOS-e820: 0000000000100000 - 000000003ffb0000 (usable)
[49987.576000] BIOS-e820: 000000003ffb0000 - 000000003ffbe000 (ACPI
data)
[49987.576000] BIOS-e820: 000000003ffbe000 - 000000003ffe0000 (ACPI NVS)
[49987.576000] BIOS-e820: 000000003ffe0000 - 000000003ffee000 (reserved)
[49987.576000] BIOS-e820: 000000003fff0000 - 0000000040000000 (reserved)
[49987.576000] BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved)
[49987.576000] BIOS-e820: 00000000fee00000 - 00000000fef00000 (reserved)
[49987.576000] BIOS-e820: 00000000fff00000 - 0000000100000000 (reserved)


此程序有什么改进之处?
透析真谛,似拨云穿雾;共享智慧,如春风沐浴
http://www.kerneltravel.net
其实在内核中就有这样的写法,在arch/i386/kernel/E820.c中的void __init print_memory_map(char *who)就是干这个的
void __init print_memory_map(char *who)
{
        int i;

        for (i = 0; i < e820.nr_map; i++) {
                printk(" %s: %016Lx - %016Lx ", who,
                        e820.map.addr,
                        e820.map.addr + e820.map.size);
                switch (e820.map.type) {
                case E820_RAM:        printk("(usable)\n");
                                break;
                case E820_RESERVED:
                                printk("(reserved)\n");
                                break;
                case E820_ACPI:
                                printk("(ACPI data)\n");
                                break;
                case E820_NVS:
                                printk("(ACPI NVS)\n");
                                break;
                default:        printk("type %u\n", e820.map.type);
                                break;
                }
        }
}
发新话题