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 ..