RAM 조각 모음/OOM 오류

RAM 조각 모음/OOM 오류

이 질문은 꽤 길기 때문에 질문을 맨 위에 게시한 다음 문제에 대한 해결책을 살펴보겠습니다.

  1. (Busybox 기반) 연속 RAM이 부족해서 rm이 ​​실행되지 않았나요?
  2. 그렇다면 시스템을 재부팅하지 않고 DMA 조각 모음을 수행할 수 있는 간단한 방법이 있습니까?
  3. 그렇지 않다면 그 이유는 무엇입니까? 앞으로 이런 일이 다시 발생하지 않도록 하려면 어떻게 해야 합니까?

지난 며칠 동안 테스트 시스템이 상당히 집중적으로 실행된 후 원격 로그인을 통해 시스템에 로그인하여 테스트 결과를 확인했습니다. 일부 데이터를 삭제하려고 하면 시스템이 명령줄을 반환합니다(마치 명령이 올바르게 실행된 것처럼). 디렉토리에서 다른 결과 세트를 확인할 때 파일이 여전히 존재하는 것을 확인합니다(ls 사용).

그 후 예상대로 실행되지 않는 쉘 명령이 점점 더 많아지는 것을 발견했습니다.

출력부터 시작하겠습니다.정보rm이 올바르게 실행되지 못한 후:

프로세스 6821(rm)에서 길이 61440을 할당하지 못했습니다.

CPU당 DMA:

CPU 0: 안녕하세요: 0, btch: $1: 0

Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 삭제할 수 없음: 6 dirty: 0 writeback: 0 불안정: 0 유휴: 821 flat: 353 매핑: 0 페이지 테이블: 0 바운스: 0

DMA 유휴: 3284kB 최소: 360kB 낮음: 448kB 높음: 540kB active_anon: 0kB inactive_anon: 0kB active_file: 4kB inactive_file: 0kB 삭제할 수 없음: 24kB 현재: 8128kB Pages_scanned: 0 all_unreclaimable? 아니요

lowmem_reserve[]: 0 0 0

DMA: 31*4kB 47*8kB 42*16kB 64*32kB 1*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3284kB

총 14개의 페이지 캐시 페이지

프로세스 데이터에 RAM을 할당할 수 없습니다. 오류 번호 12

처음에는 연속 메모리의 가장 큰 부분에서 프로그램을 실행할 수 없을 것이라고 생각했습니다. 이는 DMA가 너무 조각화되어 시스템이 메모리 조각 모음을 수행하도록 하는 방법을 찾아야 함을 의미합니다.

그런 다음 나는 빠른 수학/온전성 검사를 수행하고 프로그램이 유일한 64kB 연속 메모리 슬롯에서 실행될 수 있어야 한다는 것을 깨달았습니다. Rm은 61440바이트(60kB)를 요청했습니다.

나는 오래된 "수동 조각 모음"을 수행하고 시스템을 재부팅했습니다. 시스템을 재부팅하면 /proc/buddyinfo가 출력됩니다.

Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0

다음과 같은 매핑이 의심됩니다.

  • 2×4kB
  • 8x8KB
  • 3x16KB
  • 12x32KB
  • 1×128kB
  • 1x512KB

그러나 위의 값 목록을 합산하면 다음의 출력과 일치하지 않습니다./proc/메모리 정보:

MemTotal:           6580 kB
MemFree:            3164 kB
Buffers:               0 kB
Cached:              728 kB
SwapCached:            0 kB
Active:              176 kB
Inactive:            524 kB
Active(anon):          0 kB
Inactive(anon):        0 kB
Active(file):        176 kB
Inactive(file):      524 kB`
Unevictable:           0 kB
Mlocked:               0 kB
MmapCopy:            844 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Slab:               1268 kB
SReclaimable:        196 kB
SUnreclaim:         1072 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        3288 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

요약하자면 내 질문은 다음과 같습니다.

  1. 연속 RAM이 부족하여 rm이 실행되지 않습니까?
  2. 그렇다면 시스템을 재부팅하지 않고 DMA 조각 모음을 수행할 수 있는 간단한 방법이 있습니까?
  3. 그렇지 않다면 그 이유는 무엇입니까? 앞으로 이런 일이 다시 발생하지 않도록 하려면 어떻게 해야 합니까?

저는 uClinux 버전 2.6.30을 실행하는 Lantronix의 XPort Pro(8MB, Linux OS)를 사용하고 있습니다. 사용된 인클로저는 조용합니다.

답변1

메모리 조각 모음 정보, 견적커널 문서:

현재 이러한 파일은 다음 위치에 있습니다 /proc/sys/vm. [...]

compact_memory

경우에만 사용 가능CONFIG_COMPRESSION설정되었습니다. 1파일에 쓸 때 모든 영역은 가능한 경우 연속 블록에 사용 가능한 메모리를 제공하기 위해 압축됩니다. 프로세스가 필요에 따라 메모리를 직접 압축할 수도 있지만 이는 큰 페이지를 할당할 때 중요할 수 있습니다.

이는 다음 명령을 의미합니다(루트 권한으로 실행되고 위 커널 옵션이 활성화된 경우).

echo 1 > /proc/sys/vm/compact_memory

가능한 한 많은 메모리 조각 모음을 시도하도록 커널에 지시해야 합니다. 예를 들어 일부 RHEL6 버전에서는 커널이 충돌할 수 있습니다.

답변2

시간이 좀 걸렸지만 세 가지 하위 질문에 대한 답변을 모두 얻을 때까지 답변을 보류해야겠다고 생각했습니다.

시작하기 전에 작업 기억을 "구성"하는 것에 대해 이야기할 때 정확한 용어는 작업 기억을 "압축"하는 것임을 언급하고 싶습니다.

1. 연속 RAM이 부족해서 rm이 ​​실행되지 않는 건가요?

내 결론은 정확합니다. 연속 RAM이 충분하지 않기 때문에 rm이 실행되지 않습니다. 시스템은 계속해서 RAM을 사용하고 조각화하므로 회수가 불가능해집니다.

2. 그렇다면 시스템을 재부팅하지 않고 DMA 조각 모음을 수행할 수 있는 간단한 방법이 있습니까?

임베디드 시스템을 재부팅하는 것 외에는 메모리를 압축할 수 있는 방법이 없다는 것이 밝혀졌습니다. MMU가 없는 시스템의 경우 예방이 가장 중요합니다.

소프트웨어에서 MMU를 에뮬레이션하기 위해 Linux 커널을 해킹하는 것이 가능한지 궁금합니다. 가능하다면 누군가 이미 했을 것이라고 생각합니다. 완전히 새로운 개념이라고는 생각할 수 없습니다 ;)

3. 앞으로 이런 일이 발생하지 않도록 하려면 어떻게 해야 합니까?

이 프로젝트에서는 필요할 때마다 cron을 사용하여 프로그램을 수동으로 시작했습니다. 더 나은 접근 방식은 시작 시 프로그램을 호출한 다음 필요할 때까지 프로그램을 강제로 절전 모드로 전환하는 것입니다. 이렇게 하면 사용할 때마다 메모리를 할당할 필요가 없습니다. 이를 통해 단편화를 줄입니다.

프로젝트의 첫 번째 반복에서 우리는 쉘 스크립트 호출을 사용하여 중요한 기능(예: rm)을 수행했습니다. 꼭 필요한 것이 아니라면 바퀴를 재발명할 필요가 없다고 생각합니다.

그러나 MMU가 없는 시스템에서는 가능하면 셸 사용을 피하는 것이 좋습니다.

(질문, 실행되면 어떻게 될까요 ls -la /path/to/directory/ | grep file-i-seek? )

(답변: 새로운 자식 프로세스를 시작합니다)

C 프로그램에서 일부 핵심 쉘 스크립팅 기능을 구현해야 하는 경우 다음에서 사용된 소스 코드를 살펴보는 것이 좋습니다.바쁜 상자. 임베디드 시스템에서는 C 언어를 사용할 가능성이 높습니다.

관련 정보