Essa pergunta é bastante longa, então vou fazer as perguntas no topo e depois seguir meu método de chegar às perguntas:
- O rm (baseado no Busybox) não foi executado porque não havia RAM contígua suficiente?
- Em caso afirmativo, existe um método leve de desfragmentar o DMA - sem recorrer à reinicialização do sistema?
- Se não, o que causou isso? Como posso impedir que isso aconteça no futuro?
Depois que nosso sistema de teste esteve funcionando intensivamente nos últimos dias - eu liguei para o sistema e verifiquei os resultados do teste. Quando vim para excluir alguns dados, o sistema retornou a linha de comando (como se o comando tivesse sido executado corretamente). Quando cheguei a verificar o diretório para outro conjunto de resultados, vi que o arquivo ainda existia (usando ls).
Depois disso, notei que mais e mais dos meus comandos do shell não estavam funcionando conforme o esperado.
Começarei com uma saída do dmesg depois que o rm falhou ao executar corretamente:
Falha na alocação do comprimento 61440 do processo 6821 (rm)
DMA por CPU:
CPU 0: oi: 0, btch: 1 usd: 0
Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 inevitável: 6 sujo: 0 write-back: 0 instável: 0 grátis: 821 slab: 353 mapeado: 0 pagetables: 0 rejeição: 0
Livre de DMA: 3284kB min: 360kB baixo: 448kB alto: 540kB ativo_anon: 0kB inativo_anon: 0kB arquivo ativo - 4kB arquivo ativo - 0kB arquivo ativo - 0kB inevitável: 24kB presente: 8128kB páginas_scaneadas: 0 all_unreclaimable? não
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 de páginas de pagecache
Não foi possível alocar RAM para dados do processo, erro 12
Inicialmente, pensei que não conseguiria executar o programa na maior parte da memória contígua. Significando que o DMA estava muito fragmentado e eu teria que encontrar uma maneira de fazer com que o sistema desfragmentasse a memória.
Fiz uma rápida verificação de matemática / sanidade e percebi que o programa deveria ser capaz de rodar no único slot de memória contígua de 64kB. A Rm estava solicitando 61440 bytes (60kB).
Eu fiz um bom e velho "desfragmentador manual" e reiniciei o sistema. Quando reiniciei o sistema, produzi / proc / buddyinfo:
Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0
O qual suspeito suspeito mapear:
- 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 alguém soma a lista de valores acima, ela não corresponde à 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:
- O rm não foi executado porque não havia RAM contígua suficiente?
- Em caso afirmativo, existe um método leve de desfragmentar o DMA - sem recorrer à reinicialização do sistema?
- Se não, o que causou isso? Como posso impedir que isso aconteça no futuro?
Estou usando o XPort Pro da Lantronix (8 MB, Linux OS) executando o uClinux versão 2.6.30. A concha em uso é silenciosa.
Respostas:
Na sua pergunta 2 (desfragmentando a memória), citando https://www.kernel.org/doc/Documentation/sysctl/vm.txt :
isso implica que o seguinte comando (executado com privilégios de root e se a opção do kernel mencionada acima foi ativada)
deve dizer ao kernel para tentar desfragmentar a memória o máximo possível. Cuidado, por exemplo, em algumas versões do RHEL6, isso pode travar o kernel ...
fonte
Demorou um pouco de tempo, mas pensei em adiar a resposta até ter respostas para todas as três das minhas sub-perguntas.
Antes de começar, mencionarei que o termo correto quando se trata de "des-fragmentar" a memória de trabalho é referido como "compactar" a memória de trabalho.
1. O rm não foi executado porque não havia RAM contígua suficiente?
Eu estava certo em minha conclusão - a rm não foi executada porque havia RAM contígua insuficiente. O sistema estava adquirindo RAM e fragmentando-o, tornando-o irrecuperável.
2. Se sim, existe um método leve de desfragmentar o DMA - sem recorrer à reinicialização do sistema?
Acontece que não há como compactar a memória, exceto reiniciar o sistema incorporado. No caso de um sistema sem MMU, prevenção é o nome do jogo.
Parte de mim pondera se é possível hackear o kernel do linux para emular o 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 impedir que isso aconteça no futuro?
Para este projeto, eu estava usando o cron para iniciar manualmente o programa sempre que 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. Dessa 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 minhas chamadas de shell script para executar funções críticas (como rm). 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 shell no programa C, recomendo verificar o código-fonte usado no BusyBox . Provavelmente, você usará C em seu sistema incorporado.
fonte