next up previous
Next: About this document Up: Sistemas Operativos Control 2 Previous: Parte II

Pregunta 2

En Unix, se quiere implementar la primitiva del kernel fork() en base a copia de la tabla de páginas, marcando el espacio compartido como copy-on-access). Esto significa que las páginas se copian a medida que se referencian (sean en lectura o escritura). Suponga que ya tiene un sistema de memoria virtual implementado, y el código del manejador de faltas de página es:

PageFault(PAGETABLE *pagetable, int page)
{
    fr = FindFreeFrame();
    swapin(pagetable->page_array[page]->disk, fr);
    pagetable->page_array[page]->invalid = FALSE;
    pagetable->page_array[page]->swapout = FALSE;
    pagetable->page_array[page]->frame = fr;
    return;
}

La función que se propone, para copiar la tabla de páginas para fork() es:

PAGETABLE *CopyPageTable(PAGETABLE *pagetable)
{
    PAGETABLE *new;
    int i;

    new = kalloc(sizeof(PAGETABLE));
    new->page_array = kalloc(pagetable->size * sizeof(void *));
    new->size = pagetable->size;
   
    for(i=0; i < pagetable->size; i++) {
       new->page_array[i] = pagetable->page_array[i];
       pagetable->page_array[i]->ref_cnt++;
       pagetable->page_array[i]->copy_on_access = TRUE;
       pagetable->page_array[i]->invalid = TRUE;
    }
}

Que copia toda la tabla que recibe de parámetro, compartiendo las páginas. Las páginas quedan marcadas como copy-on-access y se les incrementa un contador de referencias para indicar cuantos procesos las comparten.

Modifique el código de PageFault para que implemente el copy-on-access. Agregue los campos y las funciones que estime razonables. Suponga que siempre hay marcos disponibles en memoria y también en el swap. Implemente un esquema en que la memoria es un cache del swap.

La idea es crear copias de las páginas hasta que el contador de referencia sea 1, en cuyo caso hay que eliminar la marca de copy-on-access no más. El único bit implementado por el hardware es el de inválido.

Puede suponer la existencia de las siguientes funciones:

FindFreeSwapFrame();       /* Busca frame libre en el swap */
copy_page(frame1, frame2); /* copia pagina en memoria de frame1 a frame2 */
PageFault(PAGETABLE *pagetable, int page)
{
    fr = FindFreeFrame();
    if( pagetable->page_array[page]->copy_on_access && 
	pagetable->page_array[page]->ref_cnt > 1 )
      {
        new_disk = FindFreeSwapFrame();
	if(pagetable->page_array[page]->swapout)
	   swapin(pagetable->page_array[page].disk, fr);
	else
	   copy_page(pagetable->page_array[page].frame, fr);

	pagetable->page_array[page]->ref_cnt--;

 	pagetable->page_array[page] = kalloc(sizeof(pagedesc));
	pagetable->page_array[page]->ref_cnt = 1;
	pagetable->page_array[page]->frame = fr;
	pagetable->page_array[page]->disk = new_disk;
	pagetable->page_array[page]->swapout = FALSE;
	pagetable->page_array[page]->invalid = FALSE;
      }
    else
      {
	swapin(pagetable->page_array[page]->disk, fr);
	pagetable->page_array[page]->invalid = FALSE;
	pagetable->page_array[page]->copy_on_access = FALSE;
	pagetable->page_array[page]->swapout = FALSE;
	pagetable->page_array[page]->frame = fr;
      }
    return;
}


José M. Piquer
Sat Oct 23 20:21:27 CLST 1999