FreeBSD VM system 2 - vm_object (shadowed) y vm_page
Para concluir con las estructuras de usadas en la administracion de memoria virtual en FreeBSD, llegamos hasta la parte final; vm_object y vm_page
vm_object
Como se menciono en el anterior post “un vm_object es abstraccion del objeto que se esta mapenado en el rango de direcciones virtuales”. Esto representa una fuente de datos mapeada en el espacio de direcciones virtuales de un proceso, como memoria física, archivos o memoria compartida.
Cuando un proceso se ejecuta, su espacio de direcciones virtuales incluye diferentes tipos de vm_object, el código del programa en donde los datos iniciales se mapean desde el archivo binario (ejecutable), el código (seccion .text) es de solo lectura y los datos (seccion .data) son copy-on-write (COW), lo que significa que si el proceso intenta modificar esos datos, el sistema operativo crea una copia privada de la página para evitar modificar el archivo original, esto se menciono en el anterior post en la funcion VM_MAP_ENTRY_FOREACH, mas que nada en el uso de VM_INHERIT_COPY.
La sección BSS (datos no inicializados) se asigna como páginas de memoria anonima (VM_INHERIT_ZERO), que son páginas llenas de ceros cuando se acceden por primera vez (se le conoce como Demand Zero Page Fill). También se pueden mapear archivos arbitrarios como memoria compartida, donde cada proceso puede tener una copia privada o una referencia compartida al archivo.
Cuando un proceso hace un fork(), el sistema operativo no crea una copia completa del espacio de direcciones si no que reutiliza las páginas existentes y las marca como copy-on-write, de modo que si uno de los procesos modifica una página, se crea una copia privada solo para ese proceso, lo que permite ahorrar memoria y mejorar el rendimiento, ya que solo las páginas modificadas realmente se copian, mientras que las páginas de solo lectura o sin modificaciones siguen siendo compartidas entre ambos procesos
Otros puntos importante a tomar en cuenta
- Cada estructura
vm_objectcontiene una lista ordenada de estructurasvm_pageque representan la cache de memoria física delvm_object - Si el vm_object entre dos procesos es privado o COW, se pueden crear cadenas de objetos o como correctamente se les dice “shadow objects”
La forma en la que se estructura es la siguiente
struct vm_object {
struct rwlock lock;
TAILQ_ENTRY(vm_object) object_list; /* list of all objects */
LIST_HEAD(, vm_object) shadow_head; /* objects that this is a shadow for */
LIST_ENTRY(vm_object) shadow_list; /* chain of shadow objects */
struct pglist memq; /* list of resident pages */
struct vm_radix rtree; /* root of the resident page radix trie*/
vm_pindex_t size; /* Object size */
struct domainset_ref domain; /* NUMA policy. */
volatile int generation; /* generation ID */
int cleangeneration; /* Generation at clean time */
volatile u_int ref_count; /* How many refs?? */
int shadow_count; /* how many objects that this is a shadow for */
vm_memattr_t memattr; /* default memory attribute for pages */
objtype_t type; /* type of pager */
u_short pg_color; /* (c) color of first page in obj */
u_int flags; /* see below */
blockcount_t paging_in_progress; /* (a) Paging (in or out) so don't collapse or destroy */
blockcount_t busy; /* (a) object is busy, disallow page busy. */
int resident_page_count; /* number of resident pages */
struct vm_object *backing_object; /* object that I'm a shadow of */
vm_ooffset_t backing_object_offset;/* Offset in backing object */
TAILQ_ENTRY(vm_object) pager_object_list; /* list of all objects of this pager type */
LIST_HEAD(, vm_reserv) rvq; /* list of reservations */
void *handle;
...
}
Observa que el segundo miembro del struct es una lista de “shadow objects”, pero ¿Que es eso?
shadow objects
En escencia son estructuras que se interponen entre un vm_object original y las entradas del mapa de direcciones (vm_map_entry) de los procesos, exactamente son usados en la implementacion de Copy-on-Write (COW) para permitir que varios procesos compartan el mismo vm_object y modifiquen una copia privada de ese objeto sin que afecte a los demas procesos, entonces podemos decir que
- Si un proceso hace fork(), el nuevo proceso hereda el
vm_map_entry, pero elvm_objectse convierte en COW, lo que creara unshadow objecten caso de que uno de ambos procesos requiera modificarlo. Desglosandolo a paso- Cuando se hce un fork, el padre el y el hijo comparten las mismas paginas de memoria
- Cuando uno de los procesos intenta modificar una de las paginas se activa COW
- Ahora se crea un shadow object para la pagina que sera modificada. Entonces la pagina original no se toca
Este mecanismo reduce la sobrecarga de memoria permitiendo aumentar la eficiencia.
Puntos clave
- Los shadow object representan copias de los datos originales
- Los shadow objects son transistorios, lo que indica que si ya no se usan se autodestruyen-
- Si uno de los procesos no requiere modificar las paginas de memoria, se puede seguir usando el mismo vm_object original
vm_page
De aqui no hay mucho que decir, ya que las vm_page son las estructuras de mas bajo nivel en la memoria virtual, y representan la memoria fisica que esta siendo usada por el sistema de memoria virtual de FreeBSD.
Puntos clave
- Cada vm_page hace referencia a una pagina fisica de la memoria fisica, esto se observa en el miebro
vm_paddr_t phys_addr;de su estructura. - Por cada pagina de memoria fisica de 4 Kb, habra una estructura
vm_page. - Un vm_object puede tener varias vm_page, esto se observa en el miembro
vm_object_t object;de la estructura
Referencias
- https://www.leidinger.net/FreeBSD/dox/vm/html/index.html
- https://docs-archive.freebsd.org/doc/6.2-RELEASE/usr/share/doc/en/articles/vm-design/vm-objects.html
- The Design and Implementation of the FreeBSD Operating System (2nd Edition)
- https://docs.freebsd.org/en/articles/vm-design/