Sie sind auf Seite 1von 13

IMPLEMENTACIN

DE LA GESTIN DE
MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos
2 DGIIM

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

NDICE

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM

1. INTRODUCCIN ........................................................................................................................ 3
2. EL TRATAMIENTO DE LA MEMORIA EN LINUX ........................................................................ 4
3. LAS PGINAS ............................................................................................................................. 4
4. LAS ZONAS ................................................................................................................................ 5
5. FUNCIONES EN MEMORIA........................................................................................................ 6
6. LA FUNCIN kmalloc ................................................................................................................ 6
7. LA FUNCIN vmalloc ................................................................................................................ 7
8. EL SLAB LAYER ........................................................................................................................... 7
9. ASIGNACIONES ESTTICAS EN LA PILA .................................................................................... 9
10. PROYECCIONES EN ALTA MEMORIA .................................................................................... 10
11. ASIGNACIONES POR CPU ...................................................................................................... 11
12. RESUMEN: LAS FUNCIONES PARA GESTIONAR LA MEMORIA ............................................ 13
13. CONCLUSIN......................................................................................................................... 13

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

1. INTRODUCCIN

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM

Las reservas y asignaciones de memoria en el ncleo o kernel no son tan fciles como
se realizan estos mismos procedimientos fuera de este. Esto se debe a que el ncleo carece de
lujos de los que puede disfrutar el espacio de usuario. A diferencia de este ltimo, el ncleo no
dispone siempre de la capacidad de reservar memoria con facilidad. Por ejemplo, no puede
tratar los errores con facilidad y con frecuencia no puede dormirse o pausar su
funcionamiento.
Debido a estas limitaciones, y a la necesidad de un esquema de asignacin de memoria
ligero, hacerse con memoria en el ncleo es bastante ms complicado que en el espacio de
usuario.
En las futuras pginas se discutirn los distintos mtodos utilizados para obtener
memoria dentro del ncleo. Antes de profundizar en todas estas funciones disponibles
actualmente, tambin se tendr que entender cmo maneja el ncleo de Linux la memoria.

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM

2. EL TRATAMIENTO DE LA MEMORIA EN LINUX

El tratamiento de la memoria en Linux es una de las partes ms complejas y a la par


importantes en la estructura del ncleo. Se caracteriza por la fuerte necesidad de cooperacin
entre el procesador y el ncleo puesto que las tareas a realizar requieren de su correcta
colaboracin.
La implementacin de la gestin de memoria cubre muchas reas: la gestin de
pginas fsicas en memoria, los distintos mecanismos de asignacin de bloques de memoria, el
espacio de direcciones de los procesos, etc.

3. LAS PGINAS
El ncleo trata las pginas fsicas como la unidad bsica de la gestin de memoria. A
pesar de que la unidad mnima direccionable del procesador es normalmente un byte, o una
palabra en general, la unidad de gestin de memoria (MMU) con frecuencia maneja pginas.
Por tanto, la MMU mantiene las tablas de paginacin del sistema con nivel de tamaos de
pgina. En lo relativo a la memoria virtual, las pginas son la menor unidad significativa.
Cada arquitectura define su propio tamao de pgina. Muchas de ellas incluso admiten
varios tamaos distintos. La mayora de arquitecturas de 32 y 64 bits presentan tamaos de 4
y 8 KB, respectivamente.
El kernel de Linux representa todas las pginas del sistema definiendo la estructura
page (struct page), definida en la biblioteca <linux/mm_types.h>. En la estructura
podemos destacar los siguientes elementos:
unsigned long flags: Este campo almacena el estado de la pgina. Entre estos
flags se incluyen, por ejemplo, si la pgina est bloqueada en memoria. La variable admite 32
flags distintos activados simultneamente.
atomic_t _count: Este campo almacena el nmero de referencias que hay a la
pgina. Esta variable es negativa cuando no se est usando la pgina, en cuyo caso estara
disponible para una nueva asignacin de memoria.
void *virtual: Este campo apunta a la direccin virtual de la pgina.
Normalmente, es simplemente la direccin de la pgina en la memoria virtual.
La estructura page representa pginas fsicas, no virtuales. El ncleo utiliza esta
estructura de datos para describir la pgina fsica asociada, no los datos contenidos en su
interior. Con la estructura, el ncleo realiza un seguimiento de todas las pginas del sistema,
puesto que necesita conocer si una pgina est libre (no asignada). Y, en caso de no estarlo,
necesita saber quin es su propietario. Entre los posibles propietarios se incluyen los procesos
de espacios de usuario, datos del ncleo asignados dinmicamente, cdigo esttico del ncleo,
etc. Aunque en un primer momento se pueda pensar que se utiliza una gran cantidad de

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM
memoria para asignar a cada pgina una struct page, observando detenidamente nos
percatamos de que la proporcin respecto a la memoria fsica del sistema es minscula.

4. LAS ZONAS
Debido a las limitaciones del hardware, el kernel no puede tratar a todas las pginas
de la misma forma. Debido a esto, divide las pginas en diferentes espacios, que denominamos
zonas. El ncleo usa estas zonas para agrupar pginas con propiedades en comn. En
particular, Linux tiene que ocuparse de dos defectos del hardware relacionados con el
direccionamiento a memoria. Por un lado, algunos dispositivos hardware pueden realizar un
acceso directo a memoria solo en determinadas direcciones. Por otro lado, algunas
arquitecturas pueden direccionar fsicamente mayores cantidades de memoria de lo que lo
hacen virtualmente, y por tanto, hay memoria que no est permanentemente asignada en el
espacio de direcciones del ncleo.
Debido a estas restricciones, Linux cuenta con cuatro zonas de memoria principales:
- ZONE_DMA: contiene las pginas que pueden someterse a un acceso directo a memoria.
- ZONE_DMA32: Como la anterior, pero solo accesible para dispositivos de 32-bit.
- ZONE_NORMAL: Contiene las pginas normales, que son asignadas con regularidad.
- ZONE_HIGHMEM: Contiene las pginas que no se asignan permanentemente al espacio de
direcciones del ncleo.
El uso y la disposicin actual de las zonas de memoria depende de la arquitectura. Por
ejemplo, algunas arquitecturas no necesitan de zona DMA al no tener problemas para realizar
el acceso directo a memoria en cualquier direccin de memoria.
Linux divide en zonas las pginas del sistema para tener un lugar comn donde realizar
las asignaciones necesitadas. As, a la hora de asignar, al ncleo le basta con tomar el nmero
de pginas necesarias de la zona conveniente. Las zonas no tienen ninguna relevancia fsica,
sino que son simplemente agrupaciones lgicas usadas por el ncleo para llevar la cuenta de
las pginas.
Aunque algunas asignaciones requieren las pginas de alguna zona particular, otras
podran tomar las pginas de varias zonas posibles, pero nunca mezclando las pginas de
ambas zonas. Por ejemplo, una asignacin normal, en lugar de en la zona normal, se podra
realizar sobre pginas del DMA. En ningn caso se tomaran a la vez pginas de ambas zonas.
Evidentemente, el ncleo optara en la mayora de los casos para este ejemplo por usar la zona
normal, para reservar las de la zona DMA a aquellas que realmente lo necesiten.
Cada zona se representa con la estructura struct zone, definida en
<linux/mmzone.h>. Los campos ms importantes de esta estructura son:

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM
- spinlock_t lock: es un bloqueo que protege la estructura de accesos concurrentes.
Protege solo la estructura, no las pginas que se encuentran en la zona.
- const char *name: cadena terminada en null representando el nombre de la zona.

5. FUNCIONES EN MEMORIA
A continuacin vamos a ver las distintas interfaces que se implementan en el ncleo
para asignar y liberar memoria dentro del mismo. El ncleo proporciona un mecanismo de
bajo nivel para solicitar memoria, junto con varias interfaces para acceder a l. Todas estas
interfaces asignan memoria a nivel de tamaos de pgina y estn declaradas en <linux/gfp.h>.
La funcin esencial es struct page * alloc_pages(gfp_t gfp_mask, unsigned int order). Esta
funcin reserva 2 pginas fsicas contiguas y devuelve un puntero a la primera estructura
reservada. En caso de error, el puntero es nulo. La pgina dada se puede convertir a su
direccin lgica con la funcin void * page_address(struct page *page), que devuelve un
puntero a la direccin lgica correspondiente. Tambin es posible obtener pginas rellenas de
ceros (todos los bit desactivados), lo cual es til para asegurar que no se compromete la
seguridad del sistema. Para eso tenemos la funcin unsigned long get_zeroed_page(unsigned
int gfp_mask).

A la hora de liberar las pginas utilizadas, el kernel dispone de una familia de funciones,
entre las que destacan: void __free_pages(struct page *page, unsigned int order); void
free_pages(unsigned long addr, unsigned int order); void free_page(unsigned long addr);

Solo se deben liberar las pginas que han sido asignadas previamente.

6. LA FUNCIN kmalloc
La funcin kmalloc()es similar a la conocida funcin malloc()del espacio de usuario.
Con la excepcin de un parmetro adicional de flags. Es una interfaz simple para obtener
memoria en el ncleo en bloques de tamao de bytes. Su prototipo es: void * kmalloc(size_t
size, gfp_t flags). Devuelve un puntero a una direccin de memoria que tiene al menos la
cantidad de bytes especificada de longitud. La regin de memoria asignada est contigua
fsicamente en memoria. En caso de error se devuelve un puntero nulo.

Los flags que se pueden especificar en todas las funciones anteriores vienen definidos
como unsigned int, y se dividen en tres categoras: modificadores de accin,
modificadores de zona y tipos. Los modificadores de accin especifican cmo debe el ncleo
reservar la memoria solicitada. Los modificadores de zona especifican desde dnde se debe
asignar la memoria. Finalmente, los flags de tipo permiten simplificar la especificacin de
mltiples modificadores.

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM
El mtodo contrario a kmalloc es void kfree(const void *ptr). Esta funcin libera un
bloque de memoria que previamente ha sido reservado por kmalloc . No se debe llamar a esta
funcin sobre memoria que no ha sido reservada o que ya ha sido liberada, ya que se podra
traducir en comportamientos extraos del sistema sobre la memoria.

7. LA FUNCIN vmalloc
La funcin vmalloc funciona de forma similar a kmalloc, con la diferencia de que solo
asigna memoria que se encuentra virtualmente contigua y no necesariamente contigua
fsicamente. Hace esto asignando principalmente cantidades de memoria fsica no contiguas y
arreglando las tablas de paginacin para formar un bloque contiguo del espacio de direcciones
lgicas.
En su mayora, solo los dispositivos hardware requieren asignaciones en memoria
fsica contigua. En consecuencia, cualquier regin de memoria con la que puedan trabajar los
dispositivos hardware debe aparecer como un bloque fsicamente contiguo y no meramente
virtual. Los bloques de memoria usados solo por el software son receptivos en el uso de
memoria que solo se encuentra contigua virtualmente. Al programar no se aprecia la
diferencia: toda la memoria se presenta en el ncleo como lgicamente contigua.
A pesar de que la memoria fsicamente contigua solo se requiere en ciertos casos, la
mayor parte del ncleo recurre a la funcin kmalloc para obtener memoria. El prototipo de
esta nueva funcin es: void * vmalloc(unsigned long size). Su funcionamiento es anlogo al
de la funcin malloc del espacio de usuario. Para liberar una asignacin realizada con esta
funcin, se utiliza void vfree(const void *addr).

8. EL SLAB LAYER
La reserva y liberacin de memoria es una de las operaciones ms comunes en
cualquier ncleo. Para facilitar estas operaciones, se introducen con frecuencia las
denominadas listas libres (free lists). Estas listas contienen un bloque de estructuras de datos
ya reservado y disponible para su uso. Cuando se requiere una nueva instancia de la
estructura, bastara con tomar una de las estructuras de la lista en lugar de reasignar la
cantidad suficiente de memoria necesaria. Cuando ya no se necesitan los datos, bastara con
volver a la lista libre en lugar de liberar la memoria.
Uno de los principales problemas de estas listas en el ncleo es que no se puede tener
un control global sobre ellas. Para remediar esto, el ncleo de Linux proporciona el
denominado slab layer. Este concepto acta como una capa genrica de almacenamiento de
estructuras de datos.
El slab layer trata de hacer uso de varios principios bsicos, entre los que destacan:
- Las estructuras de datos usadas frecuentemente tienden a ser reservadas y liberadas
luego. Resulta til que se almacenen en cach.

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM

- Las reservas y liberaciones frecuentes pueden causar fragmentaciones en la memoria.


Para prevenir esto, las listas libres se colocan contiguas. Al volver a la lista libre tras liberar los
datos, no se produce fragmentacin.

- Las listas libres proporcionan una actuacin mejorada durante reservas y liberaciones
frecuentes de memoria ya que un objeto liberado puede ser devuelto de forma inmediata a la
prxima asignacin en memoria.
- Si se est al tanto de conceptos como el tamao, el tamao de pgina o el tamao
total de cach se pueden tomar decisiones ms inteligentes.

El slab layer de Linux fue diseado e implementando teniendo en cuenta estas


premisas.

El slab layer reparte los diferentes objetos en grupos denominados cachs, cada uno
de los cuales almacena un tipo diferente de objeto. Hay una cach por tipo de objeto. Cada
cach se divide en bloques (slabs), compuestos por una o ms pginas contiguas fsicamente.
Normalmente, cada bloque tiene solo una pgina. Cada cach se compone de mltiples
bloques.

Cada bloque contiene cierto nmero de objetos, que son las estructuras de datos a
almacenar. Los bloques pueden encontrarse en tres estados distintos: vaco, lleno o parcial. Un
bloque lleno tiene todos sus objetos asignados en memoria. Un bloque vaco tiene todos sus
objetos libres. Un bloque parcial tiene objetos asignados y objetos libres. Cuando desde el
ncleo se solicita un nuevo objeto, se busca un bloque parcial para realizar la solicitud, si
existe. En caso de no existir, se realiza desde un bloque vaco. Si no existen, se crea un bloque
nuevo. Esta estrategia reduce la fragmentacin.

En cuanto a la implementacin, las cachs son representadas mediante una struct


kmem_cache. La estructura contiene tres listas, cada una con los distintos slabs (llenos, vacos y
parciales). Estas listas contienen todos los slabs asociados con la cach. La struct slab
representa cada slab. El slab layer crea nuevos slab interactuando con el asignador de pginas
a bajo nivel del ncleo y la funcin __get_free_pages. Esto se realiza en la funcin que tiene
como prototipo static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int
nodeid). Esta funcin reserva memoria suficiente para mantener el cach. El primer

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM
parmetro apunta a el cach especfico que necesita ms pginas. El segundo parmetro son
los flags requeridos en __get_free_pages. De forma anloga se libera la memoria con
kmem_freepages.

Una nueva cach es creada a travs de la funcin struct kmem_cache *


mem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void
El primer parmetro es una cadena almacenando el nombre de la cach. El
segundo parmetro es el tamao de cada elemento en la cach. El tercer parmetro es el
desplazamiento del primer objeto en el slab. Se hace para asegurar una alineacin
determinada en la pgina (normalmente basta con el valor 0). Los flags especifican
determinadas configuraciones opcionales que controlen el comportamiento del cach. El
ltimo parmetro es un constructor para la cach. En caso de xito, la funcin devuelve un
puntero a la cach creada. En caso contrario, devuelve un puntero nulo.

(*ctor)(void *)).

Para destruir una cach, se utiliza la funcin int kmem_cache_destroy(struct


kmem_cache *cachep). La funcin devuelve 0 si y solo si ha finalizado correctamente. En el
momento de la llamada a esta funcin debemos asegurarnos de que se dan las siguientes
condiciones: todos los slabs en la cach estn vacos, y que nadie accede a la cach durante la
llamada a la funcin.

Una vez la cach ha sido creada, se puede obtener un objeto a travs de la funcin
que devuelve un puntero
a un objeto de la cach pasada como argumento. Si no quedan objetos libres, se obtendrn
nuevas pginas mediante las funciones mencionadas previamente. Para liberar posteriormente
el objeto y devolverlo a su slab de origen, se usa la funcin void kmem_cache_free(struct
kmem_cache *cachep, void *objp), que marca el objeto pasado en el segundo argumento como
libre.
void * kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags),

9. ASIGNACIONES ESTTICAS EN LA PILA


En el espacio de usuario, muchas asignaciones de memoria podran haber ocurrido en
la pila puesto que muchas veces se sabe el tamao de la reserva a priori. El espacio de usuario
disfruta de una gran pila que crece dinmicamente, mientras que el ncleo no dispone de esta
ventaja, ya que las pilas en sus procesos son pequeas y fijas. Por otro lado, esto le permite al
ncleo minimizar el consumo de memoria.

El tamao de las pilas del ncleo para cada proceso depende de la arquitectura y de
una opcin en tiempo de compilacin. Histricamente, el ncleo ha tenido dos pginas por
proceso. Sin embargo, pronto se introdujo una opcin para cambiar el nmero de pginas por
proceso a una sola. Se debi a dos razones. La primera es que se reduce el consumo de

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM
memoria por proceso. La segunda y ms importante es que conforme va aumentando el
tiempo de actividad, se vuelve bastante difcil encontrar dos pginas contiguas fsicamente sin
asignar. La memoria fsica se fragmenta, y se hace ms costoso asignar nuevos procesos. Hay
una ltima complicacin que se simplifica al reducir a una pgina. Los manejadores de
interrupciones compartan la pila de los procesos interrumpidos. Con la reduccin a una
pgina, los manejadores de interrupciones pasaron a utilizar sus propias pilas.

El uso de la pila en el ncleo se debe minimizar en la medida de lo posible. En caso


contrario, podra darse un desbordamiento de pila de forma silenciosa, ya que el ncleo no
maneja su desbordamiento. A partir de aqu, el exceso de datos estropear todo aquello que
se encuentra a partir del final de la pila. Por tanto, en el ncleo siempre es mejor usar un
esquema de asignacin dinmica, como cualquiera de los mencionados anteriormente.

10.PROYECCIONES EN ALTA MEMORIA


Por definicin, las pginas en la alta memoria son aquellas que pueden no estar
proyectadas permanentemente en el espacio de direcciones del ncleo. Podran no tener una
direccin lgica.

Por ejemplo, en la arquitectura x86, toda la memoria fsica ms all de los 896 MB es
alta memoria y no se proyecta permanentemente ni automticamente en el espacio de
direcciones del ncleo, a pesar de que estos procesadores son capaces de direccionar hasta 4
GB de RAM fsica. Despus de ser reservadas, estas pginas deben proyectarse en el espacio
de direcciones lgicas del ncleo.

Para proyectar una pgina dada sobre el espacio de direcciones del ncleo se utiliza la
funcin void *kmap(struct page *page), declarada en <linux/highmem.h>. Esta funcin
funciona tanto en alta como baja memoria. Si la pgina pertenece a la baja memoria,
simplemente devuelve su direccin virtual. Si pertenece a la alta memoria, se crea una
proyeccin permanente y se devuelve su direccin. La funcin acta bien solo en el contexto
de procesos. Como el nmero de proyecciones permanentes es limitado, la alta memoria debe
ser desasignada cuando ya no se necesite. Esto se hace mediante la siguiente funcin, que
desasigna la pgina dada: void kunmap(struct page *page).

Cuando se debe crear una proyeccin pero el contexto actual no puede detenerse, el
ncleo proporciona proyecciones temporales. Estas son un conjunto de zonas reservadas que
pueden contener una proyeccin temporal. El ncleo puede proyectar automticamente una
pgina de alta memoria en uno de estas proyecciones reservadas. Una proyeccin temporal se
establece mediante la funcin void *kmap_atomic(struct page *page, enum km_type type). El
segundo parmetro es una enumeracin que describe el propsito de la proteccin. La

10

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM

proyeccin se deshace mediante la funcin void kunmap_atomic(void *kvaddr, enum km_type


type). Ninguna de estas funciones bloquea, por lo que pueden usarse en contexto de
interrupciones y en otros lugares que no se puedan reprogramar.

11.ASIGNACIONES POR CPU


Los sistemas modernos de multiprocesamiento simtrico utilizan los denominados
datos por CPU (del ingls per-CPU data), es decir, datos que son nicos a un procesador
determinado, de manera bastante amplia. Normalmente, los datos por CPU son almacenados
en un array. Cada elemento en el array se corresponde con un posible procesador en el
sistema. El nmero de procesador actual es el que da el ndice en el array.
No se requieren bloqueos al trabajar de esta forma puesto que los datos son exclusivos
al procesador que se est manejando. Si ningn otro procesador accede a estos datos, no
existe ningn problema de concurrencia, y el procesador actual puede acceder de forma
segura a los datos sin ningn bloqueo.
La apropiacin del ncleo es el nico problema con los datos por CPU. Genera los dos
siguientes problemas:
- Por un lado, si el cdigo a ejecutar es prioritario y es reasignado a otro procesador, el
ndice de acceso a los datos dejara de ser vlido, ya que est apuntando al procesador
equivocado.
- Si otra tarea tiene preferencia sobre nuestro cdigo, puede acceder a nuestros datos
por CPU en el mismo procesador.
Estos problemas se solucionan gracias a la llamada int get_cpu(), la cual nos devuelve
el nmero del procesador actual y adems anula la apropiacin del ncleo. Con la llamada
anloga put_cpu() se restablece esta apropiacin. Tambin est disponible la llamada
smp_processor_id() para obtener el nmero del procesador actual, pero esta no desactiva la
apropiacin del ncleo, luego no es segura para este tipo de movimientos.
La versin 2.6 del ncleo de Linux introdujo una nueva interfaz, conocida como percpu,
para la creacin y manipulacin de este tipo de datos. Esta interfaz simplifica mucho su
manejo. Todas las rutinas para este tipo de asignacin en memoria vienen declaradas en el
archivo de cabecera <linux/percpu.h>.
Definir una variable por CPU en tiempo de compilacin es bastante sencillo, mediante
la macro DEFINE_PER_CPU(type, name), que crea una instancia de una variable con el tipo y
nombre pasados como argumento. Tambin es posible la declaracin anticipada de variable
por CPU, gracias a la macro DECLARE_PER_CPU(type, name).
Las variables por CPU pueden manipularse gracias a las rutinas get_cpu_var y
La primera devuelve un l-valor (modificable) de la variable cuyo nombre se pasa
como argumento, en el procesador actual, y desactiva la apropiacin del ncleo, que es
restablecida por medio de la segunda funcin.
put_cpu_var.

11

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM
Tambin es posible obtener el valor de los datos por CPU de otro procesador, con la
funcin per_cpu, que admite como parmetros el nombre de la variable y el nmero del
procesador. Esta funcin debe ser usada cuidadosamente, pues no desactiva la apropiacin ni
proporciona ningn mecanismo de bloqueo. En este caso, al darse la situacin de que un
procesador intenta manipular los datos de otros procesadores, es necesario colocar bloqueos.

De la misma forma tambin tenemos la opcin de crear variables por CPU en tiempo
de ejecucin. El ncleo implementa un asignador dinmico de memoria para crear datos por
CPU. Estas rutinas crean instancias de la memoria requerida para cada procesador en los
sistemas. Las y macros ms destacadas, que vienen declaradas tambin en <linux/percpu.h>,
son void *alloc_percpu(type), void *__alloc_percpu(size_t size, size_t align) y void
free_percpu(const void *). La primera es una macro que reserva memoria para una instancia
del tipo dado en cada procesador del sistema. Es una simplificacin de la segunda funcin, que
reserva una cantidad de memoria especificada por los parmetros en cada procesador. La
ltima llamada libera los datos en todos los procesadores.
Las dos primeras llamadas para reservar memoria devuelven un puntero, que se usa de
forma indirecta para referirnos a los datos por CPU creados dinmicamente. El ncleo
proporciona las macros get_cpu_var y put_cpu_var. La primera devuelve un puntero a la
instancia especfica en los datos del actual procesador y desactiva la apropiacin del ncleo,
que se restablece con la segunda funcin.
Varios son los beneficios del uso de los datos por CPU. El primero es la reduccin de
las necesidades de bloqueos, cerrojos y otras estructuras similares. Segn la forma en que los
procesadores accedan a los datos por CPU podran incluso no llegar a necesitarse bloqueos
para nada. De hecho, un buen programador debe asegurarse de que cada procesador accede
solo a sus datos. Pero esto solo son consejos, y no hay restricciones sobre el uso de
procesadores en este caso.
En segundo lugar, los datos por CPU reducen la invalidacin de la cach. Esto ocurre
cuando los procesadores intentan mantener sus cachs sincronizadas. Si un procesador
manipula los datos de la cach de otro procesador, ese procesador debe vaciar o actualizar su
cach. Una invalidacin de la cach continuada causa estragos en el rendimiento del sistema.
El uso de datos por CPU reduce al mnimo los efectos negativos de la cach porque los
procesadores normalmente acceden solo a sus propios datos. La interfaz percpu proporciona
la seguridad de que el acceso a los datos de un procesador no afecte a la cach de otros
procesadores.
En consecuencia, el nico requerimento de seguridad para usar los datos por CPU es
deshabilitar la apropiacin del ncleo, cuyo coste es mucho menor que el de bloquear, y
adems es realizado automticamente en las interfaces ya vistas. Tambin este tipo de datos
puede ser utilizado con seguridad en contextos de procesos o interrupciones. La interfaz que
Linux proporciona para el manejo de datos por CPU, en resumen, es muy sencilla de utilizar, y
es susceptible de ser optimizada en el futuro.

12

IMPLEMENTACIN DE LA GESTIN DE MEMORIA EN LINUX

12.

Juan Luis Surez Daz


Sistemas Operativos - 2 DGIIM

RESUMEN: LAS FUNCIONES PARA GESTIONAR LA MEMORIA

A continuacin, se realizar un resumen con las principales funciones desarrolladas en


este tema para la asignacin de memoria y cundo deben ser utilizadas.
Cuando necesitemos pginas fsicas contiguas, debemos usar uno de los asignadores
de pginas a bajo nivel o la funcin kmalloc. Esta es la forma usual de reservar memoria en el
ncleo, y cmo normalmente reservaremos nuestra memoria.
Si queremos realizar reservas desde la alta memoria, debemos usar la funcin
Esta funcin devuelve una struct page. Como la alta memoria podra no ser
proyectada, la nica forma de acceder podra ser solo mediante dicha estructura. Para obtener
un puntero a memoria, tendremos que usar la funcin kmap para proyectar la alta memoria en
el espacio de direcciones lgicas del ncleo.
alloc_pages.

Cuando solo necesitemos pginas virtualmente contiguas, y no necesariamente fsicas,


usaremos la rutina vmalloc. Finalmente, cuando estemos creando y destruyendo muchas
estructuras de datos de tamao considerable, debemos considerar el establecer un slab layer,
que mantiene una cach con listas libres que pueden ser utilizadas cuando se requiere un
nuevo objeto, en lugar de hacer la correspondiente reserva de memoria.

13.CONCLUSIN
En conclusin, en este trabajo hemos tratado cmo maneja la memoria el ncleo o
kernel del Sistema Operativo Linux. Hemos visto varias unidades de categorizacin de la
memoria, como son los bytes, las pginas o las zonas. Tambin hemos visto diversos
mecanismos para obtener memoria, como los asignadores de pginas o el mecanismo del slab
layer. Obtener memoria en el ncleo no es siempre fcil porque se debe ser cuidadoso con las
condiciones a las que est sometido el ncleo, que deben ser respetadas. Para terminar, queda
claro que la relativa dificultad para hacerse con memoria en el ncleo es una de las mayores
diferencias entre este y el desarrollo en espacios de usuario.

13