<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->
~ $ cat test
#rmmod mem.ko
insmod mem.ko usBufferNum=18
mknod /dev/fmem c 10 205
chmod 777 tstmem
./tstmem alloc
Mem: 91192K used, 36028K free , 0K shrd, 0K buff, 30600K cached
Load average: 0.00, 0.01, 0.00 (State: S=sleeping R=running, W=waiting)
CPU states: 0.2% user, 0.6% system, 0.0% nice, 99.2% idle
PID USER STATUS RSS PPID %CPU %MEM COMMAND
127 root R 432 113 0.5 0.3 exe
115 root S 580 1 0.0 0.4 mini_httpd
113 root S 508 18 0.0 0.3 sh
114 root S 436 1 0.0 0.3 bftpd
52 root S 364 1 0.0 0.2 sd_hotplug
18 root S 344 1 0.0 0.2 linuxrc
66 root S 328 1 0.0 0.2 sys_monitor
1 root S 324 0 0.0 0.2 init
95 root S 280 1 0.0 0.2 easycam
108 root S 68 1 0.0 0.0 telnetd
32 root SWN 0 1 0.0 0.0 jffs2_gcd_mtd1
2 root SWN 0 1 0.0 0.0 ksoftirqd/0
3 root SW< 0 1 0.0 0.0 events/0
4 root SW< 0 1 0.0 0.0 khelper
5 root SW< 0 1 0.0 0.0 kthread
6 root SW< 0 5 0.0 0.0 kblockd/0
7 root SW 0 5 0.0 0.0 pdflush
8 root SW 0 5 0.0 0.0 pdflush
9 root SW 0 1 0.0 0.0 kswapd0
10 root SW< 0 5 0.0 0.0 aio/0
task(tstmem): c0806000 regs: c0807fb0 pgd=0xc081c000
pc : [<c0d95440>]
sp : c0807ce0 ip : 000f4209 fp : c0807d18
[0xc0807d20]<=
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c081c000
[00000000] *pgd=00fa3031, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#1]
Modules linked in: mem pinmux cifs usbhid usb_storage fotg2xx_drv usbcore timer2 isl1208drv gpio fmjpeg_drv fmpeg4_drv fmcp422_drv favc_drv favc_common fcap100_mt9m131 fcap1 fcap0 fcap_common snd_fi2s_wm8731_c1 snd_ftssp010 ftsdc010 ftmac100 cpe_wdt ct656 fi2c apb_dma
CPU: 0
PC is at __alloc_pages+0x448/0x524
LR is at vprintk+0x324/0x368
pc : [<c0bdd598>] lr : [<c0bb9c18>] Tainted: P
sp : c0807e1c ip : c0807d8c fp : c0807ef4
r10: c0dd9cfc r9 : c0854340 r8 : c0dd9cbc
r7 : 0000000a r6 : 000400d2 r5 : c0dd6bb0 r4 : c0dd6bb0
r3 : 00000000 r2 : 00000001 r1 : 00000004 r0 : 000002e9
Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment user
Control: 397F Table: 0081C000 DAC: 00000015
Process tstmem (pid: 126, stack limit = 0xc0806194)
Stack: (0xc0807e1c to 0xc0808000)
7e00: 00000000
7e20: 00000000 00000000 00000002 00000010 00000000 00000000 00000000 00000000
7e40: 00000022 000000b6 00000207 00000000 00000000 00000000 00000000 00001d00
7e60: 00000000 00006c81 0000acec 00003e2f 00002f2d 00003097 00000000 00000000
7e80: 00000000 00003536 00000000 00000000 0000000b 00000000 00000000 000027b4
7ea0: 00000000 00000000 000022ad 00000000 00000000 00000001 00000000 00000002
7ec0: 00000001 00000000 00000000 00000012 00280000 0027ffff 00000000 000000e3
7ee0: 00000000 bf125cc0 c0807f20 c0807ef8 c0bac238 c0bdd160 00000012 bf125cc0
7f 00: bf125800 00000000 c0ba1b84 c0806000 40133000 c0807f3c c0807f24 bf12508c
7f 20: c0bac1f8 c593c940 ffffffe7 c004e401 c0807f5c c0807f40 c0c0c420 bf125038
7f 40: c593c940 00000000 00000003 00000000 c0807f84 c0807f60 c0c0c728 c0c0c3b0
7f 60: 00000000 40133000 c593c940 fffffff7 c004e401 00000036 c0807fa4 c0807f88
7f 80: c0c0c788 c0c0c444 00000000 be98fee4 00008614 00008660 00000000 c0807fa8
7fa0: c0ba1a00 c0c0c758 be98fee4 c0ba9150 00000003 c004e401 00000000 00000000
7fc0: be98fee4 00008614 00008660 00000002 000084c0 00000000 40133000 be98feb8
7fe0: 400d1480 be98fe8c 00008590 400d1484 60000010 00000003 0001c8b4 00000102
Backtrace:
[<c0bdd150>] (__alloc_pages+0x0/0x524) from [<c0bac238>] (fmem_alloc+0x50/0x18c)
[<c0bac1e8>] (fmem_alloc+0x0/0x18c) from [<bf12508c>] (fmem_ioctl+0x64/0x10c [mem])
[<bf125028>] (fmem_ioctl+0x0/0x10c [mem]) from [<c0c0c420>] (do_ioctl+0x80/0x94)
r6 = C004E401 r5 = FFFFFFE7 r4 = C593C940
[<c0c0c3a0>] (do_ioctl+0x0/0x94) from [<c0c0c728>] (vfs_ioctl+0x2f4/0x314)
r7 = 00000000 r6 = 00000003 r5 = 00000000 r4 = C593C940
[<c0c0c434>] (vfs_ioctl+0x0/0x314) from [<c0c0c788>] (sys_ioctl+0x40/0x5c)
r7 = 00000036 r6 = C004E401 r5 = FFFFFFF7 r4 = C593C940
[<c0c0c748>] (sys_ioctl+0x0/0x5c) from [<c0ba1a00>] (ret_fast_syscall+0x0/0x2c)
r6 = 00008660 r5 = 00008614 r4 = BE98FEE4
Code: e2433060 e1a04003 eafffff1 e3a03000 (e5833000)
Segmentation fault
由于 __alloc_pages 有一个著名的 2MB 问题,因此,我把 size 缩小为 (1280x1024x3/2)=1.8MB 左右, 测试结果表明:用 top 来看还有 10.9MB 空闲空间时,程序崩溃。
一般想来,即使是空间不够时,至多申请不到空间,也不会出现 crash 的情况呀?奇怪之极。
深入研究一下:
在 <linux/gfp.h> 中定义如下:
#ifdef CONFIG_NUMA
static inline struct page *
alloc_pages(gfp_t gfp_mask, unsigned int order)
{
if (unlikely(order >= MAX_ORDER))
return NULL;
return alloc_pages_current(gfp_mask, order);
}
#else
#define alloc_pages(gfp_mask, order) alloc_pages_node(numa_node_id(), gfp_mask, order)
#endif
MAX_ORDER 定义在 <linux/mmzone.h> 中,
#ifndef CONFIG_FORCE_MAX_ZONEORDER
#define MAX_ORDER 11
#else
#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
#endif
我在 autoconfig.h 中定义:
#define CONFIG_FORCE_MAX_ZONEORDER 12
所以,它是可以分配 2MB 以上大小的。
内存分配在高端,这是在 <linux/autoconfig.h> 中定义的:
#define CONFIG_ISOLATE_HIGHMEM 1
我记得我是修改过的,取消了这个定义,让系统在 kernel 中而不是高端分配内存。看来是我后来在做 make xconfig 时又还原回去了。会不会是这样造成的呢?
Mem: 44876K used, 82344K free, 0K shrd, 0K buff, 30512K cached
Load average: 0.00, 0.00, 0.00 (State: S=sleeping R=running, W=waiting)
CPU states: 0.2% user, 0.4% system, 0.0% nice, 99.4% idle
PID USER STATUS RSS PPID %CPU %MEM COMMAND
120 root R 428 114 0.5 0.3 exe
115 root S 580 1 0.0 0.4 mini_httpd
114 root S 500 18 0.0 0.3 sh
111 root S 428 1 0.0 0.3 bftpd
52 root S 364 1 0.0 0.2 sd_hotplug
18 root S 344 1 0.0 0.2 linuxrc
66 root S 328 1 0.0 0.2 sys_monitor
1 root S 324 0 0.0 0.2 init
95 root S 280 1 0.0 0.2 easycam
108 root S 68 1 0.0 0.0 telnetd
32 root SWN 0 1 0.0 0.0 jffs2_gcd_mtd1
2 root SWN 0 1 0.0 0.0 ksoftirqd/0
3 root SW< 0 1 0.0 0.0 events/0
4 root SW< 0 1 0.0 0.0 khelper
5 root SW< 0 1 0.0 0.0 kthread
6 root SW< 0 5 0.0 0.0 kblockd/0
7 root SW 0 5 0.0 0.0 pdflush
8 root SW 0 5 0.0 0.0 pdflush
9 root SW 0 1 0.0 0.0 kswapd0
10 root SW< 0 5 0.0 0.0 aio/0
~ $ cat /proc/meminfo
MemTotal: 127220 kB
MemFree: 82344 kB
Buffers: 0 kB
Cached: 30512 kB
SwapCached: 0 kB
Active: 12828 kB
Inactive: 18320 kB
HighTotal: 32768 kB
HighFree: 24320 kB
LowTotal: 94452 kB
LowFree: 58024 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
Mapped: 1772 kB
Slab: 2108 kB
CommitLimit: 47224 kB
Committed_AS: 7752 kB
PageTables: 124 kB
VmallocTotal: 122880 kB
VmallocUsed: 8800 kB
VmallocChunk: 113276 kB
如果仅在 high_mem 分配的话,那应该还余下 60MB 才对呀,这是为什么呢?
如果内存不足,应该分配空指针就行了,不必要 crash 呀,这是为什么呢?
看来就是因为一个分配在高端,一个在低端,这样在 alloc_pages 的时候出错的。因为我统一在低端分配时,会打印如下信息:
Out of Memory: Killed process 162 (sh).
~ $ Out of Memory: Killed process 163 (sh).
~ $ Out of Memory: Killed process 164 (sh).
~ $ Out of Memory: Killed process 165 (sh).
Out of Memory: Killed process 108 (telnetd).
~ $ Out of Memory: Killed process 166 (sh).
这样比较好一些,因为进程被 kill ,所以看门狗无法看护,板子会自动重启的。
但这样看起来,好象 linux 限制了可以获得的连续 page 的大小,最多就 40MB ,分配多了就认为是 out of memory.
我不知道 linux 认为自己需要保留多少 memory ,看上去 swap 的空间也是不可以用的 。
结论:
linux对连续内存的管理是有bug的。一般SoC平台提供商都自行推出了管理continous的kernel patch.