Esta pregunta es bastante larga, así que haré las preguntas en la parte superior y luego pasaré por mi método para llegar a las preguntas:
- ¿No se ejecutó rm (basado en Busybox) porque no había suficiente RAM contigua?
- Si es así, ¿existe un método ligero para desfragmentar el DMA, sin recurrir a un reinicio del sistema?
- Si no, ¿qué lo causó? ¿Cómo puedo evitar que suceda en el futuro?
Después de que nuestro sistema de prueba se había ejecutado con bastante intensidad en los últimos días, ingresé por telnet al sistema y verifiqué los resultados de la prueba. Cuando vine a eliminar algunos datos, el sistema devolvió la línea de comando (como si el comando se hubiera ejecutado correctamente). Cuando llegué a revisar el directorio para obtener otro conjunto de resultados, vi que el archivo todavía existía (usando ls).
Después de esto, noté que más y más de mis comandos de shell no funcionaban como se esperaba.
Comenzaré con una salida de dmesg después de que rm no se ejecute correctamente:
La asignación de la longitud 61440 del proceso 6821 (rm) falló
DMA por CPU:
CPU 0: hola: 0, btch: 1 usd: 0
Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 unevictable: 6 dirty: 0 writeback: 0 instable: 0 free: 821 slab: 353 mapped: 0 pagetables: 0 bounce: 0
DMA libre: 3284kB min: 360kB bajo: 448kB alto: 540kB active_anon: 0kB inactive_anon: 0kB active_file: 4kB inactive_file: 0kB unevictable: 24kB presente: 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 páginas de caché total de páginas
No se puede asignar RAM para procesar datos, errno 12
Inicialmente, pensé que no podía ejecutar el programa en la mayor parte de la memoria contigua. Lo que significa que el DMA estaba demasiado fragmentado y tendría que encontrar una manera de hacer que el sistema desfragmente la memoria.
Luego hice una rápida comprobación matemática / cordura y me di cuenta de que el programa debería haber podido ejecutarse en la única ranura de memoria contigua de 64kB. Rm estaba solicitando 61440 bytes (60kB).
Hice una buena "desfragmentación manual" y reinicié el sistema. Cuando reinicié el sistema, saqué / proc / buddyinfo:
Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0
El cual sospecho que es un mapa:
- 2 x 4 kB
- 8 x 8 kB
- 3 x 16 kB
- 12 x 32 kB
- 1 x 128 kB
- 1 x 512 kB
Pero si se suma la lista de valores anterior, no coincide con la salida 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
En resumen, mis preguntas son:
- ¿No se ejecutó rm porque no había suficiente RAM contigua?
- Si es así, ¿existe un método ligero para desfragmentar el DMA, sin recurrir a un reinicio del sistema?
- Si no, ¿qué lo causó? ¿Cómo puedo evitar que suceda en el futuro?
Estoy usando XPort Pro de Lantronix (8 MB, sistema operativo Linux) con uClinux versión 2.6.30. La cáscara en uso es silencio.
Respuestas:
En su pregunta 2 (desfragmentación de memoria), citando https://www.kernel.org/doc/Documentation/sysctl/vm.txt :
esto implica que el siguiente comando (ejecutado con privilegios de root y si la opción del kernel mencionada anteriormente estaba habilitada)
debería decirle al kernel que intente desfragmentar la memoria tanto como sea posible. Tenga en cuenta que, por ejemplo, en algunas versiones de RHEL6, esto puede bloquear el núcleo ...
fuente
Me tomó un poco de tiempo, pero pensé que esperaría para contestar hasta que tuviera respuestas a mis 3 subpreguntas.
Sin embargo, antes de comenzar, mencionaré que el término correcto cuando se trata de "fragmentar" la memoria de trabajo se refiere a "compactar" la memoria de trabajo.
1. ¿No se ejecutó rm porque no había suficiente RAM contigua?
Estuve correcto en mi conclusión: rm no se ejecutó porque no había suficiente RAM contigua. El sistema había estado adquiriendo RAM y fragmentándolo, haciéndolo irrecuperable.
2. Si es así, ¿existe un método ligero para desfragmentar el DMA sin recurrir a un reinicio del sistema?
Resulta que no hay forma de compactar la memoria, salvo reiniciar el sistema incorporado. En el caso de un sistema sin MMU, la prevención es el nombre del juego.
Parte de mí reflexiona si es posible hackear el kernel de Linux para emular la MMU en el software. Me imagino que si fuera posible, alguien ya lo habría hecho. No puedo imaginar que sea un concepto completamente nuevo;)
3. ¿Cómo puedo evitar que suceda en el futuro?
Para este proyecto, estaba usando cron para iniciar manualmente el programa cada vez que se requería. Una forma mucho mejor de hacer esto es llamar al programa al inicio y luego forzar el programa a que se suspenda hasta que sea necesario. De esta manera, no es necesario asignar memoria a cada uso. Reduciendo así la fragmentación.
En la primera iteración del proyecto, confiamos en mis llamadas de script de shell para realizar funciones críticas (como rm). No vimos la necesidad de reinventar la rueda si no fuera necesario.
Sin embargo, recomendaría evitar el shell donde sea posible para un sistema sin MMU:
( Pregunta , ¿qué pasa si ejecutas
ls -la /path/to/directory/ | grep file-i-seek
?)( Respuesta : comienza un nuevo subproceso)
Si necesita implementar algunas de las funciones del script de shell central en su programa C, le recomiendo que consulte el código fuente utilizado en BusyBox . Lo más probable es que use C en su sistema integrado.
fuente