사용할 메모리(예: "58*4096kB (C)")가 아직 충분한데 "페이지 할당 실패"가 나타나는 이유는 무엇입니까?

사용할 메모리(예: "58*4096kB (C)")가 아직 충분한데 "페이지 할당 실패"가 나타나는 이유는 무엇입니까?

"58*4096kB (C)"를 사용할 수 있는데 "페이지 할당 실패"가 나타나는 이유는 무엇입니까?

알다시피, 커널은 order:10 크기의 메모리를 할당할 때 불평합니다(즉, 페이지 할당 실패: order:10). 그러나 실제로는 사용 가능한 블록(예: "58*4096kB (C)")이 있습니다. 그래서 실제로 사용 가능한 메모리가 충분하기 때문에 불평해서는 안 된다고 생각합니다.

관련 로그는 다음과 같습니다.

[ 2161.623563] xxxx: page allocation failure: order:10, mode:0x2084020(GFP_ATOMIC|__GFP_COMP)
[ 2161.632085] CPU: 0 PID: 179 Comm: AiApp Not tainted 4.9.56 #53
[ 2161.637947] 
Call Trace:
[<802f63f2>] dump_stack+0x1e/0x3c
[<800f6cf4>] warn_alloc+0x100/0x148
[<800f709c>] __alloc_pages_nodemask+0x2bc/0xb5c
[<801120fe>] kmalloc_order+0x26/0x48
[<80112158>] kmalloc_order_trace+0x38/0x98
[<8012c5d8>] __kmalloc+0xf4/0x12c
[<8048ac78>] alloc_ep_req+0x5c/0x98
[<8048f232>] source_sink_recv+0x2a/0xe0
[<8048f35e>] usb_sourcesink_bulk_read+0x76/0x1c8
[<8048f770>] usb_sourcesink_read+0xfc/0x2c8
[<80134d58>] __vfs_read+0x30/0x108
[<80135c14>] vfs_read+0x94/0x128
[<80136d12>] SyS_read+0x52/0xd4
[<8004a246>] csky_systemcall+0x96/0xe0
[ 2161.689204] Mem-Info:
[ 2161.691518] active_anon:3268 inactive_anon:2 isolated_anon:0
[ 2161.691518]  active_file:1271 inactive_file:89286 isolated_file:0
[ 2161.691518]  unevictable:0 dirty:343 writeback:0 unstable:0
[ 2161.691518]  slab_reclaimable:2019 slab_unreclaimable:644
[ 2161.691518]  mapped:4282 shmem:4 pagetables:59 bounce:0
[ 2161.691518]  free:62086 free_pcp:199 free_cma:60234

[ 2161.724334] Node 0 active_anon:13072kB inactive_anon:8kB active_file:5084kB inactive_file:357144kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:17128kB dirty:1372kB writeback:0kB shmem:16kB writeback_tmp:0kB unstable:0kB pages_scanned:0 all_unreclaimable? no

[ 2161.748626] Normal free:248344kB min:2444kB low:3052kB high:3660kB active_anon:13072kB inactive_anon:8kB active_file:5084kB inactive_file:357144kB unevictable:0kB writepending:1372kB present:1048572kB managed:734568kB mlocked:0kB slab_reclaimable:8076kB slab_unreclaimable:2576kB kernel_stack:608kB pagetables:236kB bounce:0kB free_pcp:796kB local_pcp:796kB free_cma:240936kB
[ 2161.781670] lowmem_reserve[]: 0 0 0

[ 2161.785225] Normal: 4*4kB (UEC) 3*8kB (EC) 3*16kB (UEC) 2*32kB (UE) 2*64kB (UE) 2*128kB (UE) 2*256kB (EC) 1*512kB (E) 3*1024kB (UEC) 3*2048kB (UEC) 58*4096kB (C) = 248344kB
90573 total pagecache pages

[ 2161.803526] 262143 pages RAM
[ 2161.806410] 0 pages HighMem/MovableOnly
[ 2161.810264] 78501 pages reserved
[ 2161.813509] 90112 pages cma reserved

답변1

이러한 일이 발생하는 조건, 실행 중인 시스템(Linux, Android 등) 등과 같은 많은 정보를 제공하지 않았습니다.

어쨌든 커널 미세 조정을 시작할 수 있습니다. 를 사용하면 vm.min_free_kbytes커널이 모든 상황에서 해당 메모리를 KiB 단위로 자유롭게 유지하도록 지시할 수 있습니다.

~에서kernel.org 문서("/proc/sys/vm/*에 대한 문서"):

사용 가능한 최소 킬로바이트:

이는 Linux VM이 사용 가능한 최소 킬로바이트 수를 유지하도록 하는 데 사용됩니다 . VM은 이 숫자를 사용하여 WMARK_MIN시스템의 각 lowmem 영역에 대한 watermark[ ] 값을 계산합니다. 각 lowmem 영역은 크기에 비례하여 예약된 무료 페이지 수를 얻습니다.

할당을 충족하려면 최소 메모리 양이 필요합니다 . 1024KB **PF_MEMALLOC 미만으로 설정하면 시스템이 미묘하게 손상되고 높은 부하에서 교착 상태가 발생하기 쉽습니다.

너무 높게 설정하면 기기가 즉시 OOM 상태가 됩니다.

이를 영구적으로 변경하려면 다음을 수행할 수 있습니다(최대 16MiB).

echo "vm.min_free_kbytes=16384" >> /etc/sysctl.conf

모든 것이 제대로 작동하는지 테스트하려면 현재 세션에 대해서만 변경하면 됩니다.

sysctl -w vm.min_free_kbytes=16384

본 정보의 출처는kernel.org 문서.


귀하의 질문은 위에 지정된 것보다 더 많은 여유 메모리가 있음에도 불구하고 여유 메모리가 있을 때 페이지 오류가 발생하는 이유는 무엇입니까?

사용 가능한 메모리가 지정된 제한을 초과하면 vm.min_free_kbytes대답이 나올 가능성이 높습니다.메모리 조각화 (메모리 모듈 결함 등 다른 문제도 있을 수 있습니다.)

세부사항은 다음과 같습니다:

order:10비트는 요청된 페이지 수를 간접적으로 알려줍니다. 이러한 순서는 실제로 1024페이지 또는 4096KiB의 연속 메모리에 해당하는 2 10 (2^10)을 요청하기 때문에 상위 순서로 간주됩니다!

이는 mode커널 메모리 할당자에 전달되는 플래그입니다. mode:0x2084020 (GFP_ATOMIC|__GFP_COMP) - 커널 모드 할당자(플래그) 가 있습니다 . 이를 위해서는 커널 소스 코드에 대한 지식이 필요합니다. 로고를 자세히 설명해주세요.

배너 GFP_ATOMIC:

GFP_ATOMIC플래그는 메모리 할당자가 차단되지 않음을 나타냅니다. 인터럽트 처리기, 하위 절반, 잠금을 유지하는 프로세스 컨텍스트 코드와 같이 절전 모드가 불가능한(원자성으로 유지되어야 함) 상황에서 이 플래그를 사용합니다. 커널은 할당을 차단할 수 없으며 요청을 충족하기에 충분한 메모리를 확보하려고 시도하기 때문에 지정된 할당은 GFP_ATOMIC지정되지 않은 할당보다 성공 가능성이 더 낮습니다. 하지만 현재 환경에서 수면이 불가능하다면 이것이 유일한 선택입니다. …

배너 __GFP_COMP:

복합 페이지 메타데이터

include/linux/gfp.h에서(참조:소스 1,소스 2).

이 페이지 프레임은 확장 페이지에 속합니다.

이는 필요한 메모리 양으로 돌아옵니다. 확장 페이지를 사용하면 4KiB가 아닌 4MiB 페이지 프레임을 가질 수 있습니다. 추천 도서: 리눅스 커널책과 훌륭한 기사: Kernel Korner - 커널에 메모리를 할당합니다.더 많은 정보를 알고 싶습니다.

보시다시피 4096 KiB의 비차단 할당을 요청했으며 할당은 원자성으로 유지되어야 합니다. 할당을 차단하고 메모리를 (연속적으로) 해제하려고 시도할 수 없습니다. 따라서 할당이 실패했습니다.

플래그는 다음에서 찾을 수 있습니다 include/linux/gfp.h (참조소스 1,소스 2).

편집 – 커널 버전 4.9

이는 커널 버전 4.9에 대한 중요한 정보입니다. 이 정확한 커널 버전(4.9)에는 SWAP이 전혀 작동하지 않게 만드는 회귀가 있었습니다.OOM이지만 스왑 영역이 사용되지 않음(kernel.org).

이 문제를 해결하는 권장 방법은 커널을 4.10.8 이상으로 업그레이드하는 것입니다. 이 버그는 이 버전 이상에서 수정되어야 합니다. 자세한 내용은 을 참조하세요.OOM이지만 스왑 영역이 사용되지 않음(Red Hat)

__________________
*    아마도 킬로바이트를 의미하는 것 같습니다.
** 아마도 KiB를 의미할 것입니다.

관련 정보