2011-05-14 16 views
8

Estoy usando Debian squeeze y he notado que la memoria siempre se pone a cero. ¿Es esto nuevo en las distribuciones de Linux? Hace algún tiempo, creo que podría usar puts() y se generaría basura.Kernel pone a cero la memoria?

Ejecuto este programa de prueba muchas veces, pero los resultados comentados son siempre los mismos. (Tengo randomize_va_space = 2 en sysctl.conf así que sé que la memoria en diferentes lugares se está utilizando en cada ejecución.)


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."); 
}

¿Es posible hacer que el sistema de memoria no cero? ¿Qué opciones podría haber activado esta instalación Debian squeeze que siempre no tiene memoria?

Respuesta

1

Su código no prueba si toda la memoria está puesta a cero; prueba si dos bytes específicos son cero, a [0] y a [5000]. Además, malloc() no tiene nada que ver con el kernel; es una función de biblioteca C, no una llamada al sistema. Es muy poco probable que sus implementadores tengan memoria cero; lo que está viendo es solo una peculiaridad aleatoria de su configuración particular.

7

Según lo que he leído en Linux Kernel Development, el kernel no tiene páginas porque puede contener datos del kernel que un programa de usuario podría interpretar y de alguna manera obtener acceso al sistema.

malloc le pide al kernel más páginas, por lo que el núcleo es responsable de la memoria que está recibiendo.

+0

De acuerdo con esta página de WP sobre las funciones de brk/sbrk: http://en.wikipedia.org/wiki/Sbrk usted tiene razón. Pero esto parece un desperdicio de cosas para el kernel. –

+2

¿Por qué? Parece una cosa inteligente para un programa. Si tiene un programa muy estúpido que contiene datos estúpidos sin cifrar y luego simplemente muere sin tener que hacerlo de forma gratuita, podría escribir un programa para aprovecharlo. Sin embargo, estoy bastante seguro de que puedes deshabilitar cuando compilas un kernel. –

+0

"Desactivarlo"? Definitivamente no hay forma de hacer que un kernel pierda datos en el espacio de usuario a través de las opciones normales; tendrías que romperlo intencionalmente para hacer eso. Debido al hecho de que las páginas nuevas son referencias COW de la página cero, no hay un "caso predeterminado" que pueda tener fugas. –

3

La primera vez que malloc un trozo de memoria hay una buena posibilidad de que sea cero porque la memoria asignada por una llamada al sistema (sbrk, mmap) se pone a cero por el kernel. Pero si vuelve a liberar y malloc, la memoria se recicla y puede que no contenga cero.

1

Encontrará que la memoria está puesta a cero en la mayoría de los sistemas operativos que tienen aislamiento entre procesos. La razón es que no se debe permitir que un proceso eche un vistazo a la memoria liberada por otro proceso, por lo que una página de memoria debe borrarse entre el momento en que es liberado por un proceso y el momento en que otro proceso lo libera. En la práctica, borrado significa cero, y la memoria generalmente se pone a cero en el momento en que el proceso lo asigna.

Cuando llama al malloc en su programa de juguetes, la memoria no se ha utilizado para nada más. Por lo tanto, todavía está recién salido del kernel, lleno de ceros. Si intentas en un programa real que ya está asignado y liberado una gran cantidad de bloques de almacenamiento dinámico, encontrarás que la memoria que ya ha sido utilizada por tu proceso aún contiene cualquier basura que tú (o el sistema de administración de memoria) haya puesto ahí.

16

En cualquier sistema operativo moderno, la única forma en que la memoria recién obtenida contendrá valores distintos de cero es si la memoria previamente liberada por su programa se reutilizó en malloc. Cuando se obtiene una nueva memoria del sistema operativo (kernel), inicialmente es puramente virtual. No tiene existencia física; en su lugar, se asigna como asignaciones de copia sobre escritura de una única página de memoria compartida que está llena de 0 bytes. La primera vez que intente escribir en él, el núcleo atrapará la escritura, asignará una nueva página de memoria física, copiará el contenido de la página original (que en este caso son todos 0 bytes) a la página nueva, y luego reanudará tu programa Si el kernel sabe que la memoria física recién asignada ya está llena de cero, incluso podría optimizar el paso de copiado.

Este procedimiento es necesario y eficiente. Es necesario porque la entrega de la memoria que podría contener datos privados del kernel u otros procesos de un usuario a su proceso sería una violación de seguridad crítica. Es eficiente porque no se realiza la puesta a cero en el momento de la asignación; las páginas "llenas a cero" son solo referencias a una página cero compartida.

+0

Hay un hilo en Windows cuyo trabajo es poner a cero las páginas físicas no utilizadas para proporcionar un grupo de páginas nuevas que se pueden mapear de forma segura en el espacio de usuario. (En comparación, el kernel puede asignar páginas sin cero para su propio uso). – Neil

+0

Sin embargo, los desarrolladores del kernel deben asegurarse de que los datos en sus páginas de memoria "no puestas a cero" no se filtren a ningún proceso en modo usuario. Además, dado que la memoria se pone a cero en el fondo, hay un impacto mínimo en el sistema, a menos que haya una significativa pérdida de memoria. Pero revolverse en la memoria es probablemente un problema de rendimiento independientemente de la puesta a cero. – Brian

1

Como ya se ha ilustrado, la diferencia clave es primera asignación de tiempo vs asignación. Si intenta:

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'); 

que te imprimir dos líneas (lo más probable, al menos si los punteros son los mismos).

La clave es que el bloque de memoria devuelto por malloc() tiene contenido indefinido. Puede o no ser ceros, y depende de cómo el programa ha asignado la asignación de memoria en el pasado (o qué recursos de depuración de memoria se usan).

Si desea garantizar contenidos, necesita calloc() o inicialización explícita después de la asignación.

garantía separación integridad/de datos del sistema por otra parte significa que cualquier espacio inicial dirección solicitada por el sistema - ya sea a través sbrk() o mmap(MAP_ANON) - debe ser inicializado a cero, como cualquier otro contenido de tales consistirían en una violación de la seguridad.

Cuestiones relacionadas