Busqué en Google y encontré a la mayoría de las personas que abogan por el uso de kmalloc
, ya que está garantizado que obtendrá bloques de memoria físicos contiguos. Sin embargo, también parece que kmalloc
puede fallar si no se puede encontrar un bloque físico contiguo que desea.
¿Cuáles son las ventajas de tener un bloque de memoria contiguo? Específicamente, ¿por qué necesitaría tener un bloque físico de memoria contiguo en una llamada al sistema ? ¿Hay alguna razón por la que no pueda usar vmalloc
?
Finalmente, si tuviera que asignar memoria durante el manejo de una llamada al sistema, ¿debería especificar GFP_ATOMIC
? ¿Se ejecuta una llamada al sistema en un contexto atómico?
GFP_ATOMIC
La asignación es de alta prioridad y no duerme. Esta es la bandera para usar en los manejadores de interrupciones, mitades inferiores y otras situaciones en las que no puede dormir.
GFP_KERNEL
Esta es una asignación normal y podría bloquearse. Esta es la bandera que se debe usar en el código de contexto del proceso cuando es seguro dormir.
fuente
vmalloc
es más rápido con Kernel 5.2 (Q2 2019)Respuestas:
Solo debe preocuparse por usar memoria físicamente contigua si un dispositivo DMA accederá al búfer en un bus con dirección física (como PCI). El problema es que muchas llamadas al sistema no tienen forma de saber si su búfer eventualmente se pasará a un dispositivo DMA: una vez que pasa el búfer a otro subsistema del kernel, realmente no puede saber a dónde irá. Incluso si el kernel no usa el búfer para DMA hoy, un desarrollo futuro podría hacerlo.
vmalloc es a menudo más lento que kmalloc, porque puede tener que reasignar el espacio de búfer en un rango virtualmente contiguo. kmalloc nunca reasigna, aunque si no se llama con GFP_ATOMIC, kmalloc puede bloquear.
kmalloc tiene un tamaño limitado de búfer que puede proporcionar: 128 KBytes *) . Si necesita un búfer realmente grande, debe usar vmalloc o algún otro mecanismo como reservar mucha memoria en el arranque.
Para una llamada al sistema, no necesita pasar GFP_ATOMIC a kmalloc (), puede usar GFP_KERNEL. No eres un manejador de interrupciones: el código de la aplicación ingresa al contexto del kernel por medio de una trampa, no es una interrupción.
fuente
Respuesta corta: descargue los controladores de dispositivo Linux y lea el capítulo sobre administración de memoria.
En serio, hay muchos problemas sutiles relacionados con la administración de la memoria del kernel que debe comprender; paso mucho tiempo depurando problemas con él.
vmalloc () se usa muy raramente, porque el kernel rara vez usa memoria virtual. kmalloc () es lo que se usa normalmente, pero debe saber cuáles son las consecuencias de los diferentes indicadores y necesita una estrategia para lidiar con lo que sucede cuando falla, particularmente si está en un controlador de interrupciones, como sugirió.
fuente
El desarrollo del kernel de Linux por Robert Love (Capítulo 12, página 244 en la 3ª edición) responde a esto muy claramente.
Sí, en muchos casos no se requiere memoria físicamente contigua. La razón principal por la que kmalloc se usa más que vmalloc en el kernel es el rendimiento. El libro explica, cuando se asignan grandes trozos de memoria usando vmalloc, el kernel tiene que mapear los trozos (páginas) físicamente no contiguos en una única región de memoria virtual contigua. Dado que la memoria es virtualmente contigua y físicamente no contigua, se deberán agregar varias asignaciones de direcciones virtuales a físicas a la tabla de páginas. Y en el peor de los casos, habrá (tamaño de búfer / tamaño de página) número de asignaciones agregadas a la tabla de páginas.
Esto también agrega presión sobre TLB (las entradas de caché que almacenan asignaciones de direcciones virtuales a físicas recientes) al acceder a este búfer. Esto puede provocar una paliza .
fuente
Las funciones
kmalloc()
&vmalloc()
son una interfaz simple para obtener la memoria del kernel en fragmentos del tamaño de un byte.La
kmalloc()
función garantiza que las páginas sean físicamente contiguas (y virtualmente contiguas).La
vmalloc()
función funciona de manera similar akmalloc()
, excepto que asigna memoria que es solo virtualmente contigua y no necesariamente contigua físicamente.fuente
¿Cuáles son las ventajas de tener un bloque de memoria contiguo? Específicamente, ¿por qué necesitaría tener un bloque físico de memoria contiguo en una llamada al sistema? ¿Hay alguna razón por la que no pueda usar vmalloc?
De "I'm Feeling Lucky" de Google en
vmalloc
:kmalloc es la forma preferida, siempre que no necesite áreas muy grandes. El problema es que si desea hacer DMA desde / hacia algún dispositivo de hardware, necesitará usar kmalloc, y probablemente necesitará una porción más grande. La solución es asignar memoria lo antes posible, antes de que se fragmente.
fuente
En un sistema de 32 bits, kmalloc () devuelve la dirección lógica del kernel (aunque es una dirección virtual) que tiene la asignación directa (en realidad con desplazamiento constante) a la dirección física. Este mapeo directo asegura que obtenemos una porción física contigua de RAM. Adecuado para DMA donde damos solo el puntero inicial y esperamos un mapeo físico contiguo a partir de entonces para nuestra operación.
vmalloc () devuelve la dirección virtual del kernel que, a su vez, podría no tener un mapeo contiguo en la RAM física. Útil para una gran asignación de memoria y en los casos en los que no nos importa que la memoria asignada a nuestro proceso sea continua también en la RAM física.
fuente
Una de las otras diferencias es que kmalloc devolverá la dirección lógica (de lo contrario, especifique GPF_HIGHMEM). Las direcciones lógicas se colocan en "memoria baja" (en el primer gigabyte de memoria física) y se asignan directamente a direcciones físicas (utilice la macro __pa para convertirla). Esta propiedad implica que la memoria kmalloced es una memoria continua.
Por otro lado, Vmalloc puede devolver direcciones virtuales desde "memoria alta". Estas direcciones no se pueden convertir en direcciones físicas de forma directa (debe utilizar la función virt_to_page).
fuente