网站购物车作用,南海网站建设哪家好,泉州做网站的公司,国外ui设计网站在Linux系統中可以通過memblock來設置系統保留物理內存#xff0c;防止這些內存被內存管理系統分配出去。 作者#xff1a; 彭東林 郵箱#xff1a; pengdonglin137163.com 平臺 硬件平臺#xff1a; TQ2440 Linux版本#xff1a;Linux 3.14.45 說明 1. 在tq2440上#x… 在Linux系統中可以通過memblock來設置系統保留物理內存防止這些內存被內存管理系統分配出去。 作者 彭東林 郵箱 pengdonglin137163.com 平臺 硬件平臺 TQ2440 Linux版本Linux 3.14.45 說明 1. 在tq2440上物理內存的起始地址是0x30000000一共有64MB的內存所以物理內存地址範圍是: 0x30000000 - 0x33ffffff 2. 可以在uboot傳給kernel的參數bootargs中添加一個memblockdebug這樣在Linux啓動的時候會將設置memblock的信息打印出來 參考博文 Linux内核---41.arm 内存初始化 http://bbs.chinaunix.net/thread-4143403-1-1.html 代碼調用 在Linux啓動的時候會調用machine相關的代碼定製部分系統保留內存函數調用如下 start_kernel ---- setup_arch ---- arm_memblock_init ---- mdesc-reserve() 所以我們可以修改machine相關的代碼添加reserve函數的實現。 方法一 修改mach-tq2440.c如下 1 diff --git a/arch/arm/mach-s3c24xx/mach-tq2440.c b/arch/arm/mach-s3c24xx/mach-tq2440.c2 index f9679fb..da75db2 1006443 --- a/arch/arm/mach-s3c24xx/mach-tq2440.c4 b/arch/arm/mach-s3c24xx/mach-tq2440.c5 -23,6 23,7 6 #include linux/platform_device.h7 #include linux/io.h8 #include linux/dm9000.h9 #include linux/memblock.h
10
11 #include asm/mach/arch.h
12 #include asm/mach/map.h
13 -503,11 504,28 static void __init tq2440_machine_init(void)
14 s3c_pm_init();
15 }
16
17 static void __init tq2440_reserve(void) {
18 u32 paddr,size;
19
20 printk(%s enter.\n, __func__);
21
22 paddr 0x32000000;
23 size 0x200000;
24
25 if (memblock_reserve(paddr, size) 0) {
26 pr_err(failed to reserve DRAM - no memory\n);
27 return;
28 }
29
30 printk(reserve : reserve %dM mem\n, size20);
31 }
32
33 MACHINE_START(TQ2440, TQ2440)
34 /* Maintainer: Ben Dooks ben-linuxfluff.org */
35 .atag_offset 0x100,
36
37 .init_irq s3c2440_init_irq,
38 .reserve tq2440_reserve,
39 .map_io tq2440_map_io,
40 .init_machine tq2440_machine_init,
41 .init_time samsung_timer_init, 上面我們在0x32000000開始的地方保留了2MB的物理內存然後調用memblock_reserve告訴系統。這個在系統的啓動信息中可以看到 1 [ 0.000000] Machine: TQ24402 [ 0.000000] memblock_reserve: [0x00000030008200-0x0000003057fc03] flags 0x0 arm_memblock_init0x4c/0x1bc3 [ 0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init0x158/0x1bc4 [ 0.000000] tq2440_reserve enter.5 [ 0.000000] memblock_reserve: [0x00000032000000-0x000000321fffff] flags 0x0 tq2440_reserve0x1c/0x506 [ 0.000000] reserve : reserve 2M mem7 [ 0.000000] MEMBLOCK configuration:8 [ 0.000000] memory size 0x4000000 reserved size 0x77ba049 [ 0.000000] memory.cnt 0x1
10 [ 0.000000] memory[0x0] [0x00000030000000-0x00000033ffffff], 0x4000000 bytes flags: 0x0
11 [ 0.000000] reserved.cnt 0x3
12 [ 0.000000] reserved[0x0] [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0
13 [ 0.000000] reserved[0x1] [0x00000030008200-0x0000003057fc03], 0x577a04 bytes flags: 0x0
14 [ 0.000000] reserved[0x2] [0x00000032000000-0x000000321fffff], 0x200000 bytes flags: 0x0 上面的第5行和第14行就是我們自己設置的保留內存範圍信息。在Linux啓動後在debugfs中也可以看到memblock的信息 [rootTQ2440 /]# cat /sys/kernel/debug/memblock/memory 0: 0x30000000..0x33ffffff
[rootTQ2440 /]# cat /sys/kernel/debug/memblock/reserved 0: 0x30004000..0x30007fff1: 0x30008200..0x3057fc032: 0x32000000..0x321fffff3: 0x33f60000..0x33ffbfff4: 0x33ffc540..0x33ffc96b5: 0x33ffc980..0x33ffc9f76: 0x33ffca00..0x33ffca037: 0x33ffca20..0x33ffca238: 0x33ffca40..0x33ffca439: 0x33ffca60..0x33ffca6310: 0x33ffca80..0x33ffcad211: 0x33ffcae0..0x33ffcb3212: 0x33ffcb40..0x33ffcb9213: 0x33ffcba0..0x33ffcbbb14: 0x33ffcbc0..0x33ffcdc715: 0x33ffcdd0..0x33ffffff 其中memory節點中存放的是可用的物理內存地址範圍reserved表示已經分配出去的物理地址第2行記錄的就是我們設置的。 既然添加了保留物理內存那麼如何使用呢下面我寫了一個簡單的內核模塊使用我們添加的保留物理內存下面是內核模塊的代碼 1 #include linux/module.h2 3 #define RESERVE_PHY 0x320000004 #define RESERVE_SIZE 0x2000005 6 static char str[] pengdonglin137163.com\n;7 8 static __init int reserve_demo_init(void)9 {
10 memcpy(phys_to_virt(RESERVE_PHY), str, sizeof(str));
11
12 printk(%s: virt: %p\n, __func__, phys_to_virt(RESERVE_PHY));
13
14 return 0;
15 }
16
17 static __exit void reserve_demo_exit(void)
18 {
19 printk(%s: %s\n, __func__, (char *)phys_to_virt(RESERVE_PHY));
20 }
21
22 module_init(reserve_demo_init);
23 module_exit(reserve_demo_exit);
24 MODULE_LICENSE(GPL); 可以看到我們直接調用函數phys_to_virt將物理地址轉換成虛擬地址然後直接向這個虛擬地址中寫入數據在模塊卸載時再將內容打印出出來。 1 [rootTQ2440 /]# insmod nfs/demo.ko
2 [ 1417.153362] reserve_demo_init: virt: c2000000
3 [rootTQ2440 /]#
4 [rootTQ2440 /]# rmmod demo
5 [ 1420.986938] reserve_demo_exit: pengdonglin137163.com
6 [ 1420.986938] 可以看到第2行中得到物理地址0x32000000對應的虛擬地址是0xC2000000。在模塊卸載時打印出了我們之前寫入的內容。 這種方法使用與物理內存在Normal區域的情況。 方法二 修改mach-tq2440.c 1 diff --git a/arch/arm/mach-s3c24xx/mach-tq2440.c b/arch/arm/mach-s3c24xx/mach-tq2440.c2 index f9679fb..345a868 1006443 --- a/arch/arm/mach-s3c24xx/mach-tq2440.c4 b/arch/arm/mach-s3c24xx/mach-tq2440.c5 -23,6 23,7 6 #include linux/platform_device.h7 #include linux/io.h8 #include linux/dm9000.h9 #include linux/memblock.h
10
11 #include asm/mach/arch.h
12 #include asm/mach/map.h
13 -503,11 504,31 static void __init tq2440_machine_init(void)
14 s3c_pm_init();
15 }
16
17 static void __init tq2440_reserve(void) {
18 u32 paddr,size;
19
20 printk(%s enter.\n, __func__);
21
22 paddr 0x32000000;
23 size 0x200000;
24
25 if (memblock_reserve(paddr, size) 0) {
26 pr_err(failed to reserve DRAM - no memory\n);
27 return;
28 }
29
30 memblock_free(paddr, size);
31 memblock_remove(paddr, size);
32
33 printk(reserve : reserve %dM mem\n, size20);
34 }
35
36 MACHINE_START(TQ2440, TQ2440)
37 /* Maintainer: Ben Dooks ben-linuxfluff.org */
38 .atag_offset 0x100,
39
40 .init_irq s3c2440_init_irq,
41 .reserve tq2440_reserve,
42 .map_io tq2440_map_io,
43 .init_machine tq2440_machine_init,
44 .init_time samsung_timer_init, 用新kernel啓動在啓動信息中可以看到 1 [ 0.000000] Machine: TQ24402 [ 0.000000] memblock_reserve: [0x00000030008200-0x0000003057fc03] flags 0x0 arm_memblock_init0x4c/0x1bc3 [ 0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init0x158/0x1bc4 [ 0.000000] tq2440_reserve enter.5 [ 0.000000] memblock_reserve: [0x00000032000000-0x000000321fffff] flags 0x0 tq2440_reserve0x1c/0x686 [ 0.000000] memblock_free: [0x00000032000000-0x000000321fffff] tq2440_reserve0x3c/0x687 [ 0.000000] reserve : reserve 2M mem8 [ 0.000000] MEMBLOCK configuration:9 [ 0.000000] memory size 0x3e00000 reserved size 0x57ba04
10 [ 0.000000] memory.cnt 0x2
11 [ 0.000000] memory[0x0] [0x00000030000000-0x00000031ffffff], 0x2000000 bytes flags: 0x0
12 [ 0.000000] memory[0x1] [0x00000032200000-0x00000033ffffff], 0x1e00000 bytes flags: 0x0
13 [ 0.000000] reserved.cnt 0x2
14 [ 0.000000] reserved[0x0] [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0
15 [ 0.000000] reserved[0x1] [0x00000030008200-0x0000003057fc03], 0x577a04 bytes flags: 0x0 在kernel啓動後在memory和reserved節點中 [rootTQ2440 /]# cat /sys/kernel/debug/memblock/memory 0: 0x30000000..0x31ffffff1: 0x32200000..0x33ffffff 可以看到此時系統中有兩塊物理內存但是這兩塊物理內存的地址之間不連續中間有一個大小爲2MB的“洞”。此時在reserved節點看不到這部分內存。 [rootTQ2440 /]# cat /sys/kernel/debug/memblock/reserved 0: 0x30004000..0x30007fff1: 0x30008200..0x3057fc032: 0x33f60000..0x33ffbfff3: 0x33ffc520..0x33ffc94b4: 0x33ffc960..0x33ffc9d75: 0x33ffc9e0..0x33ffc9e36: 0x33ffca00..0x33ffca037: 0x33ffca20..0x33ffca238: 0x33ffca40..0x33ffca439: 0x33ffca60..0x33ffcab210: 0x33ffcac0..0x33ffcb1211: 0x33ffcb20..0x33ffcb7212: 0x33ffcb80..0x33ffcb9b13: 0x33ffcba0..0x33ffcbbb14: 0x33ffcbc0..0x33ffcdc715: 0x33ffcdd0..0x33ffffff 此時在使用這部分保留內存時就不能直接使用了需要申請然後映射後才能使用如下 1 #include linux/module.h2 #include linux/ioport.h3 #include linux/io.h4 5 #define RESERVE_PHY 0x320000006 #define RESERVE_SIZE 0x2000007 8 static char str[] pengdonglin137163.com\n;9 static void __iomem *addr;
10
11 static __init int reserve_demo_init(void)
12 {
13
14 if (!request_mem_region(RESERVE_PHY, RESERVE_SIZE, my reserve))
15 return -EBUSY;
16
17 addr ioremap_nocache(RESERVE_PHY, RESERVE_SIZE);
18 memcpy(addr, str, sizeof(str));
19
20 printk(%s: virt: %p\n, __func__, addr);
21
22 return 0;
23 }
24
25 static __exit void reserve_demo_exit(void)
26 {
27 printk(%s: %s\n, __func__, (char *)addr);
28
29 iounmap(addr);
30 release_mem_region(RESERVE_PHY, RESERVE_SIZE);
31 }
32
33 module_init(reserve_demo_init);
34 module_exit(reserve_demo_exit);
35 MODULE_LICENSE(GPL); 然後加載這個模塊此時會向addr中寫入字符串在卸載時再打印出來。log如下 1 [rootTQ2440 /]# insmod nfs/demo.ko
2 [ 43.853848] reserve_demo_init: virt: c5000000
3 [rootTQ2440 /]#
4 [rootTQ2440 /]# rmmod demo
5 [ 49.247204] reserve_demo_exit: pengdonglin137163.com
6 [ 49.247204]
7 [rootTQ2440 /]# 方法三 在uboot可以通過在bootargs中設置mem參數告訴kernel可用的物理內存。 修改uboot傳給kernel的bootargs如下 setenv bootargs memblockdebug noinitrd root/dev/mtdblock2 init/linuxrc consolettySAC0,115200n8 mem32M 此時啓動Linux啓動信息中可以看到 [ 0.000000] memblock_reserve: [0x00000030008200-0x00000030589c83] flags 0x0 arm_memblock_init0x5c/0x1d8
[ 0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init0x8c/0x1d8
[ 0.000000] MEMBLOCK configuration:
[ 0.000000] memory size 0x2000000 reserved size 0x585a84
[ 0.000000] memory.cnt 0x1
[ 0.000000] memory[0x0] [0x00000030000000-0x00000031ffffff], 0x2000000 bytes flags: 0x0
[ 0.000000] reserved.cnt 0x2
[ 0.000000] reserved[0x0] [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0
[ 0.000000] reserved[0x1] [0x00000030008200-0x00000030589c83], 0x581a84 bytes flags: 0x0
... ...
[ 0.000000] Memory: 26752K/32768K available (3912K kernel code, 214K rwdata, 1176K rodata, 155K init, 176K bss, 6016K reserved) 可以看到此時Linux只知道有32MB的物理內存而實際上板子上有64MB的物理內存。 可以看到memory和reserved節點的內容如下 1 [rootTQ2440 /]# cat /d/memblock/memory 2 0: 0x30000000..0x31ffffff3 [rootTQ2440 /]# 4 [rootTQ2440 /]# cat /d/memblock/reserved 5 0: 0x30004000..0x30007fff6 1: 0x30008200..0x30589c837 2: 0x31fa6000..0x31ffbfff8 3: 0x31ffc840..0x31ffca6b9 4: 0x31ffca80..0x31ffcaf7
10 5: 0x31ffcb00..0x31ffcb03
11 6: 0x31ffcb20..0x31ffcb23
12 7: 0x31ffcb40..0x31ffcb43
13 8: 0x31ffcb60..0x31ffcb63
14 9: 0x31ffcb80..0x31ffcbda
15 10: 0x31ffcbe0..0x31ffcc3a
16 11: 0x31ffcc40..0x31ffcc9a
17 12: 0x31ffcca0..0x31ffccbb
18 13: 0x31ffccc0..0x31ffcdc3
19 14: 0x31ffcdd0..0x31ffffff 使用剩餘的物理內存同樣需要先申請再映射然後再使用 1 #include linux/module.h2 #include linux/ioport.h3 #include linux/io.h4 5 #define RESERVE_PHY 0x320000006 #define RESERVE_SIZE 0x2000007 8 static char str[] pengdonglin137163.com\n;9 static void __iomem *addr;
10
11 static __init int reserve_demo_init(void)
12 {
13
14 if (!request_mem_region(RESERVE_PHY, RESERVE_SIZE, my reserve))
15 return -EBUSY;
16
17 addr ioremap_nocache(RESERVE_PHY, RESERVE_SIZE);
18 memcpy(addr, str, sizeof(str));
19
20 printk(%s: virt: %p\n, __func__, addr);
21
22 return 0;
23 }
24
25 static __exit void reserve_demo_exit(void)
26 {
27 printk(%s: %s\n, __func__, (char *)addr);
28
29 iounmap(addr);
30 release_mem_region(RESERVE_PHY, RESERVE_SIZE);
31 }
32
33 module_init(reserve_demo_init);
34 module_exit(reserve_demo_exit);
35 MODULE_LICENSE(GPL); 加載模塊然後卸載可以看到log 1 rootTQ2440 /]# insmod /nfs/demo.ko
2 [ 266.998897] reserve_demo_init: virt: c3000000
3 [rootTQ2440 /]#
4 [rootTQ2440 /]# rmmod demo
5 [ 271.735731] reserve_demo_exit: pengdonglin137163.com
6 [ 271.735731] 完 转载于:https://www.cnblogs.com/pengdonglin137/p/5837115.html