Defragging RAM / OOM failure

10

Esta questão é bastante longa, por isso vou fazer as perguntas no topo e, em seguida, passar pelo meu método de responder às perguntas:

  1. O (baseado em Busybox) rm não foi executado porque não havia RAM suficiente contígua?
  2. Em caso afirmativo, existe um método leve de desfragmentar o DMA - sem recorrer a um reinício do sistema?
  3. Se não, o que causou isso? Como posso evitar que isso aconteça no futuro?

Depois que nosso sistema de teste esteve funcionando de forma bastante intensa nos últimos dias - eu fiz o telnet no sistema e verifiquei os resultados do teste. Quando cheguei a excluir alguns dados, o sistema retornou a linha de comando (como se o comando tivesse sido executado corretamente). Quando cheguei para verificar o diretório para outro conjunto de resultados, vi o arquivo ainda existia (usando ls).

Depois disso, notei que cada vez mais meus comandos do shell não estão funcionando como esperado.

Vou começar com uma saída do dmesg depois que o rm não foi executado corretamente:

Allocation of length 61440 from process 6821 (rm) failed

DMA per-cpu:

CPU 0: hi: 0, btch: 1 usd: 0

Active_anon:0 active_file:1 inactive_anon:0 inactive_file:0 unevictable:6 dirty:0 writeback:0 unstable:0 free:821 slab:353 mapped:0 pagetables:0 bounce:0

DMA free:3284kB min:360kB low:448kB high:540kB active_anon:0kB inactive_anon:0kB active_file:4kB inactive_file:0kB unevictable:24kB present:8128kB pages_scanned:0 all_unreclaimable? no

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 total pagecache pages

Unable to allocate RAM for process data, errno 12

Inicialmente, achei que não consegui executar o programa na maior parte da memória contígua. O que significa que o DMA estava muito fragmentado e eu teria que encontrar uma maneira de fazer com que o sistema desfragmentasse a memória.

Então eu fiz uma checagem matemática rápida e percebi que o programa deveria ter sido executado no único slot de memória contígua de 64kB. Rm estava solicitando 61440 bytes (60kB).

Eu fiz um bom e velho "manual defrag" e reiniciei o sistema. Quando eu reiniciei o sistema eu saída / proc / buddyinfo:

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

Que eu suspeito mapear para:

  • 2 x 4 kB
  • 8 x 8 kB
  • 3 x 16 kB
  • 12 x 32 kB
  • 1 x 128 kB
  • 1 x 512 kB

Mas se somarmos a lista de valores acima, ela não corresponderá à saída de / proc / meminfo :

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

Para recapitular, minhas perguntas são:

  1. O rm não foi executado porque não havia RAM suficiente contígua?
  2. Em caso afirmativo, existe um método leve de desfragmentar o DMA - sem recorrer a um reinício do sistema?
  3. Se não, o que causou isso? Como posso evitar que isso aconteça no futuro?

Estou usando o XPort Pro da Lantronix (8MB, Linux OS) executando a versão 2.6.30 do uClinux. O shell em uso é hush.

    
por OldTinfoil 01.08.2012 / 16:51

2 respostas

6

Demorou um pouco, mas pensei em deixar de responder até ter respostas para todas as três das minhas sub-perguntas.

Antes de começar, porém, mencionarei que o termo correto quando se trata de "fragmentar" a memória de trabalho é chamado de "compactar" a memória de trabalho.

1. O rm não foi executado porque não havia RAM suficiente contígua?

Eu estava correto em minha conclusão - o rm não foi executado porque havia RAM contígua insuficiente. O sistema estava adquirindo RAM e fragmentando-o, tornando-o irrecuperável.

2. Em caso afirmativo, existe um método leve de desfragmentar o DMA - sem recorrer a um reinício do sistema?

Acontece que não há como compactar a memória, a não ser reiniciar o sistema embarcado. No caso de um sistema sem MMU, a prevenção é o nome do jogo.

Parte de mim pondera se é possível hackear o kernel do Linux para emular a MMU no software. Eu acho que se fosse possível, alguém já teria feito isso. Não consigo imaginar que seja um conceito totalmente novo;)

3. Como posso evitar que isso aconteça no futuro?

Para este projeto, eu estava usando o cron para iniciar manualmente o programa toda vez que fosse necessário. Uma maneira muito melhor de fazer isso é chamar o programa na inicialização e forçar o programa a dormir até que seja necessário. Desta forma, a memória não precisa ser alocada em cada uso. Reduzindo assim a fragmentação.

Na primeira iteração do projeto, contamos com as chamadas do meu shell script para executar funções críticas (como rm). Nós não vimos a necessidade de reinventar a roda se não precisássemos.

No entanto, eu recomendaria evitar o shell sempre que possível para um sistema sem MMU -

( Pergunta , o que acontece se você executar ls -la /path/to/directory/ | grep file-i-seek ?)

( Resposta : inicia um novo subprocesso)

Se você precisar implementar algumas das principais funcionalidades do script de shell em seu programa em C, recomendo verificar o código-fonte usado em BusyBox . É provável que você esteja usando C no seu sistema embarcado ..

    
por 13.09.2012 / 14:34
10

Em sua pergunta 2 (desfragmentando memória), citando link :

compact_memory

Available only when CONFIG_COMPACTION is set. When 1 is written to the file, all zones are compacted such that free memory is available in contiguous blocks where possible. This can be important for example in the allocation of huge pages although processes will also directly compact memory as required.

isso implica que o seguinte comando (executado com privilégios de root e se a opção do kernel mencionada acima estava habilitada)

echo 1 > /proc/sys/vm/compact_memory

deve dizer ao kernel para tentar desfragmentar a memória o máximo possível. Tenha cuidado, por exemplo em algumas versões do RHEL6, isso pode travar o kernel ...

    
por 01.08.2014 / 15:28