Как я могу программно получить объем памяти, доступный в настоящее время из кода C/С++?

В моем программном слое промежуточного программного обеспечения я получаю много сбоев из-за сообщения,

page allocation failure. order:10, mode:0xd1

Как я понимаю, авария может произойти по ряду причин, заканчивая динамической памятью для дальнейших распределений или фрагментации памяти.

Обратная линия, которая следует за сообщением, не имеет отношения к тому, что она поступает через модуль сторонних драйверов. Скорее всего, проблема связана с этим драйвером, но, к сожалению, я не могу ни получить отладочную информацию, ни исходный код. Я хотел бы профилировать свой исходный код, используя некоторые программные вызовы функций, чтобы исключить возможность двух описанных выше сценариев.

Я не могу использовать valgrind, потому что ARM еще не полностью поддерживается Valgrind.

[Обновить:] Добавление stacktrace, поскольку ответ @caf предполагает, что в нем может быть какая-то ценная информация.

Application: page allocation failure. order:10, mode:0xd1
Backtrace:                                                  
[<c00297d0>] (dump_backtrace+0x0/0x114) from [<c02812b8>] (dump_stack+0x18/0x1c)
 r7:0000000a r6:000000d1 r5:00000000 r4:00000000                                
[<c02812a0>] (dump_stack+0x0/0x1c) from [<c00716e4>] (__alloc_pages_nodemask+0x49c/0x4fc)
[<c0071248>] (__alloc_pages_nodemask+0x0/0x4fc) from [<c007175c>] (__get_free_pages+0x18/0x44)
[<c0071744>] (__get_free_pages+0x0/0x44) from [<bf021790>] (tsif_request_rx_buffer+0x74/0xf4 [tsif_data])
[<bf02171c>] (tsif_request_rx_buffer+0x0/0xf4 [tsif_data]) from [<bf021bd8>] (tsif_data_ioctl+0x17c/0x9d4 [tsif_data])
 r7:be9e8604 r6:c0045319 r5:c3793400 r4:00000007
[<bf021a5c>] (tsif_data_ioctl+0x0/0x9d4 [tsif_data]) from [<c00a1c30>] (vfs_ioctl+0x78/0x94)
[<c00a1bb8>] (vfs_ioctl+0x0/0x94) from [<c00a22e0>] (do_vfs_ioctl+0x594/0x5f0)
 r7:c2067e80 r6:00000021 r5:c2067e80 r4:00000021
[<c00a1d4c>] (do_vfs_ioctl+0x0/0x5f0) from [<c00a237c>] (sys_ioctl+0x40/0x64)
[<c00a233c>] (sys_ioctl+0x0/0x64) from [<c0025ec0>] (ret_fast_syscall+0x0/0x28)
 r7:00000036 r6:00144220 r5:00139030 r4:008a47cc
Mem-info:
DMA per-cpu:
CPU    0: hi:   18, btch:   3 usd:   0
active_anon:4120 inactive_anon:134 isolated_anon:0
 active_file:79 inactive_file:3729 isolated_file:0
 unevictable:0 dirty:0 writeback:0 unstable:0 buffer:0
 free:4137 slab_reclaimable:198 slab_unreclaimable:894
 mapped:1707 shmem:64 pagetables:75 bounce:0
DMA free:16548kB min:1104kB low:1380kB high:1656kB active_anon:16480kB inactive_anon:536kB active_file:316kB inactive_file:14916kB unevictable:0kB isolated(o
lowmem_reserve[]: 0 0 0
DMA: 215*4kB 131*8kB 73*16kB 49*32kB 30*64kB 8*128kB 3*256kB 2*512kB 3*1024kB 2*2048kB 0*4096kB 0*8192kB 0*16384kB = 16548kB
3872 total pagecache pages
19200 pages of RAM
4209 free pages
4738 reserved pages
960 slab pages
1751 pages shared
0 pages swap cached

Итак, вопрос в том, как я могу программно получить объем памяти, доступный в настоящее время из кода C/С++, платформа Linux.

Ответ 1

Сообщение, которое вы указали, указывает на невозможность выделения памяти для распределения ядра, а не для распределения пользовательского пространства. Это запрос для 4 МБ (это то, что означает order = 10) блок смежной физической памяти. Это очень большой запрос kmalloc(), и неудивительно, что он терпит неудачу (вероятно, из-за фрагментации памяти, а не свободной памяти).

Вы можете узнать, сколько свободной памяти доступно в /proc/meminfo, однако более подробное резюме доступно из журнала ядра сразу после обратной линии - начиная с строки "Mem-info".


Ваша обратная трассировка показывает, что доступно 16548 КБ памяти, но самый большой блок - 2048 КБ (order = 9). Таким образом, фрагментация памяти действительно ваша проблема.

Из чтения источника для драйвера tsif, который вы используете, кажется, что драйвер запрашивает выделение ядра с размером полностью управляемый пользовательским пространством, вызывается TSIF_REQ_RX_BUF ioctl() (это очень плохой дизайн, особенно учитывая, что он даже не пытается сообщать о сбоях в пользовательском пространстве!). Мое предложение состоит в том, чтобы уменьшить размер буфера, который вы запрашиваете, с помощью этого ioctl.