Pregunta

Busqué en Google y encontré que la mayoría de las personas abogaban por el uso de kmalloc, ya que tiene la garantía de obtener bloques físicos de memoria contiguos.Sin embargo, también parece que kmalloc puede fallar si un contiguo físico No se puede encontrar el bloque que deseas.
¿Cuáles son las ventajas de tener un bloque de memoria contiguo?Específicamente, ¿por qué necesitaría tener un contiguo? físico bloque de memoria en un llamada al sistema?¿Hay alguna razón por la que no pueda simplemente 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 manejadores de interrupción, mitades inferiores y otras situaciones en las que no puede dormir.

GFP_KERNELEsta es una asignación normal y podría bloquearse.Este es el indicador de usar en el código de contexto de proceso cuando es seguro dormir.

¿Fue útil?

Solución

Solo debe preocuparse por el uso de 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 núcleo, realmente no puede saber adónde irá.Incluso si el kernel no usa el buffer para DMA hoy, un desarrollo futuro podría hacerlo.

vmalloc suele ser más lento que kmalloc, porque es posible que tenga que reasignar el espacio del búfer en un rango prácticamente contiguo.kmalloc nunca reasigna, aunque si no se llama con GFP_ATOMIC kmalloc puede bloquear.

kmalloc está limitado en el tamaño del buffer que puede proporcionar:128 KB*).Si necesita un búfer realmente grande, debe usar vmalloc o algún otro mecanismo como reservar mucha memoria en el arranque.

*) Esto fue cierto para los núcleos anteriores.En kernels recientes (probé esto en 2.6.33.2), ¡el tamaño máximo de un solo kmalloc es de hasta 4 MB!(Escribí un bastante publicación detallada sobre esto.) — kaiwán

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 mediante una trampa, no es una interrupción.

Otros consejos

Respuesta corta:descargar Controladores de dispositivos Linux y lea el capítulo sobre gestión de memoria.

En serio, hay muchos problemas sutiles relacionados con la administración de la memoria del kernel que debes comprender; dedico gran parte de mi tiempo a depurar problemas con esto.

vmalloc() rara vez se usa 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, especialmente si está en un controlador de interrupciones, como sugirió.

Linux Kernel Development de Robert Love (Capítulo 12, página 244 en la tercera edición) responde a esto muy claramente.

Sí, en muchos de los 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 que cuando se asignan grandes fragmentos de memoria mediante vmalloc, el kernel tiene que asignar los fragmentos (páginas) físicamente no contiguos a una única región de memoria virtual contigua.Dado que la memoria es virtualmente contigua y físicamente no contigua, será necesario 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 del 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 recientes de direcciones virtuales a físicas) al acceder a este búfer.Esto puede llevar a paliza.

El kmalloc() & vmalloc() Las funciones son una interfaz simple para obtener memoria del kernel en fragmentos del tamaño de un byte.

  1. El kmalloc() La función garantiza que las páginas sean físicamente contiguas (y virtualmente contiguas).

  2. El vmalloc() La función funciona de manera similar a kmalloc(), excepto que asigna memoria que es sólo virtualmente contigua y no necesariamente físicamente contigua.

¿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 "Me siento afortunado" de Google en vmalloc:

kmalloc es la forma preferida, siempre que no necesite áreas muy grandes.El problema es que, si desea realizar 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 la memoria lo antes posible, antes de que la memoria se fragmente.

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 un desplazamiento constante) a la dirección física.Este mapeo directo garantiza que obtengamos una porción física contigua de RAM.Adecuado para DMA donde solo damos el puntero inicial y esperamos un mapeo físico contiguo posterior para nuestra operación.

vmalloc() devuelve la dirección virtual del kernel que, a su vez, podría no tener una asignación contigua en la RAM física.Útil para grandes asignaciones de memoria y en casos en los que no nos importa que la memoria asignada a nuestro proceso sea continua también en la RAM física.

Una de otras diferencias es que kmalloc devolverá una 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 (use la macro __pa para convertirlas).Esta propiedad implica que la memoria asignada es memoria continua.

Por otro lado, Vmalloc puede devolver direcciones virtuales desde "alta memoria".Estas direcciones no se pueden convertir en direcciones físicas de forma directa (debe utilizar la función virt_to_page).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top