为什么还有36MB内存时,再分配连续内存alloc_pages()系统也会crash?

<!-- /* 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.

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草根大哥

进军大神程序员路上,谢谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值