Le kernel met la mémoire à zéro?

J’utilise Debian Squeeze et j’ai remarqué que la mémoire est toujours mise à zéro. Est-ce nouveau dans les dissortingbutions linux? Il y a quelque temps, je pense que je pourrais utiliser put () et garbage serait sorti.

Je lance ce programme de test plusieurs fois mais les résultats commentés sont toujours les mêmes. (J’ai randomize_va_space = 2 dans sysctl.conf, je sais donc que de la mémoire à différents emplacements est utilisée à chaque exécution.)

char *a = malloc(50000000); a[49999999] = '\0'; puts(a); // it outputs nothing since all are zeroes printf("%p\n", a); if(a[5000] == '\0') // this condition is always true { puts("It is a nul char."); } 

Est-il possible de rendre le système non nul en mémoire? Quelles options cette installation squeeze de Debian aurait-elle pu activer afin de toujours conserver la mémoire zéro?

Sur tout système d’exploitation moderne, la mémoire obtenue récemment contient des valeurs non nulles si la mémoire libérée précédemment par votre programme a été réutilisée par malloc . Lorsqu’une nouvelle mémoire est obtenue à partir du système d’exploitation (kernel), elle est initialement purement virtuelle . Il n’a pas d’existence physique; au lieu de cela, il est mappé en tant que mappages de copie sur écriture d’une page de mémoire partagée unique remplie de 0 octet. La première fois que vous essayez d’écrire dessus, le kernel interrompt l’écriture, alloue une nouvelle page de mémoire physique, copie le contenu de la page d’origine (qui dans ce cas sont tous 0 octets) dans la nouvelle page, puis reprend votre programme. Si le kernel sait que la mémoire physique nouvellement allouée est déjà remplie de zéros, il pourra même optimiser l’étape de copie.

Cette procédure est à la fois nécessaire et efficace. Cela est nécessaire, car le transfert d’une mémoire susceptible de contenir des données privées du kernel ou des processus d’un autre utilisateur à votre processus constituerait une atteinte à la sécurité critique. C’est efficace car aucune réduction à zéro n’est effectuée au moment de l’allocation; les pages “remplies de zéro” font simplement référence à une page zéro partagée.

D’après ce que j’ai lu dans Linux Kernel Development, le kernel ne contient aucune page car il peut contenir des données du kernel qu’un programme utilisateur peut interpréter et accéder d’une certaine manière au système.

Malloc demande plus de pages au kernel. Le kernel est donc responsable de la mémoire que vous recevez.

La première fois que vous mallodez une mémoire de bloc, il y a de fortes chances qu’elle soit égale à zéro car la mémoire allouée par un appel système (sbrk, mmap) est mise à zéro par le kernel. Mais si vous libérez et malloc à nouveau, la mémoire est recyclée et peut ne pas contenir zéro.

Votre code ne teste pas si toute la mémoire est mise à zéro – il vérifie si deux octets spécifiques sont nuls – un [0] et un [5000]. De plus, malloc () n’a rien à voir avec le kernel – c’est une fonction de la bibliothèque C, pas un appel système. Il est hautement improbable que ses implémenteurs aient une mémoire zéro: ce que vous constatez n’est qu’un caprice aléatoire de votre configuration particulière.

Vous constaterez que la mémoire est mise à zéro sur la plupart des systèmes d’exploitation disposant d’une isolation entre les processus. La raison en est qu’un processus ne doit pas être autorisé à consulter la mémoire libérée par un autre processus. Par conséquent, une page mémoire doit être effacée entre le moment où il est libéré par un processus et celui où il est libéré par un autre processus. En pratique, effacé signifie mis à zéro et la mémoire est généralement mise à zéro au moment où elle est allouée par le processus.

Lorsque vous appelez malloc dans votre programme de jouets, la mémoire n’a encore été utilisée. Donc, c’est encore frais du kernel, plein de zéros. Si vous essayez un programme réel qui a déjà alloué et libéré beaucoup de blocs de tas, vous constaterez que la mémoire déjà utilisée par votre processus contient toujours les déchets que vous (ou le système de gestion de la mémoire) ont pu y mettre.

Comme cela a déjà été illustré, la principale différence est la première atsortingbution de temps par rapport à l’ allocation . Si tu essayes:

 char *a, tst; do { a = malloc(50000000); a[49999999] = '\0'; printf("%50s\n%p", a, a); // it outputs nothing 1st, but bbbb.... 2nd tst = a[5000] memset(a, 'b', 50000000); free(a); } while (tst == '\0'); 

il vous imprimera deux lignes (très probablement, du moins si les pointeurs sont les mêmes).

Key est que le bloc de mémoire renvoyé par malloc() a un contenu indéfini . Il peut s’agir ou non de zéros et dépend de la façon dont le programme a alloué la mémoire par le passé (ou des fonctions de débogage de la mémoire utilisées).

Si vous voulez garantir le contenu, vous avez besoin de l’ calloc() ou explicite après affectation.

La garantie intégrité / séparation des données du système signifie par contre que tout espace d’adressage initial demandé par le système – que ce soit via sbrk() ou mmap(MAP_ANON) – doit être initialisé à zéro, car tout autre contenu de cet espace consisterait en une sécurité. violation.