Cette question est assez longue, donc je vais poser les questions en haut et ensuite passer par ma méthode pour arriver aux questions:
- (Basé sur Busybox) rm ne s'est-il pas exécuté parce qu'il n'y avait pas assez de RAM contiguë?
- Si oui, existe-t-il une méthode légère pour défragmenter le DMA - sans avoir recours à un redémarrage du système?
- Sinon, quelle en est la cause? Comment puis-je empêcher que cela se produise à l'avenir?
Après que notre système de test ait fonctionné assez intensivement au cours des derniers jours - j'ai telneté dans le système et vérifié les résultats du test. Lorsque je suis venu pour supprimer certaines données, le système a renvoyé la ligne de commande (comme si la commande s'était exécutée correctement). Quand je suis venu vérifier le répertoire pour un autre ensemble de résultats, j'ai vu que le fichier existait toujours (en utilisant ls).
Après cela, j'ai remarqué que de plus en plus de mes commandes shell ne fonctionnaient pas comme prévu.
Je vais commencer avec une sortie de dmesg après l'échec de l'exécution de rm:
Échec de l'allocation de la longueur 61440 à partir du processus 6821 (rm)
DMA par processeur:
CPU 0: hi: 0, btch: 1 usd: 0
Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 non prévisible: 6 sale: 0 écriture différée: 0 instable: 0 libre: 821 dalle: 353 mappé: 0 pagetables: 0 rebond: 0
Sans DMA: 3284 ko min: 360 ko bas: 448 ko haut: 540 ko active_anon: 0 ko inactif_anon: 0 ko fichier_actif: 4 ko fichier inactif: 0 ko non prévisible: 24 ko présent: 8128 ko pages numérisées: 0 tout_non récupérable? non
lowmem_reserve []: 0 0 0
DMA: 31 * 4 Ko 47 * 8 Ko 42 * 16 Ko 64 * 32 Ko 1 * 64 Ko 0 * 128 Ko 0 * 256 Ko 0 * 512 Ko 0 * 1024 Ko 0 * 2048 Ko 0 * 4096 Ko = 3284 Ko
14 pages de pagecache au total
Impossible d'allouer de la RAM pour les données de processus, errno 12
Au début, je pensais que j'étais incapable d'exécuter le programme dans la plus grande partie de la mémoire contiguë. Cela signifie que le DMA était trop fragmenté et que je devrais trouver un moyen d'obtenir que le système défragmente la mémoire.
Ensuite, j'ai fait une vérification rapide des mathématiques / de la santé mentale et j'ai réalisé que le programme aurait dû pouvoir s'exécuter dans le seul emplacement de mémoire contigu de 64 Ko. Rm demandait 61440 octets (60 Ko).
J'ai fait une bonne vieille "défragmentation manuelle" et j'ai redémarré le système. Lorsque j'ai redémarré le système, je produis / proc / buddyinfo:
Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0
Que je soupçonne de mapper:
- 2 x 4 ko
- 8 x 8 ko
- 3 x 16 kB
- 12 x 32 ko
- 1 x 128 Ko
- 1 x 512 Ko
Mais si l'on additionne la liste de valeurs ci-dessus, elle ne correspond pas à la sortie 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
Pour récapituler, mes questions sont les suivantes:
- Rm ne s'est-il pas exécuté parce qu'il n'y avait pas assez de RAM contiguë?
- Si oui, existe-t-il une méthode légère pour défragmenter le DMA - sans avoir recours à un redémarrage du système?
- Sinon, quelle en est la cause? Comment puis-je empêcher que cela se produise à l'avenir?
J'utilise XPort Pro de Lantronix (8 Mo, OS Linux) exécutant uClinux version 2.6.30. La coquille utilisée est silencieuse.
Réponses:
Sur votre question 2 (défragmenter la mémoire), en citant https://www.kernel.org/doc/Documentation/sysctl/vm.txt :
cela implique que la commande suivante (exécutée avec les privilèges root et si l'option de noyau mentionnée ci-dessus a été activée)
devrait indiquer au noyau d'essayer de défragmenter la mémoire autant que possible. Attention par exemple sur certaines versions de RHEL6, cela peut planter le noyau ...
la source
Cela a pris un peu de temps, mais j'ai pensé que je ne répondrais pas jusqu'à ce que j'aie des réponses à mes 3 sous-questions.
Avant de commencer cependant, je mentionnerai que le terme correct lorsqu'il s'agit de «dé-fragmenter» la mémoire de travail est appelé «compactage» de la mémoire de travail.
1. rm ne s'est-il pas exécuté parce qu'il n'y avait pas assez de RAM contiguë?
J'avais raison dans ma conclusion - rm ne s'est pas exécuté parce qu'il n'y avait pas suffisamment de RAM contiguë. Le système avait acquis de la RAM et l'avait fragmentée, la rendant ainsi irrécupérable.
2. Dans l'affirmative, existe-t-il une méthode légère de défragmentation du DMA - sans recourir à un redémarrage du système?
Il s'avère qu'il n'y a aucun moyen de compacter la mémoire, à moins de redémarrer le système embarqué. Dans le cas d'un système sans MMU, la prévention est le nom du jeu.
Une partie de moi se demande s'il est possible de pirater le noyau Linux pour émuler la MMU dans le logiciel. Je suppose que si c'était possible, quelqu'un l'aurait déjà fait. Je ne peux pas imaginer que c'est un concept entièrement nouveau;)
3. Comment puis-je empêcher que cela se produise à l'avenir?
Pour ce projet, j'utilisais cron pour lancer manuellement le programme chaque fois qu'il était nécessaire. Une bien meilleure façon de procéder consiste à appeler le programme au démarrage, puis à le forcer à s'endormir jusqu'à ce qu'il soit nécessaire. De cette façon, la mémoire n'a pas besoin d'être allouée à chaque utilisation. Réduisant ainsi la fragmentation.
Lors de la première itération du projet, nous nous sommes appuyés sur mes appels de script shell pour effectuer des fonctions critiques (telles que rm). Nous n'avons pas vu la nécessité de réinventer la roue si nous n'en avions pas besoin.
Cependant, je recommanderais d'éviter le shell autant que possible pour un système sans MMU -
( Question , que se passe-t-il si vous exécutez
ls -la /path/to/directory/ | grep file-i-seek
?)( Réponse : il démarre un nouveau sous-processus)
Si vous devez implémenter certaines des fonctionnalités de base du script shell dans votre programme C, je vous recommande de vérifier le code source utilisé dans BusyBox . Il y a de fortes chances que vous utilisiez C dans votre système embarqué.
la source