0% encontró este documento útil (0 votos)
13 vistas116 páginas

Introducción a Sistemas Operativos y Hardware

El documento describe los conceptos básicos de hardware y sistemas operativos, incluyendo procesadores, memoria, E/S, procesos, planificación, concurrencia y gestión de memoria. Explica las interrupciones hardware y cómo el sistema operativo las maneja para cambiar entre procesos.

Cargado por

F. Montes
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
13 vistas116 páginas

Introducción a Sistemas Operativos y Hardware

El documento describe los conceptos básicos de hardware y sistemas operativos, incluyendo procesadores, memoria, E/S, procesos, planificación, concurrencia y gestión de memoria. Explica las interrupciones hardware y cómo el sistema operativo las maneja para cambiar entre procesos.

Cargado por

F. Montes
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Lucila Canalini

Sistemas Operativos

Introducción al Hardware ................................................................................................................... 2


Introducción a Sistemas Operativos ................................................................................................... 5
Sistemas monoprogramados vs. Sistemas multiprogramados ........................................................... 7
Programa ............................................................................................................................................. 7
Procesos .............................................................................................................................................. 8
Hilos ................................................................................................................................................... 14
Planificación de CPU .......................................................................................................................... 19
Arquitectura de Kernel ...................................................................................................................... 31
Concurrencia ..................................................................................................................................... 33
Deadlock ............................................................................................................................................ 40
Livelock .............................................................................................................................................. 47
Memoria real ..................................................................................................................................... 47
Memoria virtual................................................................................................................................. 62
File System ........................................................................................................................................ 76
File Allocation Table (FAT) ................................................................................................................. 94
Unix File System (ext2/ext3) (UFS) .................................................................................................... 97
FAT vs. UFS ...................................................................................................................................... 102
Entrada/Salida ................................................................................................................................. 104

1
Lucila Canalini

03/04/2020

Introducción al Hardware
El procesador está compuesto por: registros, la unidad aritmética lógica (UAL), la cache, etc.

 Registros visibles: Son los que el usuario puede manipular de manera directa.
 Registros de control y estado: Suelen ser registros que nos permiten administrar y
mantener un buen mantenimiento del computador.

Elementos básicos de una computadora


La memoria RAM es aquella donde vamos a guardar todos los programas y datos que vamos a
estar usando mientras tenemos la computadora encendida. Todos los programas que se
ejecutan están en dicha memoria.
Módulo de entrada/salida donde se conectan todos los dispositivos externos a la
computadora. Una computadora sin módulos de entrada/salida no funcionaría para nada. Se
encarga de enviar las cosas provenientes de estos dispositivos hacia el procesador.
Todos estos elementos se conectan por el BUS.
Dentro del procesador hay un conjunto de registros. Estos pueden ser de uso general, visibles
al programador, o de control y estado (el PC, los flags, IR, etc.), que son para gestionar la
administración del sistema.
El program counter (PC) puede ser manipulado por hardware y software, y contiene la
dirección de la próxima instrucción a ser ejecutada.
El procesador tiene un set de instrucciones que se dividen en privilegiadas y no privilegiadas.
Las privilegiadas solo se pueden ejecutar en modo kernel, mientras que las no privilegiadas
pueden ser ejecutadas por el modo usuario también. Las segundas son las que pueden hacer
cualquier programador. Las primeras son preferentemente para que las haga el sistema
operativo y están relacionadas con cosas que pueden afectar a la computadora, por ejemplo,
intentar acceder a un dispositivo de entrada y salida.

Ciclo de instrucción
Una vez que una instrucción empieza a ejecutarse, no puede interrumpirse hasta el final. Los
pasos que se ejecutan dentro de una instrucción son: fetch, decode, execute.
Si tenemos un procesador podemos ejecutar un solo programa a la vez.
Para poder ejecutar un conjunto de instrucciones, una computadora debe cargar las
instrucciones del disco (I/O) solamente a memoria.

Interrupciones
Una interrupción es un mecanismo que tienen los dispositivos de hardware para cortar el flujo
de instrucción de un programa. Así, una vez atendida, implica siempre un cambio a modo
kernel, pero el programa que se estaba ejecutando y se interrumpió, no se entera de que fue
interrumpido.

2
Lucila Canalini

Se utilizan para cortar la ejecución de la secuencia actual de instrucciones para que el SO pueda
seguir haciendo cosas. Nos ayuda a hacer las cosas en “paralelo” aunque realmente no es así.
Son notificaciones de eventos dirigidas al procesador. Cualquier dispositivo de E/S puede
enviar interrupciones al procesador para que detenga lo que está haciendo y se ponga a hacer
otra cosa. Siempre estas notificaciones tienen de destino final el procesador.
Para atender una interrupción, es necesario, previamente guardar el estado de todos los
registros del procesador.
Después de ejecutar cada instrucción, antes de pasar a la siguiente, pregunta por un flag si hubo
alguna interrupción, y en caso positivo, se la atiende. Esto es porque una vez que se ejecuta la
instrucción, esta no se puede interrumpir mientras se está ejecutando.
Se pueden clasificar de varias maneras dependiendo de quien lo origino:
 Hardware (externas al procesador): Las que vienen de un dispositivo de E/S.
Por ejemplo: Un disco, una posición de memoria que se rompió.
 Software (internas al procesador): Se originan dentro del procesador como
consecuencia de la ejecución de una instrucción.
Por ejemplo: Hacer una división por 0.
 Enmascarables: Pueden no ser ejecutadas en el mismo instante.
Por ejemplo: Una lectura de disco, pero la computadora está haciendo algo más
importante, se puede postergar.
 No enmascarables: Se tienen que atender siempre.
Por ejemplo: Una falla de hardware no se puede pasar por alto (falla eléctrica, de
memoria, etc.), no puede postergarse.
 E/S.
 Fallas de Hardware: Falla cuando no se encuentre un dispositivo, por lo que no se
pueda usar.
 Clock: Reloj de la computadora. Dispositivo Hardware que nos interrumpe cada cierto
tiempo que podemos definir como sistema operativo.

Ciclo sin interrupciones:


El ciclo de instrucción consiste en las etapas de fetch (traer instrucción), decode (decodificar la
instrucción) y execute (ejecutar la instrucción). Al final se realiza un chequeo de la existencia
de interrupciones, y en caso de que exista alguna se llama al sistema operativo.

Ciclo con interrupciones:


El fetch busca la siguiente instrucción que se tiene que ejecutar a la memoria. En la memoria
están todas las instrucciones del programa que se tiene que ejecutar. Una vez ejecutada la
instrucción, se pregunta si las interrupciones están habilitadas o no, y de serlo, se atiende, y si
no, se vuelve a la etapa de fetch actualizando el valor del PC para que busque la siguiente
instrucción del programa.

3
Lucila Canalini

La interrupción se atiende siempre que se termina una ejecución. Luego de cada ciclo de
instrucción se valida si es que hay interrupciones por lo que se atenderá al finalizar de ejecutar
la instrucción en curso. Luego de atender la interrupción seguirá con la syscall.

¿Qué es lo que pasa cuando llega una interrupción?


1. Se genera una interrupción.
2. Finaliza la instrucción actual.
3. Se guarda PC y PSW (Procesador Status Word) del programa.
4. Se carga en PC la dirección del manejador de interrupciones.
5. Se guarda la información del procesador.
6. Procesa la interrupción.
7. Restaura información del procesador guardada.
8. Restaura PC y PSW.
Los primeros 5 puntos son los que pasan dentro del procesador. El procesador está programado
para que pasen esas cosas. Después de finalizar la instrucción, el procesador es el que pregunta
si hay interrupciones.
A partir de que el PC cambia de posición, empieza a funcionar el software.
La manipulación del program counter es algo que realiza el sistema operativo, para que, si
tenemos un programa abierto, podamos usar otro.
Caso específico: Interrupción de e/s finalizada
Cuando se está ejecutando un proceso y se produce una interrupción de entrada/salida
finalizada, frena la ejecución del proceso actual.
Al finalizar la instrucción actual se chequea si hay interrupciones pendientes. Se guarda el
contexto de ejecución del proceso actual en la pila del sistema operativo.
Se produce un cambio de modo usuario a modo kernel. Se pasa el control al gestor de
interrupciones del sistema operativo. El sistema operativo pasa el proceso bloqueado a la lista
de listos.
Suponiendo que el planificador de corto plazo no implica desalojo: Se cambia el modo de
ejecución de kernel a usuario y se restaura el contexto de ejecución del proceso original de la
pila del sistema.

4
Lucila Canalini

Técnicas de entrada/salida
 E/S programada.
 E/S por interrupciones.
 Acceso directo a memoria (DMA).

Jerarquía de memoria
Cuando hablemos de memoria nos referimos a la memoria RAM, pero todas las memorias
tienen tamaños y velocidades diferentes, aunque las utilizamos para tener un sistema de
memoria acorde al que necesitamos.
Memoria interna de la computadora:
 Registros de CPU: La que se encuentra más cerca del procesador.
 Memoria Cache.
 Memoria RAM.
Memoria secundaria:
 Disco de estado sólido.
 Disco magnético.
Almacenamiento terciario:
 Discos ópticos CD/DVD
 Almacenamiento fuera de línea (cintas): La que se encuentra más lejos del procesador.
Mientras más lejos se encuentre del CPU, mayor tamaño tiene, pero menor costo y más lento.

Introducción a Sistemas Operativos


Un sistema operativo administra los recursos del sistema y los programas en ejecución.
Además, se administra a sí mismo. Hay muchos tipos de sistemas operativos.

Funciones que tiene el sistema operativo:


(las primeras 2 son las favoritas de Dan)
 Administrar la ejecución de programas.
 Interfaz para usuario y programadores. Como todo el hardware es diferente entre sí,
esto desliga al programador a tener que averiguar con cuál hardware está trabajando.
 Administración de los recursos de hardware y software.
 Administrar los dispositivos de entrada/salida.
 Administrar los archivos.
 Comunicación entre programas.
 Asignación de recursos.
 Protección y Seguridad.

5
Lucila Canalini

Capas de una computadora:


 Aplicaciones (Chrome, block de notas, etc.), utilizadas por el usuario final.
 Utilidades (compilador, interfaces gráficas, etc.), utilizado por el programador.
 Sistema operativo (kernel) (memoria, disco, procesador), utilizado por el programador.
 Hardware, utilizado por el diseñador del sistema operativo.

Modos de ejecución
Separar en dos modos aumenta la seguridad, evitando que el usuario ejecute instrucciones
privilegiadas que puedan dañar al sistema. El procesador va cambiando de modo usuario a
modo kernel constantemente.
Modo kernel es el sistema operativo: Puede ejecutar instrucciones privilegiadas y no
privilegiadas.
Modo usuario es todo lo que no sea el sistema operativo: El Word, el Chrome, el block de notas,
etc. Solo puede ejecutar instrucciones no privilegiadas.
Motivos para que haya cambio de modo:
Son las interrupciones (se está ejecutando una instrucción en modo usuario, se realiza la
interrupción en modo kernel, y luego vuelve a modo usuario para que pueda seguir ejecutando
sus programas de usuario), y las llamadas al sistema (mecanismo que ofrece el SO para que
los programas o programadores puedan pedir algún servicio al Sistema Operativo).
Si un usuario, un programador, necesita hacer algo que implique una instrucción privilegiada,
debe hacerlo a través de una Syscall.

Llamadas al sistema (Syscall)


Funciones incluidas en la parte principal (en el núcleo) del sistema operativo, y suele estar
relacionada al uso de recursos de la computadora. Permite a los programas acceder a recursos
de manera más segura.
Se utilizan para solicitar un servicio al sistema operativo. Por ejemplo, escribir algo en un
archivo. Yo le estoy pidiendo como programador/usuario al sistema operativo que se escriba
eso en el archivo.
Es una herramienta utilizada por los procesos para solicitar servicios al sistema operativo
que de otra forma le serían imposibles poder realizar, como el uso de recursos de hardware
(leer disco, por ejemplo) o de otra índole (crear un klt, por ejemplo). Los procesos ejecutan en
modo usuario, bajo el cual no se pueden ejecutar instrucciones privilegiadas. Al realizar una

6
Lucila Canalini

llamada al sistema, se cambia a modo kernel, y solamente en dicho modo se pueden ejecutar
instrucciones privilegiadas.
Suelen ser utilizadas a través de una API por medio de wrappers. Estas son funciones que
incluyen alguna llamada al sistema. Un programa escrito utilizando wrappers de una biblioteca
standard permite portabilidad.
La syscall es el punto de entrada oficial y último para solicitar un servicio al sistema operativo.
Ofrece máxima flexibilidad de uso y optimizaciones de performance, aunque carece de
facilidad/claridad/portabilidad de uso.
El wrapper (de una syscall) es una función que corre en modo usuario que se interpone entre
la solicitud del servicio y la syscall real. Ofrece mayor facilidad/claridad/portabilidad en el uso,
aunque restringe flexibilidad y la posibilidad de realizar optimizaciones de performance.
14/04/2020

Sistemas monoprogramados vs. Sistemas multiprogramados


En un sistema monoprogramado hay un único programa que se está ejecutando, además del
sistema operativo. Las operaciones tardan mucho tiempo, por lo que hay tiempo del procesador
que se está desperdiciando y este es muy importante.

En los sistemas multiprogramados se pueden ejecutar más de dos programas, no en el mismo


instante, pero si en un mismo intervalo de tiempo. La multiprogramación es un modo de
operación que permite que dos o más programas ejecuten de forma concurrente. Durante esta
puede haber varios programas en un intervalo de tiempo.
La creación de estos sistemas dio pie a que existieran los sistemas multiusuarios, es decir, que
pueda estar ejecutando más de un usuario.
Distinto es el multiprocesamiento, que son múltiples procesadores. En este hay muchos
procesadores que pueden ejecutar en paralelo dos procesos diferentes.
Ejecución concurrente son dos o más programas ejecutando en el mismo intervalo de tiempo.
Este intervalo va de 0 hasta algún número.

Programa
Un programa es una secuencia de instrucciones compiladas a código máquina. Esto significa
que escribimos nuestros programas en un lenguaje de programación, lo compilamos y genera
un archivo binario (ejecutable) donde encontramos las instrucciones que debe seguir el
programa. Es un archivo dentro de la computadora que si nunca lo abriste seguro nunca lo
necesitaste.

7
Lucila Canalini

Procesos
Un proceso es mucho más que un programa que se está ejecutando. Es una secuencia de
instrucciones (un programa) que contiene el programa y más componentes asociados al
proceso y la memoria que utiliza. Un proceso tiene vida y está todo el tiempo haciendo algo. El
Sistema Operativo trabaja con procesos.

Se puede ejecutar un único proceso en un determinado momento en una CPU. La única


situación en la que pueden ejecutar 2 o más procesos en el mismo instante de tiempo es cuando
hay 2 o más procesadores (multiprocesamiento). Si el sistema tiene un solo procesador,
entonces puede ejecutar un solo proceso en un instante de tiempo.

Estructuras que contiene un proceso:


 Código: Espacio asignado para almacenar la secuencia de instrucciones del programa.
Van a haber un conjunto de instrucciones haciendo referencia a las declaraciones.
 Datos: Espacio asignado para almacenar variables globales.
 Pila: Espacio usado para guardar variables locales, parámetros y, además, los puntos
de retorno a la función.
 Heap (cúmulo o montículo): Espacio asignado para el uso de memoria dinámica. Se
pide esta memoria a medida que el proceso va avanzando.

Contexto de ejecución del proceso


Está compuesto por los registros del procesador y por el PSW (Program Status Word).

8
Lucila Canalini

Atributos para diferenciar a un proceso de otro:


 Process ID (PID): Identificador univoco de un proceso.
 Parent Process ID (PPID): El identificador del proceso padre.
 User ID (UID): El id de quien creo el proceso.
 Información de gestión de memoria.
 Información de planificación: Cuando un proceso tiene prioridad sobre otro para
ejecutarse.
 Información de E/S: Dispositivos que utiliza el proceso.
 Información contable o de estadística: Cuánto se usó el procesador, cuanto tardo en
responder, cuanta memoria se usó, etc.
Toda esta información está guardada en el Bloque de Control del Proceso (PCB). Este bloque
contiene toda la información relacionada al proceso y se guarda en la parte de la memoria
del kernel para poder administrar todos los procesos. Es básicamente una lista que le permite
al SO ir para adelante o para atrás. Trabaja de este lado por la información estadística que
contiene.
Dentro del PCB, la información del contexto de ejecución (registros del procesador) tiene
utilidad solamente cuando el proceso no está ejecutando, pero tampoco finalizo.
El PCB es una estructura y para el manejo propio del SO maneja todo con punteros. Tienen una
cantidad finita de espacio, aunque sea un número muy grande.
Como procesos no sabemos cuál es nuestro PID porque el programador no tiene acceso al PCB,
a menos que programes sistemas operativos. Para saber este tipo de información habrá que
hacer una llamada al sistema.
Hay un solo PCB por cada proceso. Contiene la dirección a las estructuras del proceso y guarda
el contexto de ejecución cuando el proceso no este ejecutando, además de los atributos.

Representación del proceso en el sistema


Un proceso puede modificar los siguientes elementos de su
imagen:

 datos estáticos
 pila
 heap
Estos son espacios de memoria utilizados para que el
programador guarde datos (Arrays, Variables, etc.). El código
del programa no puede modificarse y el PCB solo lo manipula
el Sistema Operativo.

Ciclos de vida de un proceso (esto es desde que inicia hasta que termina)
Sobre los estados:
Un proceso está Listo cuando está esperando para ser pasado al procesador y poder ejecutar
sus instrucciones.

9
Lucila Canalini

El estado Suspendido sirve para un proceso que está siendo depurado. Uno de los usos de este
estado es para la depuración de procesos. Otro uso es para aquellos procesos que pasan de
Memoria Principal al Área de Intercambio (o Swapping).
El proceso en estado Finalizado, aunque no conserva el código, los datos, la pila y el heap,
mantiene el PCB, por lo tanto, sigue existiendo. Se mantiene por fines estadísticos o porque
ningún proceso tomó su valor de retorno. Su padre pudo haber finalizado, pero el proceso
puede seguir ejecutando.

Estado de los procesos: Diagrama de 2 estados.

Esto no va a ser siempre así. En algún momento de tiempo puede ser que el PCB3 pase a “No
ejecutado” para que el PCB4 pase a ejecutar. Los procesos constantemente pueden pasar de un
estado a otro. Los PCBs están enlazados entre sí, al azar, o quizás no, pero todos tienen una
prioridad para ejecutarse antes que otro.
Para que funcione bien tiene que tener los estados listos, bloqueado, y ejecutando, por lo que
el diagrama de 2 estados no funciona muy bien.
Estado de los procesos: Diagrama de 3 estados.

En este diagrama, un proceso que no está listo es uno que está bloqueado. Se bloquea porque
seguramente hubo una llamada al sistema. No podrá seguir ejecutando hasta que no obtenga
lo que pidió. Un ejemplo sería si solicitó abrir un archivo para adquirir información. Hasta no
obtenerla, estará bloqueado.
Para que un proceso ejecutando pase a bloqueado puede ser una llamada al sistema porque
necesita algo del Sistema Operativo o, raramente, porque el proceso quiere dejar de ejecutar
porque prefiere que ejecute otro o decide hacer otras cosas.
Un proceso bloqueado puede pasar a listo cuando obtiene lo que se le solicitó al Sistema
Operativo. Se entera que obtuvo dicha información a través de una interrupción. Esta
interrupción nos dirá que la lectura del disco, o lo que se necesitaba hacer, ya finalizó. Cuando

10
Lucila Canalini

se dispara dicha interrupción, el Sistema Operativo lo agarra, lo pasa al espacio de memoria


donde debe pasar los datos, y cambia el estado del proceso.
Para que un proceso que esté ejecutando pase a la cola de listos, puede darse porque se le
acabó el tiempo que se le asigno para ejecutar, o porque se produjo una interrupción y un
proceso que estaba bloqueado o un proceso nuevo tiene más prioridad que el que se está
ejecutando.
Estado de los procesos: Diagrama de 5 estados.

El estado finalizado es cuando el PCB se queda aguardado para ver qué valor se retorna. El
lugar que ocupaba en memoria y datos globales se liberan. Solo conserva su PCB, el resto lo
elimina para no seguir ocupando espacio. Cuando otro proceso toma el valor de retorno de
dicho proceso, sale del sistema y deja de existir.
Estado de los procesos: Diagrama de 7 estados.

Los nuevos estados (ready/suspended y blocked/suspended) se usan cuando hay un


intercambio de memoria. El estado suspendido sirve para un proceso esperando por un
evento.
Un proceso Ejecutando puede realizar una llamada al sistema y pasa al estado Bloqueado. En
un algoritmo con desalojo puede ser desalojado y pasa a estado Listo. Cuando un proceso
finaliza de manera normal (exit) o por algún evento inesperado, pasa al estado Finalizado. Para
pasar a Suspendido, debe pasar previamente por Bloqueado o Listo.
Cuando quiero agregar un proceso, pero no tengo memoria disponible, puedo pasar cosas al
disco para liberar espacio. Al liberarlo, el proceso que estaba en estado New esperando para
entrar, puede pasar a estado Ready.

11
Lucila Canalini

La imagen de un proceso puede estar ubicada en memoria cuando su estado es Bloqueado.


Cuando el proceso está bloqueado, tiene su imagen en memoria, pero cuando se encuentra
“Listo/Suspendido” o “Bloqueado/Suspendido”, algunas estructuras que componen la imagen
del proceso se encuentran en el área de intercambio (habitualmente en disco).
Depuración (debugging): Sirve para poder cortar la ejecución mientras mi proceso se está
ejecutando. Cuando se llama un debugger y se agrega un breakpoint donde queremos parar, lo
que estamos haciendo es agregar una interrupción particular. El debugger está programado
para que pueda acceder a los datos del programa que está siendo debuggeado. Para activarlo
hay que hacerlo en modo kernel, y se activa vía la palabra PSW. En el modo debug significa que
cada instrucción va a ser de alguna manera interrumpida para que se ejecute otro proceso.

E/S bloqueante y no bloqueante


Las bloqueantes son como las recién mencionadas. El proceso se está ejecutando, pero necesita
algo del Sistema Operativo entonces se lo solicita y se bloquea hasta que lo recibe.
Las no bloqueantes son aquellas en las que el proceso necesita algo del sistema operativo, pero
no se bloquea hasta que lo obtiene, sino que se sigue ejecutando. El problema es que, a
diferencia de las E/S bloqueantes, al seguir ejecutando hay que preguntar a cada rato si la
información que había solicitado ya está disponible o todavía no y hay que reintentar más tarde
o no está disponible y se produce un error.

Creación de un proceso
Puede ser creado por el sistema operativo para dar algún servicio. Yo creo un proceso porque
necesito que haga algo para mí.
También puede ser creado a pedido de otro proceso. El proceso que crea otro proceso se
llamará padre y el creado se llamará hijo. El proceso padre e hijo pueden ejecutar de forma
concurrente o el padre puede esperar a que los hijos finalicen.

Pasos para crear un proceso:


1. Se asigna el Process ID. Dicho PID se va creando uno a uno.
2. Se reserva espacio de estructuras (código, datos, pilas y heap).
3. Se inicializa el PCB.
4. Se ubica el PCB en listas de planificación.

12
Lucila Canalini

En C en Linux, un proceso se crea a través de la función fork():


int pid;
char *programa[]; = {“ps”, “f”, NULL);
pid = fork();
if(pid<0){
printf(“hubo un error con el fork\n”);
return -1;
}
if(pid == 0){
execv(“/bin/ps”, programa);
}
if(pid > o){
wait(NULL);
printf(
}

Finalización de un proceso
a) Terminación normal, donde se ejecuta la llamada al sistema exit. No la escribimos
cuando programamos, pero cuando hacemos return el programa sabe que es un exit. El
valor de retorno es el exit_status que es lo que le ponemos al return. También hay un
caso wait, en el que hay que esperar que termine el hijo.
b) Terminado por falla o condición de error, como lo sería una división por cero.
c) Terminado por otro proceso. El comando kill envía señales, entre ellas, una puede ser
matar a un proceso. Desde la consola puedo hacer kill, algún código que indique la
eliminación de un proceso, y el número de proceso.

Cambio de un proceso
Un proceso ejecuta sus instrucciones y, en algún momento, por alguna razón, el Sistema
Operativo toma el control del procesador y comienza a administrar los procesos y los recursos.
Cuando paso del proceso al Sistema Operativo hubo un cambio de modo: estaba ejecutando en
modo usuario y ahora que está en el Sistema Operativo está en modo kernel.
El Sistema Operativo hace sus tareas, puede estar atendiendo una interrupción, una llamada al
sistema, etc. Cuando termina, vuelve a ejecutar el proceso que estaba ejecutando. Nuevamente,
hay un cambio a modo usuario.
Vuelve a aparecer una llamada al sistema o interrupción y aparece el Sistema Operativo. Ahora,
el SO decide que se siga con el siguiente proceso cuando termina de hacer sus tareas, en lugar
de volver al proceso que todavía no estaba terminado de ejecutar. A esto le llamamos cambio
de proceso. Lo que paso previamente de que paso del primer proceso al Sistema Operativo y de
nuevo al proceso inicial, no fue un cambio de proceso.

13
Lucila Canalini

Un process switch implica dos cambios de modo. Puede generarse por una interrupción o por
una llamada al sistema. El primer cambio de modo es de modo usuario a modo kernel, y el
segundo es de modo kernel a modo usuario.
Overhead (sobrecarga): Son las tareas administrativas que lleva a cabo el sistema operativo.
Son tareas que a mí como usuario no me interesa que se hagan, aunque es importante que se
hagan porque permite que se ejecuten varios programas a la vez, etc.
Pasos del cambio de proceso (podrían ser más):
1. Ejecutando Proceso A, se produce una INTERRUPCIÓN.
2. Se guarda el PC y PSW del proceso A.
3. Se actualiza PC para atender la interrupción y se cambia de modo de ejecución (modo
usuario a kernel).
4. Se guarda el resto del contexto del proceso A.
5. Se decide cambiar el proceso.
6. Se guarda el contexto del proceso A en su PCB.
7. Se cambia el estado del proceso A de Ejecutando a Listo (u otro).
8. El PCB del proceso A se ubica en la lista de procesos Listos (u otra).
9. Se selecciona otro proceso para ser ejecutado (el proceso B).
10. Se cambia el estado del proceso B a Ejecutando.
11. Se actualizan los registros de administración de memoria del procesador con los del
proceso B.
12. Se actualizan los registros del procesador con los del PCB de B y se cambia el modo de
ejecución (modo kernel a usuario).
En el PCB se guardarán los registros del procesador cuando el proceso no esté en estado
Ejecutando. Esto es porque cuando lo esté, no es necesario guardar los registros en el PCB ya
que los está utilizando y estos varían constantemente.
18/04/2020

Hilos
Son subprocesos que permite que se hagan varias cosas a la vez. Nos da ventajas con respecto
a los procesos. Los hilos en ejecución comparten las variables globales (Datos) y la memoria
dinámica (Heap). A través de una variable global podría accederse a la memoria dinámica.
Dos hilos de diferentes procesos pueden ejecutar secciones de código idénticas entre sí. Datos,
Pila y Heap, son espacios de memoria utilizados para que el programador guarde datos (Arrays,
Variables, etc). El código del programa no puede modificarse y el PCB sólo lo manipula el
Sistema Operativo.

Monohilo
Un proceso que tiene un solo hilo de ejecución. Tenemos una secuencia de instrucciones y
vamos haciendo una por una y siempre una después de la otra, salvo que haya algún salto. Una
serie de pasos a seguir, como si fuese una receta. No tenemos manera de hacer varias cosas a la
vez. Es un program counter saltando de una instrucción a la otra.

14
Lucila Canalini

Multihilo
Hace muchos años no se usan los sistemas monohilo, porque ahora existe la posibilidad de
hacer sistemas multihilo. Su función es poder aprovechar recursos y poder hacer muchas cosas
al mismo tiempo en un mismo programa. Esto surge porque el contexto de ejecución del
programa está separado de los recursos que utiliza un proceso. Si hay un solo procesador, hay
un solo proceso ejecutando, y se está haciendo una única cosa a la vez. No es ventajoso si
buscamos seguridad, pero tiene varias ventajas:
 Capacidad de respuesta: Un proceso aprovecha mucho mejor el procesador por más
que esté a la espera de información. Procesamiento simultaneo de un mismo proceso
(no en paralelo).
 Economía: Se refiere a la economía del Sistema Operativo. Ahorro recursos y hacer
cambios entre hilos también será rápido. No habrá tanto overhead.
 Compartición de recursos: Porque un hilo puede abrir un archivo, y el resto de los
hilos también. Se logra compartir recursos al compartir variables.
 Comunicación eficiente: Compartir recursos es una de las maneras que tienen los
procesos de comunicarse, mandándose paquetes, por ejemplo.
 Permite multiprocesamiento.
 Procesamiento asíncrono: Ningún hilo tiene que esperar que otro hilo haga algo para
poder ejecutar.
El procesador va a ejecutar siempre lo mismo, a la misma velocidad que puede, pero tiene la
ventaja de que hoy en día los procesadores tienen varios núcleos, por lo que cuando salte entre
diferentes hilos va a ser mucho más rápido que si cambio entre procesos. Va a ser más rápido
desde el punto de vista del proceso, pero desde la vista del procesador, va a ser la misma
cantidad de tarea. Su velocidad es fija para todo.
En un sistema operativo que admite procesos multihilo, cambian la pila y el PCB por ser parte
del contexto de ejecución del programa. Cada hilo tiene su propio contexto, sus propios datos
particulares y su propio estado. El PCB se dividirá en dos: una pila y un TCB. Así es como el
proceso contiene una pila por cada hilo. Por otro lado, el código, los datos y el heap son
compartidos por todos los hilos del mismo proceso.

Los procesos con múltiples hilos requieren un PCB y un TCB por cada hilo. El PCB guarda la
información relacionada al proceso. Cada hilo tiene su propio TCB, con información relacionada
a ese hilo. Los hilos, independientemente de que sean KLTs o ULTs comparten memoria (por
ejemplo, variables globales) sin intervención del sistema operativo.

15
Lucila Canalini

Estado de hilos (uno de los siguientes)

Implementación de los hilos


Hace un tiempo los sistemas operativos no soportaban hilos, y esto traía un gran problema
porque no se podía contar con dichas ventajas de los hilos. Había que simularlos desde mi
programa sin que el SO se enterara.
Desde el modo usuario vemos la biblioteca con los hilos, y del lado del Sistema Operativo
lo único que ve es un proceso simple con una única línea de ejecución, por lo que se estará
trabajando con un único contexto de ejecución.
Implementación de hilos de usuarios (ULT):
Se necesita una biblioteca en modo usuario que simule
la creación de hilos, la planificación (se ejecuta uno a la
vez) y la interacción entre ellos, y cómo hacer que no
ejecuten de manera desordenada o, de ser así, darle
coherencia al programa. Igualmente, por más que
puedan solicitar servicios por la biblioteca, también lo
pueden hacer directamente al sistema operativo a
través de una syscall.
El sistema operativo nunca se va a enterar que en el
proceso hay hilos porque son implementados a nivel
usuario. Un sistema que sólo admite el uso de procesos monohilo puede utilizar hilos a nivel de
usuario (ULT).
 Bajo overhead: No intercambio contexto de hilos dentro del procesador, sino que
siempre es un único proceso con su contexto. No hago intercambio constante de las
palabras y registros que están dentro del procesador porque estoy siempre trabajando
sobre la misma memoria. Por lo tanto, el cambio de hilo entre hilos de un mismo proceso
tendrá menos overhead usando hilos ULT, respecto a los KLT.

 Planificación personalizada: No dependo del sistema operativo porque este solo ve


una línea de ejecución. La planificación es interna a la biblioteca.

16
Lucila Canalini

 Portabilidad: Como no hago llamadas al SO, con solo darle soporte a mi programa, yo
podría llevarme el programa y ejecutarlo en otra plataforma. No hay dependencia de
creación y comunicación de hilos con el SO, sino que la biblioteca es la que provee.

 Syscall bloqueante bloquea todo el proceso: Cualquier operación que requiera un


recurso mediante llamadas bloqueantes va a hacer que se bloquee todo el proceso y no
puedan seguir operando los otros hilos. Esto es porque hay un único PC para el proceso,
por lo que, al bloquearse la imagen, todo pasa a estado bloqueado.

 No permite multiprocesamiento: Al tener un único PC, no se puede procesar más de


un proceso a la vez.

E/S bloqueantes
En el caso de los programas que implementan hilos de usuario,
tenemos el problema de que, si voy a esperar en la red o leer un
archivo, me va a bloquear todo el proceso hasta que dicho recurso
que necesitaba esté disponible y el Sistema Operativo se lo provea
al proceso para consumir. Hay métodos en los cuales podríamos
utilizar E/S bloqueantes y no bloqueantes.
Si convierto la llamada bloqueante en no bloqueante, puedo lograr
que el proceso no se bloquee nunca o al menos intente no
bloquearse cada vez que tenga que hacer una syscall. Para lograr
utilizar los ULT en muchas bibliotecas se utiliza el jacketing.

Jacketing
Previene que un hilo ULT se bloquee en caso que el dispositivo este
bloqueado. Convierte una E/S bloqueante en una no bloqueante.
Como el Sistema Operativo desconoce la existencia de los hilos ULT
y sólo conoce a la entidad proceso, el sistema operativo bloquea al
proceso completo. Si los hilos ULT utilizaran la técnica de Jacketing,
el proceso no se bloquearía. Además, los hilos no cambiarían de
estado porque cada uno tiene su propio contexto de ejecución.
Algunos podrían estar bloqueados o listos.

Implementación de hilos de kernel (KLT):


El hecho de tener hilos de kernel me permite tener subprocesos.
Cada uno de esos hilos tiene su propio program counter y esto
permite que cada hilo tenga una función asociada y que se vaya
ejecutando de manera paralela a la ejecución del resto de los
hilos si es que hay multiprocesadores.

17
Lucila Canalini

Cada hilo de kernel se va a comportar como un proceso para el sistema operativo. El sistema
operativo lo va a ver y por eso podrá planificarlo y asignarle recursos dentro del procesador.
 Syscall bloqueante bloquea solo ese hilo: Si algún hilo de kernel pide una llamada
bloqueante, se bloqueará únicamente este hilo, el resto de los hilos podrían
tranquilamente funcionar. Básicamente, no bloquea el proceso, sino que bloquea
únicamente el KLT.

 Permite multiprocesamiento de hilos del mismo proceso: Cada hilo de kernel tiene
su propio PC por lo tanto tengo soporte de estructuras que el procesador puede
manejar. Los hilos KLT de un mismo proceso pueden ejecutar en diferentes
procesadores. Si bien forman parte de un mismo proceso, el sistema operativo los
gestiona como procesos diferentes.

 Mayor overhead respecto ULT: Esto es porque cualquier cosa que se quiera hacer con
los hilos deberá pasar por el sistema operativo porque este los planifica.

 Planificación del sistema operativo: Si el SO puede ver los hilos de kernel, los va a
poder planificar, y esto significa que vamos a estar atados al sistema operativo y su
planificación. Si tiene una planificación que no es afín a lo que necesitamos, traerá
problemas, pérdidas de tiempo, etc.

 Portabilidad: Al estar atado al SO en la implementación, si mi programa, que trabaja


con hilos de kernel en Linux, lo muevo a Windows, es muy probable que no funcione
porque las llamadas para crear hilos, intentar hacerlos planificar, y demás, no
funcionen.
Hay veces que hay bibliotecas que tienen un sistema operativo que soporta hilos de kernel. En
ese caso, se puede trabajar con ambos tipos de hilos, haciendo una combinación.
Se puede hacer una combinación entre un proceso que usa biblioteca que soporta hilos de
usuario y a su vez el SO da soporte de KLT. Son herramientas que nos permiten como
profesionales de sistemas, hacer uso de las capacidades que tenemos del lado de la máquina y
los recursos que nos provee a través del Sistema Operativo, optimizándolos.

Cambio de ejecución de un KLT a otro del mismo proceso


Aclaración: No se actualizan registros relacionados con punteros a segmentos de memoria
estáticos, heap o código, dado que pertenecen al proceso y son compartidos por todos los hilos.

1. Se guarda una parte inicial del contexto (PC, FLAGS) en el stack del sistema.
2. El SO ingresa su ejecución y guarda el resto de los registros en el stack del sistema.
3. El SO determina que debe realizar un thread switch.
4. Mueve el contexto de ejecución completo del stack del sistema al TCB del hilo.
5. Elige el próximo hilo a ejecutar.
6. Copia todo el contexto del TCB del nuevo hilo al procesador y realiza un cambio de modo
(a usuario), todo al mismo tiempo.

18
Lucila Canalini

24/04/2020

Planificación de CPU
La planificación de un proceso es información que se
guarda en el PCB.
Cuando cambiamos de proceso, una de las tareas que hay
que hacer es elegir qué proceso se va a ejecutar ahora.
Podría ser elegir un proceso al azar, pero no es lo más
conveniente.
Uno de los recursos masmás importantes q tiene el
sistema es el procesador, porque es el recurso que si o si
van a utilizar los procesos.
La idea de la planificación del CPU, es asignar el próximo
proceso y el motivo por el que se elijeelige dicho proceso.
La idea es queque, si tengo muchos procesos en el
sistema, todos los procesos puedan ejecutar un poco, y que ningún proceso se quede sin
ejecutar en absoluto.
Muchas veces el proceso que tenemos que elegir para que siga ejecuandoejecutando es porqueq
tenemos un sistema que funcione para algo en particular.
Hay muchos tipos de procesos: los del sistema, los interactivos con los usuarios, sistemas que
ejecutan procesos uno después del otro sin tener interacción con el usuario.

Objetivo:
 Asignar procesos al procesador.
 Rendimiento / Productividad.
 Optimizar algún aspecto del comportamiento del sistema.

Ciclo de ráfagas
Empieza usando el CPU, entrada/salida, CPU, entrada/salida, constantemente. Es la forma
normal que tienen los procesos de funcionar.
Procesos limitados por la CPU: En estos, las ráfagas de CPU, que son todas las instrucciones
que se ejecutan simultáneamente, son muchas más que las que ejecuta de entrada y salida.
Procesos limitados por la E/S: Lo contrario a los otros. Tienen poco de CPU y mucha espera
de E/S. Después otra vez poco CPU, y así. Un ejemplo es algún programa interactivo, en la que
el sistema espera a que nosotros hagamos algo.

Diagrama de siete estados de un SO


Entre las transiciones de los estados hay detalles. Son interacciones manejadas por el Sistema
Operativo, pero no la misma parte del SO se encarga de pasar los procesos de un estado a otro.
Esto lo realizan diferentes planificadores. Los nombres de los planificadores tienen que ver con
cada cuanto tiempo se ejecutan.

19
Lucila Canalini

En los planificadores de largo y medio plazo pueden afectar el orden de los procesos en lista
de procesos listos para ejecutar.
Los nombres de las planificaciones tienen que ver con cada cuanto se llevan a cabo. Las de largo
plazo son porque solamente se hacen cuando llega o se va un proceso, lo que no pasa tan
seguido como lo que pasa en la planificación de corto plazo.
1. Planificador de largo plazo: Involucra los estados New y Exit. Ambos estados tienen
un grado de multiprogramacion que indica cuantos procesos puedo tener en el sistema
ejecutando como maximo en un intervalo de tiempo. Cuando un proceso finaliza, hay
lugar para un proceso nuevo. El grado de multiprogramación se modifica cuando pasa
esto. El planificador de largo plazo, al momento de admitir un proceso nuevo, puede
afectar el orden de los procesos de Listos.

2. Planificación de medio plazo: Se relaciona con los estados Suspendidos. No son


estados que se usen hoy en dia, principalmente porque está mas avanzada la gestion de
memoria. Lo normal es que ningun Sistema Operativo los utilice así, de manera
separada. Tiene que ver con la decision del SO de reducir o aumentar el grado de
multiprogramación, preservar los recursos (porque muchos procesos ocupen memoria
o interviniendo, usando un mismo recurso, haciendo que dicho recurso funcione mal
por el uso intenso sobre el). El planificador de medio plazo, puede afectar el orden de
los procesos listos cuando un proceso es pasado de disco a memoria.

20
Lucila Canalini

3. Planificación de corto plazo: Están involucrados los estados Running, Ready y


Blocked. Constantemente los procesos están pasando de Ready a Blocked. El estado
Blocked es un estado en el que al proceso le falta información o necesita recibir algo
para poder seguir ejecutando. Las transiciones de Running a Blocked ocurren cuando
hay una llamada al sistema. Y de Blocked a Ready se da cuando el proceso ya esperó lo
que tenía que esperar para poder ejecutar. Estando en Ready, el proceso espera a que
el Sistema Operativo decida que este va a ejecutar. En ningún momento un proceso
puede pasar de Ready a Blocked.
El planificador de corto plazo es invocado cuando se realiza una llamada al
sistema o una interrupción. Cuando un proceso realiza una llamada al sistema, podría
cambiar su estado a Bloqueado. Una interrupción puede provocar que un proceso se
desbloquee y quede en estado Listo o que cambie de estado Ejecutando a Listo.

Decide cuál es el próximo proceso quese debe ejecutar, según el objetivo del sistema operativo,
conviene elegir uno u otro. También decide dónde ubicar el PCB del proceso que se estaba
ejecutando.
La interrupción de Clock permite que el SO, tome el control del procesador para que realice
alguna tarea. Esa tarea puede ser realizar un cambio de proceso, o no. El procesador no realiza
cambios de proceso.

21
Lucila Canalini

Criterios de planificación
Son los que nos permiten tomar una decisión sobre qué tipo de proceso elegir en cada momento.
Los criterios pueden ser:
 Orientados al usuario: Cómo ve el usuario el funcionamiento de los procesos.
 Orientados al sistema: Es un análisis general de como funciona el sistema operativo.

Las métricas nos dan un valor preciso pero no podemos optimizar todas a la vez. Por ejemplo,
el tiempo de espera está en contra de la utilización del CPU.

Métricas cuantitativas orientadas al usuario/proceso:


 Tiempo de ejecución: El tiempo que pasa entre el inicio y el fin del proceso.
 Tiempo de respuesta: Tiene que ver con lo que hace el proceso cuando está
ejecutando. Una vez que se realiza una E/S, cuánto tiempo se tarda en tener una
respuesta. No significa la respuesta completa.
 Tiempo de espera: Cuánto tiempo el proceso estuvo listo para ejecutar y no ejecutó.
Es un tiempo importante porque es el que me va a decir si mi planificador de corto plazo
está eligiendo bien.
Métricas cuantitativas orientadas al sistema: Tienen que ver con el funcionamiento general
del SO.
 Tasa de procesamiento: Mide la cantidad de procesos que finalizaron en una cantidad
de tiempo. Queremos que sea lo más alto posible (más procesos en la menor cantidad
de tiempo posible), lo que implica aprovechar al maximo el procesador.
 Utilización del CPU: Porcentaje que cada proceso usó del CPU en un momento
determinado.
Cualitativas:
1. Previsibilidad: Apreciación que tiene el usuario sobre lo que está haciendo un proceso.
Quizás distintos usuarios sobre un proceso tienen distintas apreciaciones.
 Equidad: Que todos los procesos pueden avanzar un poco en su ejecución y que
ninguno quede perdido. La idea es que todos puedan ejecutar de manera pareja.
 Imposición de prioridades: Necesito que todos puedan avanzar en su ejecución por
más que un proceso tenga una prioridad más alta que otro.
 Equilibrio de recursos: Poder hacer que los procesos no utilicen siempre los mismos
recursos.

22
Lucila Canalini

Algoritmos de planificación
A cada proceso se le asigna una prioridad. La prioridad de un proceso puede cambiar a lo largo
de todo su cilco de vida. La idea es que el planificador seleccione el proceso de prioridad más
alta.
Esto no quiere decir que solo van a ejecutar los procesos con prioridad alta. Lo que
generalmente pasa es que el tiempo que un proceso está en estado bloqueado suele ser mayor
al de listo, por lo que en algún momento, los de baja prioridad van a ejecutarse.
El tiempo en unidades que va a ejecutar cada proceso se conoce como ráfaga.
Las E/S no pueden solaparse, se deben hacer una detrás de la otra, y siempre es FIFO.
Los alogritmos se dividen en dos categorías: sin desalojo (sin expulsión), y con dejsalojo (con
expulsión). Los algoritmos sin desalojo, si bien no vemos las interrupciones en los procesos, lo
que podría pasar en dichas intervenciones es que se decida cambiar el proceso sin que este
termine toda su ráfaga. Es en los algoritmos con desalojo en los que sí representamos las
interrupciones.
Los algoritmos con desalojo tienen en cuenta los mismos eventos de los algoritmos sin desalojo
(bloqueo del proceso por syscall y finalización del mismo), y consideran también evento que
derive en un ingreso a la cola de Ready (syscalls de creación de hilos/procesos, o interrupciones
que indiquen fin de ráfaga o fin de I/O). Los algoritmos sin desalojo descartan estos últimos
eventos porque deciden no expropiar la cpu al proceso una vez que la misma fue asignada.
Existen ciertas implicancias de la utilización de planificadores con o sin desalojo en sistemas
operativos de tiempo compartido (o multitarea). El sistema operativo solo puede recuperar el
control de la CPU cuando el proceso finaliza o se bloquea, por lo que un usuario/proceso podría
nunca ejecutar si otro proceso nunca libera el procesador, ya sea por un error o porque
deliberadamente no se bloquea nunca.
Algoritmo FIFO
El primero que llega es el primero en ejecutar. Este es un algoritmo sin desalojo.
Ejemplo:

23
Lucila Canalini

Algoritmo Short Job First sin desalojo (SPN)


El primer proceso entra a ejecutar, sin importar que tan largo sea el CPU. Después de la primera
E/S de este, si hay dos procesos listos, la prioridad la tendrá el que tenga CPU más corto.
Para algoritmos que usan la próxima ráfaga de CPU, como el Short Job First, generalmente solo
se pueden implementar con un estimador de ráfagas. Esto es porque el Sistema Operativo no
conoce de antemano cuál será el tiempo de cada ráfaga. Por lo tanto, es necesario estimarla.
Ejemplo:

Desventajas de este algoritmo de planificación:


 Inanición (starvation): Situación en la que a un proceso se le niega la posibilidad de
utilizar un recurso por la constante aparición de otros procesos de mayor prioridad.
Esta problemática podría nunca ocurrir, independientemente del algoritmo utilizado.
Algunos algoritmos no sufren inanición. Otros algoritmos podrían sufrirla, pero tienen
que darse ciertas condiciones. Por ejemplo, Short Job First puede sufrir inanición, pero
si todas las ráfagas de los procesos son iguales, entonces no habrá inanición.

Ejemplo: El proceso 2 llegó mucho antes que la mayoría, pero se postergó por tener una
ráfaga muy larga en comparación al resto. En este caso, el recurso que se le niega es el
procesador.

 Estimación de ráfaga: En la realidad ocurre que ningún programa te dice cuanto es su


ráfaga de CPU, por lo que lo único que podemos hacer es basarnos en estadísticas para
tratar de calcular de alguna manera el tamaño de las ráfagas de CPU. La otra forma es
utilizar estimadores.

24
Lucila Canalini

Lo que se ejecuta es lo real, pero lo que se planifica es lo estimado. Es decir, elijo qué
proceso vendrá en base a lo estimado, pero se van a ejecutar los CPUs reales.

Algoritmo Short Job First con desalojo (SRT)


En este algoritmo, empieza a ejecutar el primer proceso que llega, y seguirá ejecutando el
proceso que tenga la ráfaga más corta. En casos de “empate”, tendrá prioridad para ejecutar el
proceso que ya estaba ejecutando.
Ejemplo: El proceso 1 tenía una ráfaga de 4 para ejecutar, pero fue interrumpido por el proceso
2. En el instante 1 hay un desalojo. Esto ocurrió porque el CPU del 2 tenía ráfaga más pequeña
que la del 1, entonces pasó a esta. En el instante 3, se compara 1 contra 1, porque al proceso 2
le queda una ráfaga y al 3 también. En casos como este, en el que hay que desempatar, y seguirá
ejecutando el 2. En este ejemplo hay dos desalojos: en el instante 1 y en el instante 8.

Round Robin
Es un algoritmo con desalojo, al que a cada proceso se le dará un quantum (q) de tiempo. Antes
de ejecutar, el Sistema Operativo asignará cuanto tiempo tendrá para ejecutar. Esto quiere decir
que cada q unidades de tiempo, habrá un desalojo. El orden de llegada va a decidir cuál es el
siguiente proceso a ejecutar. Esto es porque se maneja por FIFO.

25
Lucila Canalini

Es muy importante el tamaño de quantum que se define porque de hacerlo mal, podremos
encontrarnos con varios inconvenientes. Un algoritmo con un quantum muy grande termina
siendo igual a un algoritmo de FIFO, y no se aprovecha el desalojo.
El algoritmo más justo es el Round Robin con quantum q=1, porque así todos pueden ejecutar
un poco. Sin embargo, tiene un inconveniente. El Sistema Operativo tiene que hacer
interrupciones en todos los instantes, y esto lleva tiempo, generando más overhead, a diferencia
de si el quantum es más grande.
Por lo tanto, si el quantum es muy grande, el algoritmo degenera en FIFO. Si el quantum es muy
chico, el algoritmo se vuelve más justo porque los procesos avanzan de manera más pareja, pero
genera mucho Overhead por todas las intervenciones necesarias del sistema operativo.
Además, los procesos que tienen ráfagas de CPU muy chicas, sufren un poco más,
principalmente porque nunca terminan de aprovechar todo el quantum.
Prioridades para desempatar (porque si no es FIFO):
1. El que fue interrumpido por el quantum.
2. El que su E/S fue terminada.
3. El que es nuevo (llegada).
Ejemplo: Se define un quantum q=3

Virtual Round Robin (VRR)


Trata de solucionar el problema que tienen los procesos limitados por entrada y salida. Se la
arregla para que tengan más prioridad que los procesos limitados por CPU.
Es un algoritmo con desalojo que también cuenta con un quantum (q) de tiempo. Tendrá dos
colas de procesos listos para ejecutar: la original y la auxiliar. Además, los procesos que estén
bloqueados, no pasarán a la cola de listos, sino que pasarán a la auxiliar. Así, los procesos que
tienen mucha ráfaga de E/S son beneficiados porque van a una cola diferente.

26
Lucila Canalini

Ningún proceso de listos se va a ejecutar mientras haya procesos en la cola auxiliar. La


cola auxiliar tendrá más prioridad por lo que se tiene que vaciar y recién ahí es cuando se
pueden ejecutar los procesos en la cola de listos.
Los procesos que estén en la cola de listos, tendrán el quantum definido por el Sistema
Operativo, mientras que los procesos que estén en la cola auxiliar, tendrán como valor de
quantum la diferencia que no había ejecutado previamente en el procesador.
Si el proceso que se está ejecutando tiene una ráfaga de, por ejemplo, 3, y ejecuta una sola
porque luego de 1 unidad de tiempo se bloquea, ahí pasará a la cola auxiliar con un quantum de
2. Si cuando sale de la cola, se ejecuta 1 sola unidad de tiempo y se vuelve a bloquear, no tendrá
otra vez 2 de quantum, sino que será 1. Por lo que los quantums se irán restando a medida
que van avanzando las ráfagas y los bloqueos.
Si un proceso tenía 3 unidades para ejecutar, ejecuta 1 unidad de tiempo y pasa al estado de
bloqueados, cuando se desbloquee pasara a la cola de listos. Pero si tenía un quantum de 3, esté
pasará con un quantum igual a 2 a la cola de listos.

Simultaneidad de eventos en la cola de listos


Esto no es usual que pase, pero en un momento determinado, cuando las unidades de tiempo
son cortas, puede pasar que en dicho momento lleguen procesos distintos de distintos lugares
a la cola de listos.
Los tres estarán al final de la cola de listos, pero ¿cuál primero?
Si hay una interrupción, lo normal es que el Sistema Operativo la atienda, por lo que los
procesos que vienen por medio de una interrupción se van a habilitar antes porque se van a
terminar antes, en comparación a una llamada al sistema.
Existe un vector de interrupciones, mientras más baja la posición, mayor prioridad tiene la
interrupción. La interrupción de reloj es la que está en la posición cero, por lo que es la que más
prioridad tiene.
Por lo tanto, el orden en el que entrarán a la cola de listos será el siguiente:

27
Lucila Canalini

Highest Ratio Response Next (HRRN)


Este algoritmo es sin desalojo y tiene envejecimiento (aging). Siempre empieza el que llegó
primero pero después tendrá más prioridad aquel con mayor tasa de respuesta. La tasa de
respuesta es el valor que toma R, que siempre será mayor a 1.

A partir de esto, podemos ver que mientras más tiempo espere el proceso en la cola de listos,
mayor será el valor de R, por lo que mayor será su prioridad. Prioriza a los procesos más cortos
y a los que esperan mucho tiempo en la cola de listos.
El uso de estimadores produce mucho overhead para el Sistema Operativo, y por eso se hace
sin desalojo, para no sumar aún más overhead.
Al ser sin desalojo, el primer proceso que llegue a la cola de listos se ejecutará con su ráfaga
completa. Lo mismo con el resto de los procesos, una vez que se encuentra el proceso que tiene
mayor prioridad y dicho proceso se ejecuta.
Si el cálculo de R es igual, entonces tendrá prioridad el que llegó antes a la cola de listos. Si
llegaron al mismo tiempo, tendrá prioridad el bloqueado, en lugar de él que llegue de proceso
nuevo.
Si hay un único proceso esperando, va ese, no se calcula la R.
Ejemplo: Una vez que se ejecutó el proceso 1, hay que ver qué proceso va a seguir ejecutando.
En el instante 3, el proceso 2 estuvo esperando 2 tiempos en la cola de listos porque llegó en el
instante 1, y tiene 4 unidades de tiempo de ráfaga, por lo que R = (2+4)/4. Por el otro lado, el
proceso 3 estuvo una única unidad de tiempo esperando porque entró en el instante 2, y tiene
para ejecutar una ráfaga e 3 unidades de tiempo, por lo que R = (1+3)/3. La prioridad la tendrá
el proceso 2 porque R2>R1.

28
Lucila Canalini

Algoritmo de colas multinivel


Es un algoritmo por prioridades. Clasifica los procesos y los agrupa dependiendo de su tipo.
Permitirá que siempre los procesos con mayor prioridad se ejecuten antes de los otros. Por lo
que para que se ejecute un proceso de prioridad media, no debe haber algoritmo de prioridad
mayor.
Como es un algoritmo de prioridades y estas no varían, son siempre las mismas como en el
gráfico, los procesos que están en la cola de máxima prioridad (o la que sea), una vez que se
ejecutan y vuelven a la cola de listos, siempre vuelven a la misma cola.

Algoritmo de colas multinivel realimentado (Feedback Multinivel)


Si hay desalojo por interrupción de reloj baja su prioridad. Este algoritmo también agrupa a los
procesos en diferentes colas, pero los procesos nuevos siempre llegan a la cola de mayor
prioridad. A medida que van ejecutando, la prioridad de dichos procesos puede ir cambiando.
Van bajando de prioridad a medida que van gastando su quantum.
Cuando se utiliza "feedback multinivel", durante el ciclo de vida de un proceso, este puede
moverse entre las diferentes listas de "ready" que pueden tener diferentes prioridades entre sí.
El sistema operativo seleccionará los procesos de la lista más prioritaria. En caso que esta
última lista este vacía, se continúa por la siguiente en orden de prioridad. Si entra en E/S, sube
de prioridad.
Se puede utilizar mecanismos de Aging para evitar inanición.

29
Lucila Canalini

Ejemplo: En este caso en particular, vemos que un proceso que sale de la cola de mayor
prioridad y usa todo su quantum, pasa a una cola de menor prioridad, para que el resto de los
procesos puedan ejecutarse también.

Ejemplos de Planificación con SO


Va a haber una interrupción cuando hay desalojo, quantum o cuando finaliza la entrada/salida.
Va a haber una syscall cuando llegue un proceso nuevo, haya un cambio de proceso o se pase a
entrada/salida.

Por lo tanto, habrá cambio de modo siempre que ejecute el Sistema Operativo, y esto será
siempre que haya: una syscall de i/o, una syscall new, una syscall exit, una interrupción, o un
cambio de proceso.

¿Cómo planificar procesos que tienen hilos?


Principalmente los hilos de usuario (ULT) tienen una planificación. El planificador de corto
plazo decidirá el momento en que el proceso podrá utilizar el procesador. Pero internamente
al proceso, la biblioteca de hilos decidirá que hilo ejecutará.

30
Lucila Canalini

Ejemplo:
El proceso 1 tiene dos hilos a nivel usuario. El Sistema Operativo lo ve como uno solo, como si
el proceso 1 fuera un KLT, como lo es el proceso 2.
Como son hilos a nivel usuario, cuando se bloquee uno (ULT1), se bloqueará el otro (ULT2). Es
por eso que cuando entra a E/S el U1, el U2 no puede ejecutar.

Si se usara jacketing en el instante 2, el ULT2 podría ejecutarse, porque convierte la E/S en no


bloqueante.
En los instantes 3 y 4 no ejecuta nadie porque el U1 y el U2 están bloqueados y el P2 todavía no
llegó. Ahí entonces el Sistema Operativo ejecuta un proceso IDLE que hace rutinas al nivel SO.
Este proceso es un programa que hace el Sistema Operativo y lo único que hace es no hacer
nada. Cuando nadie está ejecutando, el sistema operativo lo pone a ejecutar. El mismo está
siempre en la cola de ready, pero es el de la prioridad más baja, por eso solo se ejecuta si nadie
ejecuta. Esto es porque siempre debe haber algo ejecutando en el procesador. Lo mismo ocurre
en el instante 5.
En el instante 9 están listos para ejecutar tanto el U1 como el U2, pero ejecuta el U2 por SJF.
En el instante 11, el U2 termina de ejecutar y ahora están disponibles el U1 y el P2. Por SJF,
pensaríamos que sigue el P2, porque tiene 1 ráfaga de CPU mientras que el U1 tiene 2, pero
como el U1 y el U2 son hilos de un mismo proceso, el P1 está ejecutando, y por más que el U2
terminó, el sistema operativo no se entera de que termino un hilo y va a cambiar a otro. Para el
sistema operativo sigue ejecutando el mismo proceso, por eso sigue con U1.
Por lo tanto, a menos que haya una E/S, los hilos de un proceso se ejecutarán uno tras otro.
El que planifica un proceso que tiene hilos de usuario, es la biblioteca de usuario.
Cuando se bloquea un ULT, se bloquea todo el proceso al que pertenece dicho hilo. Distinto es
si el hilo es KLT.
02/05/2020

Arquitectura de Kernel
El Sistema Operativo es un sistema grande y complejo. Es apropiado dividirlo en componentes
más pequeños. El Kernel es el componente básico que tienen los SO.

31
Lucila Canalini

Tipos de arquitectura:
La primera que apareció fue la MONOLÍTICA. Se la denomina así porque
tiene un solo código, y este se ejecuta en modo kernel, formando todas las
funcionalidades parte de un mismo programa. Si bien está dividido en
módulos (uno para planificación, otro para E/S, etc.), desde cualquier
modulo se puede acceder a cualquier estructura que puede haber en otro
modulo. Así, sus módulos están fuertemente acoplados porque todo
corresponde a un gran programa. Tengo todo disponible en el lugar
correcto, y si quiero algo no necesito mandar un mensaje. Se vuelve muy
difícil de mantener porque si hago un cambio en un módulo, puede afectar
a otro.
La velocidad de acceder de un módulo a otro y obtener información de un momento a otro es
lo que hace que Windows y Linux lo sigan eligiendo, por más que no sea tan robusto.
Con la intención de acomodar dicho kernel monolítico, se creó la
arquitectura en CAPAS. A medida que se va subiendo en capas, se va
pasando por los diferentes módulos que tiene el sistema operativo. Las
capas más bajas serían las más relacionadas con el hardware y las que se
encuentran más arriba son las relacionadas con los usuarios y los
procesos.
También ejecuta en modo kernel, pero la relación entre los módulos no
es como el de la arquitectura monolítica, porque para que los módulos se
puedan comunicar, deben hacerlo a través de sus capas intermedias. Esto
es porque un módulo solo se puede comunicar con módulos adyacentes. Así, la mejora sería que
existen interfaces bien definidas en cada capa, y mientras se hagan cambios en los módulos y
se respeten interfaces, se respetaran los protocolos de comunicación entre las capas y no habría
problemas a la hora de solicitar recursos o hacer consultas a otros módulos del Sistema
Operativo. Sigue siendo un sistema muy grande ejecutando en modo kernel.
Sin embargo, un estudio reveló que cada mil líneas de código,
cincuenta tenían errores. Surgió entonces la arquitectura
MICROKERNEL. Así, decidieron reducir el kernel al máximo. Las
cosas más importantes (esenciales) ejecutarían en modo kernel y
las no tan importantes en modo usuario. En caso de que se
necesitara información, se manda un mensaje a cierto modulo para
que devuelva el valor necesario.
Entre sus ventajas en comparación a las otras arquitecturas, son
fáciles para agregarles funcionalidad. Además, es más robusto y confiable que un kernel
monolítico. Como parte de la funcionalidad del Sistema Operativo que se ejecuta en modo
usuario, es menos probable que ocurran errores graves.
Entre sus desventajas, el paso de mensajes genera un gran volumen de mensajería porque se
comunican con el MicroKernel para hacerlo, y se genera un gran armado de paquetes.

32
Lucila Canalini

Hoy en día se menciona que se usa el monolítico por un lado y el MicroKernel por el otro. Tanto
Windows como Linux se basan en la arquitectura monolítica. Por el otro lado, el sistema
operativo de Mac utiliza la arquitectura MicroKernel, porque tomaron un diseño anterior.
El lenguaje más usado para hacer sistemas operativos es C.
08/05/2020

Concurrencia
Multiprogramación: Cantidad de procesos que se admiten para poder ejecutar. Es un
parámetro que define el sistema.
Multiprocesamiento: Tener varios CPU corriendo, con lo cual me permite correr varios
procesos que están en memoria. Sirve para tener varios hilos corriendo. El multiprocesamiento
implica un sistema que posee varios procesadores. Teniendo en cuenta que sólo puede
ejecutarse un proceso por procesador, entonces existe multiprogramación.
Compartir recursos: Voy a tener datos o información input que requieran ser compartidas
entre procesos o hilos para poder tener un resultado final. El sistema operativo administra los
recursos, asignándolos a cada proceso. Pero es responsabilidad del programador resolver las
cuestiones de concurrencia en secciones críticas y del ordenamiento en la ejecución de los
procesos, para evitar condiciones de carrera.
Competir por recursos: Ver quien llega primero y toma el recurso compartido. Si no me
prevengo que haya dicha competencia y la forma en que lo toma, y que de alguna manera no
genere incoherencias, mi programa devolverá cualquier cosa.
Condición de carrera: Es una condición para ver quien llega primero a la meta. Quien tomara
un recurso primero. Estas condiciones de carrera se producen en secciones críticas.
Sección crítica: Aquel espacio en el código en el cual se hace uso de un recurso visible por los
diferentes procesos y que, en caso de ser escrito o manipulado, cambiando su valor interno de
alguna forma, será una sección critica. Esto es porque si no tenemos en cuenta un mecanismo
que intenta modificarlo, si no lo impedimos podremos tener incoherencias. Más aún si es
modificado de manera concurrente.

Interacción entre procesos/hilos


La interacción de procesos puede ser de varias maneras:

 Comunicación entre procesos: Que haya datos de un proceso a otro para que puedan
seguir trabajando.
 Competencia de los procesos por recursos.
 Cooperación de los procesos vía compartición: Podemos tener que los procesos se
comuniquen compartiendo recursos (archivos, pagina en memoria, buffer, etc.). Estos
son espacios que tienen en común los procesos, y van poniendo valores, y pueden ir
pisando los datos. El trabajo concurrente entre los mismos no debería traer
incoherencias. Por ejemplo: Variable global. En la compartición, un proceso puede no
conocer al otro, a diferencia de la comunicación.

33
Lucila Canalini

 Cooperación de los procesos vía comunicación: La comunicación implica


protocolado. Es comunicación de procesos mediante red. Comunicar de un proceso a
otro si hay cambios. Por ejemplo: A través de sockets.

Sección crítica
Es un pedazo de código con ciertas instrucciones. Para que no haya
incoherencias, hay requisitos que deben cumplirse: exclusión mutua,
progreso, espera limitada y velocidad relativa.

 Exclusión mutua: Dentro de la sección critica puede haber un único proceso/hilo


ejecutando y trabajando sobre el recurso. No puede haber más de uno ejecutando al
mismo tiempo. La mutua exclusión corta la multiprogramación dentro de una sección
crítica, por lo tanto, la performance se reduce para asegurar la integridad de los datos.
Debido a que representa una pérdida de performance, es deseable, y no obligatorio, que
un proceso esté un tiempo reducido en la sección crítica.
 Progreso: Si hay un proceso/hilo ejecutando en la sección critica, los que están
esperando deben poder ejecutar una vez que termine este. De esta forma, que no se
quede con la sección critica para sí mismo. No perjudicar al resto de los procesos.
 Espera limitada: Siguiendo el punto anterior, que pueda ejecutar rápido. Si están
esperando varios hilos para empezar a ejecutar, que el que está ejecutando no haga que
mueran por inanición los que esperan por tardar tanto.
 Velocidad relativa: El código de entrada y de salida para la sección critica debe tener
cierta velocidad y que haga que el proceso no sea tan lento.

Posibles soluciones
 De Software.
Todas las soluciones de software presentan el problema de la espera activa, haciendo un uso
intenso del procesador. Es por esto que la performance es un factor clave que les juega en
contra.
La espera activa (while(turno!=0)) hace que los valores del procesador se vayan a la mierda (no
encontré otra palabra para decirlo).
Soluciones que cumplen con los requisitos de la sección crítica: Algoritmo de Dekker y
Algoritmo de Peterson. Nos permiten generar secciones críticas bien resguardadas. Son
soluciones que garantizan la mutua exclusión.

34
Lucila Canalini

Ejemplo del Algoritmo de Peterson:

 Hardware. Software desde el lado del procesador.


A diferencia de las instrucciones de software, que el problema era que se interrumpía en la
mitad, acá no pasará eso.
Una de las opciones es deshabilitar interrupciones. Las interrupciones siempre se chequean
al final del ciclo de instrucción, por lo cual, si se las deshabilita, podemos hacer que el
planificador las sacara del procesador. Esto es en un sistema monoprocesador únicamente.
Para lograr esto hay que, en la parte del código de entrada, deshabilitar las interrupciones, y
dentro de todas las sentencias de la sección critica, no podré ser sacado del procesador (no me
podrán re planificar), y tendré la certeza de que el recurso compartido no lo tocará otro, y
cuando salga de la sección crítica volveré a activar las interrupciones. Esta es una operación
privilegiada, por lo que estará atado a que este tipo de soluciones las provea el Sistema
Operativo, o que directamente sea poco factible implementarla.
Deshabilitar las interrupciones asegura la mutua exclusión, pero corta con la
multiprogramación y con la atención de interrupciones. Además, es difícil de implementar en
sistemas con multiprocesamiento. El uso de las instrucciones test and set es seguro ya que no
pueden ser interrumpidas.
Esto conviene usarlo cuando la mayoría de los procesos compartan recursos.
También hay instrucciones especiales de procesador. Lo especial es que permiten hacer
operaciones atómicas y que no puedan ser interrumpidas. Entre estas instrucciones tenemos el
test and set, y el Exchange.
La primera testea el valor que uno le da por defecto si en una determinada posición de memoria
devuelve algo. Lo hace de manera atómica y, así, el chequeo será más rápido por hacerlo en una
única instrucción del procesador.
La segunda, lo que hace es lo siguiente (y sigue teniendo el problema de la espera activa):

35
Lucila Canalini

 Provistas por el SO: Semáforos.


Son los más simples de utilizar y permite la exclusión mutua entre varios procesos, sincronizar
u ordenar varios procesos, y controlar acceso a recursos.
Son utilizados mediante wait(s) y signal(s). Wait se utiliza para la barrera de entrada, haciendo
un chequeo interno de si puede acceder o no (si no bloquea). Por el otro lado, Signal es la
barrera de salida. Signal decrementa el valor del semáforo en 1, y luego desbloquea un proceso
si el valor quedo en cero o negativo. En caso que el valor del semáforo quedase en un valor
positivo, significa que no hay procesos bloqueados en la cola del semáforo. Las funciones de
wait() y signal() son syscalls, y las mismas siempre se realizan con un cambio de modo.
Lo provee el sistema operativo.
El semáforo está compuesto por un valor entero y una lista de procesos bloqueados. El primero
es un contador que hace referencia a los recursos o básicamente dice si se ingresó o no a la
sección critica. La segunda es una lista de los procesos bloqueados cuando el wait no deja pasar
al proceso. Los procesos de esta lista se despiertan de a uno y ejecutan después de la instrucción
de wait.
Los semáforos son estructuras globales y, por lo tanto, compartidas (como ya mencionamos,
una variable numérica y una lista o cola) que pueden ser modificados por varios procesos o
hilos a la vez, por lo tanto, debe asegurarse la mutua exclusión. La manera de realizarlo es a
través de las soluciones de software y hardware. Si bien algunas de estas presentan espera
activa, la sección crítica del semáforo es relativamente chica y no afecta tanto la performance.
Son una buena solución a la sección crítica porque cumple con mutua exclusión ya que sólo
un proceso podrá adquirir el semáforo a la vez, el resto se quedarán bloqueados. Cumple
progreso ya que los únicos que pueden afectar que un proceso pueda adquirir el semáforo son
los que también están realizando el wait. Cumple con espera limitada ya que los procesos se
bloquearán en una cola de dicho semáforo y luego se irán despertando a medida que se haga
signal respetando el orden de bloqueo. No depende de la velocidad de los procesos. Los wait y
signal operan sobre los semáforos que son compartidos, por lo que también tienen una región
crítica.
Para que el Sistema Operativo logre que sus syscalls, wait y signal sean atómicas, este podría
usar una técnica de HW como por ejemplo testAndSet.

36
Lucila Canalini

Funciones de los semáforos:


 Iniciar/Finalizar un semáforo: Le asigno el valor y los recursos que deba asignar, y al
final los libero.
 wait(sem): Decrementa en uno el valor del semáforo.
 signal(sem): Incrementa en uno el valor del semáforo.

Los semáforos son recursos del sistema y son limitados. Debe declararse uno por cada recurso
compartido (variable global, impresora, scanner, etc.). Hay que inicializarlo siempre para poder
hacer uso del wait y el signal. Se inicializa según la cantidad de instancias que se tienen de dicho
recurso, a menos que sea una variable global, que en dicho caso se la inicializa en 1.
Dependiendo de lo que se desee hacer, también puede inicializarse en 0, pero nunca en número
negativo. Dicho valor del contador implicaría que está en la cola de bloqueados si está en
negativo. Por eso el valor del semáforo va a ir cambiando a medida que haya nuevos procesos
ejecutando o bloqueados.
Hay semáforos de tipo fuerte, porque hablando de su cola de procesos bloqueados, las trabaja
con una planificación de tipo FIFO. Hay semáforos débiles, que básicamente tienen una
planificación diferente en la cola. Entonces se sacará los procesos de la cola por un criterio
distinto a FIFO.
Existen algunos tipos de semáforos que, en lugar de tener una cola de bloqueados, utilizan
espera activa. Esto tiene sentido en sistemas con multiprocesadores. Los mismos garantizan la
mutua exclusión a través de alguna solución de software (algoritmo de peterson, por ejemplo)
o usando la instrucción de hardware (como test_and_set). Tienen la ventaja de sirven para
sistemas multiprocesador sin generar overhead extra (como sí lo haría el deshabilitar las
interrupciones). Tienen la desventaja de generar una pequeña carga de espera activa.
Existen distintos tipos de semáforos. Hay generales o de contador, y después hay binarios.
Los generales o de contador (N instancias) son los que pueden tener un valor mayor a uno y
puede ser casi infinito. N dependerá de la cantidad de dicho recurso que se tiene disponible.
Los binarios, que son aquellos en los que ponemos valores entre 0 y 1 para representar un
recurso o para intentar representar esa sección critica en la que vamos a utilizar semáforos.

37
Lucila Canalini

Existen tres tipos de semáforos:


1. Contadores: representan instancias de un recurso. Pueden tener cualquier valor,
siempre y cuando sean números enteros.
2. Binarios: representan dos estados (cero o uno, libre u ocupado). Se utilizan para
permitir o prohibir a un proceso avanzar.
3. Mutex: son un caso particular de los binarios. Se utilizan para garantizar mutua
exclusión sobre un recurso o región crítica.
Para un productor consumidor infinito necesitaríamos un semáforo mutex que proteja el buffer
compartido y un semáforo contador que lleve un registro de la cantidad de mensajes en el
buffer. De esa forma, un consumidor no intentará retirar un mensaje si no hay ninguno aún, y
el productor lo incrementará ante cada nuevo mensaje.
Utilidades:
 Acceso a recursos (N instancias)

Ejemplo: Sistema con tres procesos sincronizados mediante semáforos sabiendo que hay 3
impresoras, 2 scanners y una variable compartida.
Así, declaro un semáforo para el uso de la impresora (inicializado en 3), un semáforo para el
uso del scanner (inicializado en 2), y un semáforo para la variable global (inicializado en 1, pero
no porque haya una sola, sino porque cada variable global se inicializa siempre en 1).

 Exclusión mutua

38
Lucila Canalini

Ejemplo: Como existen dos variables compartidas, declaro dos semáforos distintos (uno para
cada una), y ambos se inicializan en 0. Si inicializara un único semáforo, se bloquearía un
proceso usando una de las variables cuando en realidad si puede usarla porque el otro no la
está usando.

 Sincronizar

Ejemplo: Dos procesos A, B y C sincronizados para que ejecuten A, B, C, A, B, C.

 Provistas por los lenguajes de programación: Monitores.


Los monitores son soluciones provistas por algunos lenguajes de programación que permiten
resolver problemas de mutua exclusión y de coordinación.
Solo algunos lenguajes de programación los proveen. Suelen utilizarse en lenguajes de
programación orientados a objetos, los cuales aprovechan la característica de encapsulamiento
para el acceso a los datos compartidos.

39
Lucila Canalini

No dependemos del sistema operativo. Tiene


internamente estructuras abstractas y las primitivas se
encargan de las secciones críticas. Se ve más complejo
que un semáforo, pero cuando se lo implementa es más
simple.
El monitor internamente tiene su propia área con
datos y variables de condición.
Únicamente un proceso o hilo puede estar utilizando el
monitor en un determinado momento.
Las variables de condición serán de barrera para ver si
se puede seguir ejecutando o habrá que bloquearse. Si
pasa esto último, pasara el proceso/hilo a la cola de
procesos bloqueados.
Tiene como ventaja que será más simple utilizarlos porque es más natural programar usando
monitores que usando semáforos.
15/05/2020
Todos los procesos con los que trabajamos cumplen las acciones de solicitar un recurso, usarlo
y liberarlo. El uso de estos recursos lo hacen a través de syscalls. Si un proceso solicita un
recurso y este no está disponible, el proceso debe bloquearse hasta que el recurso esté listo.

Deadlock
Bloqueo permanente de un conjunto procesos donde cada uno de estos procesos está
esperando un evento que sólo puede generar un proceso del conjunto.
Esto quiere decir que, habrá un conjunto de procesos bloqueados indefinidamente. Un proceso
espera que otro haga un signal, este último está esperando que otro haga un signal, y así. Todos
los procesos están esperando a otro a que haga un signal y no va a pasar porque están todos
bloqueados.
El Deadlock (o en español Interbloqueo) es un problema que se presenta en algunas ocasiones
cuando existe una mala sincronización o cuando no hay sincronización. Que ocurra o no puede
depender del orden en que se selecciona un proceso para que utilice el procesador.

Una vez ocurrido el Deadlock entre algunos procesos, esos permanecerán bloqueados
indefinidamente. El resto de los procesos, que no participan del Deadlock y que no comparten
recursos con los procesos involucrados en él, no se ven afectados.
El motivo del bloque indefinido es que un proceso de ese grupo, esta solicita un recurso que se
encuentra asignado a otro proceso del grupo. A su vez, el segundo proceso mencionada solicita
un recurso que fue asignado al primero.

40
Lucila Canalini

Tipos de recursos
 Reutilizables: El proceso solicita el recurso, lo usa, lo libera, y después otro proceso
puede volver a usarlo. Se puede modificar, pero seguirá disponible.
Ejemplo: Un archivo (a menos que se lo borre), una variable global, un semáforo, etc.
 Consumibles: Recursos que los puedo usar una única vez porque una vez que se usa se
consume y se deshace. No son tan comunes como los reutilizables.
Ejemplo: Una interrupción, un mensaje en un socket. Una vez que se envía y se recibe,
ese mensaje se lo queda a menos que lo reenvíe. No estar más en el buffer para ser leído.

Grafo de asignación de recursos


Permite representar el estado del sistema con respecto a la asignación de los recursos a cada
proceso en un momento determinado.
Es un grafo que muestra el estado con respecto a qué procesos tienen asignados qué recursos
actuales del sistema. Tengo que saber cuáles procesos tengo y que recursos asigne a cada uno.

El recurso con tres instancias son tres recursos que no son diferenciables entre sí, sino que los
voy a usar para la misma tarea. Si tengo tres impresoras, y me da lo mismo en cual imprimir,
son el mismo recurso.
Si yo tengo una arista entre el proceso 1 hacia el recurso, significa que estoy solicitando cierta
cantidad de un recurso. Según la cantidad de flechas, es la cantidad de instancias de dicho
recurso que solicito.
Si la flecha va desde el recurso hacia el proceso, quiere decir que dicho recurso ya está asignado
al proceso.
Ejemplo 1: Foto actual del estado del sistema. Va cambiando constantemente.

41
Lucila Canalini

Ciclos
El sentido de las flechas es muy importante para determinar si hay un ciclo o no.
a) Si no hay ciclos, podemos asegurar que en ese instante no hay Deadlock.
b) Si hay un ciclo en el grafo, puede implicar la existencia de Deadlock.
c) Si hay un ciclo y además todos los recursos son de una sola instancia, entonces hay
Deadlock. Única manera de asegurarlo.

Condiciones para la existencia de Deadlock


Se tienen que dar simultáneamente las cuatro condiciones para decir que existe Deadlock. Con
que falte una ya no habrá Deadlock.

Condiciones necesarias:
Si no hay mutua exclusión, los procesos no se bloquearían. Ingresarían todos a la sección
critica, pero habría condición de carrera.
La retención y espera de recursos. Un proceso que ya tenga un recurso asignado y este
solicitando otro. Consiste en que los procesos tienen la facultad de solicitar un recurso, luego el
sistema operativo se lo asigna y mientras lo tiene asignado tiene la posibilidad de solicitar otro.
Si un proceso tiene la facultad de desalojar un recurso del otro proceso, entonces no habrá
problemas para tomarlo. Si el sistema no tiene la política de sacar un recurso a la fuerza de un
proceso, entonces será sin desalojo de recursos. Solo se deja de usar el recurso cuando el
proceso lo libera.

Suficiente:
Espera circular. Es consecuencia de las tres condiciones necesarias.
Cada proceso del mismo (ciclo) está esperando que otro proceso del
mismo grupo libere un recurso.

Tratamiento del Deadlock


Se pueden dividir en dos estrategias: estrategias para que nunca ocurra Deadlock y estrategias
en la que puede ocurrir Deadlock.

1. Prevención de Deadlock
Ataca un poco las condiciones mencionadas. Como es necesario que se cumplan las cuatro,
haciendo que una no se cumpla, evitaremos que ocurra Deadlock. Los inconvenientes que tiene
esta técnica son las restricciones que tienen los procesos al momento de pedir recursos.
Los programas no son quienes restringen la manera que tienen los procesos de asignar
recursos, sino que este es el Sistema Operativo.
Para evitar que haya mutua exclusión es generar condiciones de carrera, pero hará que haya
resultados incoherentes. Hay casos en los que estamos seguros que se puedan compartir los
recursos, como cuando son solo de lectura, entonces ahí no se necesita que los recursos tengan
mutua exclusión. Pero si dicha variable es modificable, se vuelve difícil evitarla.

42
Lucila Canalini

Para evitar que haya retención y espera, hay solo dos maneras. Los procesos están muy
afectados a la hora de solicitar recursos. Una es que el Sistema Operativo obligue a los procesos
a que soliciten todos los recursos juntos. La otra es pedirlos de a uno, usarlos y liberarlos,
constantemente. O pedirlos de a grupo. Solicitándolos de a uno o varios, siempre y cuando se
asegure que los va a utilizar y liberar.
Existen dos formas de hacer que haya desalojo de recursos. Una es si un proceso tiene
recursos asignados, solicita uno que no está disponible, entonces debe liberar el resto de los
recursos que sí tiene. La otra es si un proceso A solicita un recurso que está asignado a otro
proceso B que está a la espera de más de recursos, entonces el recurso asignado al proceso B
puede asignarse al proceso A.
El problema es que cuando me bloqueo para buscar el recurso y me lo sacan, me voy a
desbloquear, pero no voy a tener dicho recurso, por lo que me bloquearé de nuevo. Esto puede
causar inanición. Este tipo de estrategias se suele utilizar con recursos que pueden volver al
estado anterior, como lo es por ejemplo una variable, pero con un archivo no sería tan fácil.
Para evitar que haya espera circular se puede asignar un numero de
orden a los recursos. Estos solo pueden solicitarse en orden creciente.
Dicho orden no podrá alterarse.
Un ejemplo de uso podría ser una computadora de un avión, donde las consecuencias de la
ocurrencia del deadlock podrían ser fatales.
Cuando las tareas son muy relevantes, hay que asegurarnos que no haya deadlock. Esto lo
podemos hacer con la estrategia de prevención o con la estrategia de detección de deadlock. Si
existe alto overhead en el sistema en el momento, lo mejor sería utilizar la estrategia de
prevención, porque la de evasión agrega mucho overhead, y como ya contamos con un alto nivel
de overhead, no sería conveniente agregar más.

2. Evasión o predicción de Deadlock


Garantiza que no ocurrirá Deadlock, al igual que la estrategia anterior. Tiene el problema de
que genera una baja utilización de recursos. El Sistema Operativo puede negar la utilización de
recursos cuando cree que se puede producir un Deadlock si entregase el recurso.
De todas las soluciones, la de evasión es la que más overhead genera. Cada vez que hay una
asignación de recursos, hay que hacerle a procesador calcule las matrices y si el estado es
seguro o no.
Existen dos técnicas. Una es denegar el inicio del proceso, y otra es denegar la asignación de un
recurso (algoritmo del banquero). En ambas técnicas necesitan que los procesos antes de iniciar
la ejecución, declaren las necesidades máximas que utilizaran en la ejecución.
Es por esto que una de las técnicas es que si esas necesidades máximas, más las necesidades
básicas de todos los procesos ejecutando, es mayor a la cantidad del recurso que hay en el
sistema, entonces el sistema no permite que inicie.
Puede generar inanición porque no se sabe cuándo van a terminar los otros procesos, y hasta
que no terminen de ejecutar, el proceso que quiere usar cierto recurso no va a poder ejecutar
nunca.

43
Lucila Canalini

Ambas estrategias de evasión tienen un enfoque pesimista. En cuanto a la Detección, tiene más
overhead porque con cada solicitud es necesario verificar si hay estado inseguro. El algoritmo
de detección se dispara cada cierto tiempo o evento. La estrategia de evasión tiene un enfoque
pesimista porque "ante la duda" deniega la solicitud.
No tenemos la seguridad de que la solicitud denegada iba a producir un Deadlock. Por eso
decimos que es pesimista.
Denegar el inicio de un proceso:

Denegar la asignación de un recurso:


La estrategia de evasión deniega la solicitud de un recurso cuando se detecta que dicha solicitud
produciría un Estado Inseguro. Por estado inseguro decimos que se trata de un estado del
sistema en el cual podría ocurrir un Deadlock.
Algoritmo del banquero
El SO puede asignar el recurso al proceso que lo solicito y no habrá deadlock.
En estado inseguro, no se asigna el recurso al proceso porque podría existir deadlock. No
asegura que haya Deadlock, pero existe la posibilidad. Ante esa duda, no asigna el recurso, y se
asegura de que todos los procesos puedan finalizar. Una vez que se define que hay estado
seguro, el sistema nunca podría quedar en estado inseguro, debido a que la estrategia consiste
en no otorgar recursos que pudieran dejarlo en dicha situación n.
En el estado seguro, se asigna el recurso al proceso. El algoritmo del banquero siempre está en
estado seguro. Simula que entrego el recurso al proceso que lo está pidiendo, y analiza si existe
una secuencia en que todos los procesos puedan finalizar. Entonces si existe, se define que es
un estado seguro y de asigna el recurso. En caso contrario, llega a la conclusión de que se puede
llegar a un estado inseguro y no se asigna el recurso, manteniendo el estado seguro previo.

Las necesidades máximas son datos que el proceso declara al sistema operativo antes de
ingresar o cuando ingresa. Asegura que no usara más recursos que los definidos.
Los recursos asignados irán cambiando a medida que se vayan asignando recursos, a diferencia
de las necesidades máximas que serán inamovibles durante toda la ejecución.
A partir de esta información, se tiene todo lo necesario para definir si hay estado seguro o no.

44
Lucila Canalini

Se restan las necesidades máximas y los recursos asignados para conseguir las necesidades
pendientes.

Se simula la asignación del recurso y se aplica el algoritmo de seguridad. La simulación se


empieza con los recursos disponibles, y esta matriz se va modificando a medida que finaliza un
proceso y libera los recursos que tenía asignados.
Si todos los procesos liberan los recursos, entonces mis recursos disponibles, una vez que
termina la simulación, debería ser igual a los recursos totales. Esto sirve como validación si está
bien hecha la simulación.
Si se desea que, si o si no se genere deadlock, entonces las cuatro estrategias se reducen a dos:
prevención o evasión. Si se requiere flexibilidad para los usuarios a la hora de buscar los
recursos, convendría usar la estrategia que dé más flexibilidad al momento de usar recursos.
Esta sería la de evasión, porque la de prevención restringe a la hora de solicitar recursos. En la
de evasión se pueden pedir todos los recursos que se quieran, pero el algoritmo decidirá si
entrega el recurso o no.

3. Detección y recuperación de Deadlock


Estrategias en la que puede ocurrir Deadlock y luego se evalúa qué hacer. No hay restricciones
para asignar recursos disponibles. Recurso que se pide, si está disponible, se asignara al
proceso, sin análisis previo. Periódicamente se ejecuta el Algoritmo de Detección para
determinar la existencia de Deadlock. No se ejecuta con cada asignación, sino que se podrá
ejecutar en diferentes momentos.
Parecería que no es necesario detectar Deadlock en sistemas caseros. En sistemas críticos
preferiríamos que nunca ocurran.
Cuando se utiliza la estrategia de Detección existe la posibilidad de que se produzca un
Deadlock. Esta estrategia permite detectar si en el sistema hay Deadlock en un determinado
momento.
Cuando las tareas son relevantes y acceden muchísimos usuarios, la mejor opción sería la de
detección y recuperación. Tiene overhead, pero no tanto, y se utilizara cuando los recursos

45
Lucila Canalini

estén en mayor aprovechamiento, lo que no es todo el tiempo. Por ejemplo, en una red social,
hay horas pico. Por lo que está bueno que haya un algoritmo que este todo el tiempo revisando
si se produjo deadlock o si se va a producir.
Opciones de Recuperación:

 Terminar procesos involucrados.


 Retroceder el proceso a un estado anterior. No siempre es fácil.
 Terminar algún proceso involucrado hasta que deje de existir Deadlock.
 Expropiar recursos hasta que no exista Deadlock. El problema es que, si
expropiamos recursos que luego un proceso querrá utilizar nuevamente, no estará en
el mismo estado y quizás ya no le sirve de esa forma.
Lo más recomendable es finalizar la menor cantidad de procesos posibles.
En una situación de deadlock, matar a todos los procesos involucrados es una solución “barata”
a nivel de no tener que determinar cuál es más conveniente pero no siempre soluciona el
problema. Además, el impacto es muy alto ya que se pierde el avance de todos los procesos a
diferencia de finalizar sólo uno o desalojar recursos.
Criterios de selección de procesos para terminar o expropiar:

 Menor tiempo de procesador consumido.


 Menor cantidad de salida producida.
 Mayor tiempo restante estimado.
 Menor número total de recursos asignados.
 Menor prioridad.

En el proceso 4 ya se sabe que no habrá Deadlock porque no tiene recursos asignados. Por lo
que se lo descartará del análisis desde un principio.
Si no puedo finalizar, entonces todos los que quedaron de esta forma se dirá que están en
Deadlock. Y el recurso que marcamos al principio tampoco podría finalizar, pero no está en
Deadlock, está en inanición por culpa del Deadlock del proceso 1 y el proceso 3.
La recuperación no necesariamente debe ser hecha por el Sistema Operativo. La puedo hacer
yo.

46
Lucila Canalini

Un ejemplo de uso de esta estrategia podría ser una base de datos transaccional, donde los
deadlocks deberían resolverse, pero es más importante la performance del sistema.
4. No hacer nada
La estrategia integrada es la de agrupación de recursos y a cada grupo se le aplica alguna de las
técnicas. Hay que evaluar si prefiero overhead y que no haya Deadlock, o al revés.
Si las tareas que se llevan a cabo, siendo estas las que generan deadlock, no son muy relevantes,
entonces no hacer nada, es decir. No tratar el deadlock, sería la mejor estrategia contra la
posible ocurrencia de tal.

Livelock
Es cuando los procesos avanzan y retroceden constantemente. Es decir, resuelven su Deadlock
y vuelven a dicho estado bloqueado, y así constantemente. También puede ser un problema
permanente. Sus procesos están constantemente intentando avanzar y volviendo para atrás. Un
proceso quiere usar un recurso, pero decide no hacerlo para que lo use otro. Todos los procesos
están haciendo esto, y usan el procesador en abundantemente, a diferencia del Deadlock.
Un bloqueo Livelock consume procesador. Los procesos están constantemente consultando si
pueden utilizar los recursos que solicitan. En cuanto a que los procesos puedan continuar
ejecutando sus instrucciones, es tan grave como el Deadlock. Pero en cuanto al estado general
del sistema, es peor que el Deadlock.
En el Deadlock los procesos quedan estado bloqueado y no vuelven a usar el procesador. En el
Livelock los procesos utilizan el procesador para consultar constantemente por la solicitud del
recurso, ocasionando que el resto de los procesos no involucrados en el Livelock compitan por
el uso del procesador con los que se encuentran en Livelock.
Si dos procesos A y B no comparten recursos, pero existe un Livelock, entonces sí comparten
un recurso, y este es el procesador.
Si el proceso A se encuentra en una situación en la que no termina de ejecutar, tenemos dos
opciones: puede haber deadlock o livelock. Si hay deadlock, el proceso A se puede bloquear
tranquilamente, dejando ejecutar al conjunto B sin problema ya que no comparten recursos.
Pero si hay livelock, el proceso A no permitiría la correcta ejecución del proceso B por estar
utilizando el CPU.
29/05/2020

Memoria real
La memoria real, o memoria física, es la memoria RAM de la computadora.
Para que un proceso o programa pueda ejecutarse, debe estar guardado en memoria. El PCB es
la parte de la memoria que pertenece al sistema operativo.
El proceso está por completo en la memoria excepto cuando se encuentran suspendidos, y están
de manera contigua.
La memoria es un array muy grande, con muchas divisiones indexadas. Cada una de estas
divisiones forman parte de un byte de la memoria. Cada posición tendrá un índice asociado.

47
Lucila Canalini

La memoria no conoce su contenido, por lo que uno puede cargar cualquier programa en la
memoria, y la memoria no sabrá lo que está cargado. Por eso es que puede cargar virus.
Las operaciones que se pueden hacer sobre la memoria son leer y escribir sobre esta. Son cosas
que suele hacer el procesador, aunque existen otros dispositivos que también pueden hacerlo.
Leer algo del procesador es mucho más rápido que leer algo de la memoria, pero la memoria
sigue siendo un componente muy rápido a comparación de otros.
La memoria tiene varios requisitos a cumplir. Los más importantes son:
 Reubicación: Característica que tiene que permitir al SO descargar un proceso de
memoria y volver a cargarlo, en el mismo lugar o en otro, sin ningún problema.
 Protección: Caso gráfico de que un proceso no puede acceder al espacio de direcciones
de otro proceso. Este es el espacio que ocupa el proceso en memoria. El único que puede
tener dicho acceso es el sistema operativo. Registro base y límite:

 Compartición: Poder permitir que dos procesos diferentes accedan a otra posición de
memoria que es diferente a ellos, pero que los dos pueden acceder. El caso ejemplo seria
cuando hablamos de variables que se comparten entre diferentes procesos y ambos
pueden modificarlos y leerlos indistintamente.
 Organización física y lógica: Organización física se refiere a que es un dispositivo de
acceso más rápido que el resto de los dispositivos. Es un dispositivo volátil donde van a
estar todos los programas que estén en uso y que se estén ejecutando. Que sea volátil
quiere decir que cuando apago la computadora, se reinicia la memoria. La organización
lógica administra cómo los procesos se almacenan en memoria y como se organizan sin
que se pisen entre sí.
¿Cómo se asignan los programas a una memoria?

48
Lucila Canalini

Cuando compilamos un programa estamos generando el ejecutable, pero pasan cosas en el


medio. Primero la compilación, que convierte todo lo que escribimos en un programa de tipo
objeto. Traduce en el procesador todas las sentencias que escribimos. Enlaza todas las
bibliotecas que utilizamos y otras bibliotecas que pueden ser del sistema. Finalmente, la parte
de carga ocurre cuando ejecutamos el programa y se carga en forma de proceso dentro del
sistema operativo.

 Asignación en tiempo de compilación:


En este tipo de asignación, en el momento que compilamos el programa ya sabemos dónde van
a estar ubicadas las variables. El problema es que cuando hago el programa, no sé si tengo otro
programa ocupando lugar en una memoria. Entonces el proceso no lo puedo cargar hasta no
tener todas las direcciones que va a ocupar.

En la asignación de direcciones en tiempo de compilación, para una variable la dirección física


es igual a la lógica. Al momento de compilar el programa, ya se define en qué ubicación de la
memoria real estará la variable. Si esa dirección no existe en el hardware, no podrá ejecutarse
el programa.
 Asignación en tiempo de carga:
Resuelve los problemas de los tipos de asignación anteriores. Las direcciones se incluyen en un
programa ejecutable en base a algo conocido. En este ejemplo, es el inicio del programa. Ahora
puedo tener dos programas y puedo cargarlos en diferentes ubicaciones. Igualmente, sigue
teniendo el problema de que cuando cargo el programa en memoria y ya le asigno una dirección
a cada variable, durante todo el ciclo de vida del proceso, esa dirección no va a cambiar.
Entonces, cuando haya técnicas de swapping, estoy obligado a cargar los datos en la misma
posición en las que estaban antes.

49
Lucila Canalini

 Asignación en tiempo de ejecución:


La dirección de cada variable, de cada acceso a memoria que quiero hacer, la calcularé en
tiempo de ejecución. Esto es cada vez que lo necesito. En el ejemplo, la variable ‘a’ va a depender
de un inicio y de una referencia. La referencia no cambiará, pero sí cambiará la posición de
inicio. Este tipo de asignación sí me permite descargar programas al disco y luego volver a
cargarlos en distintas posiciones de memoria (reubicación).

En la asignación de direcciones en tiempo de ejecución, la MMU es quien realiza la traducción


de direcciones. Es decir, el cálculo no lo hace el sistema operativo, porque generaría mucho
overhead. Esto lo hace un dispositivo que es la Unidad de Administración de Memoria (MMU).
Convertirá la referencia que tenemos en la verdadera posición de la memoria. Traduce de la
dirección lógica (logical address) a la dirección física (physical address):
La MMU es un componente que forma parte del procesador. La idea de que lo haga el hardware
es que no sea tan lento poder acceder a una posición de memoria. El hardware siempre tiene
mejor rendimiento y hace más rápido las cosas que si lo hiciera el sistema operativo.

El hardware colabora mucho con el sistema operativo. Debe haber mucha comunicación entre
ellos, para poder administrar la memoria. El MMU es una colaboración que da el hardware para
que haya mejor rendimiento.
Tipos de direcciones en el gráfico:
Dirección relativa: Es un tipo de dirección lógica particular, pero desde un punto conocido.
Dirección lógica: Referencia a una ubicación de memoria utilizada por los procesos, son
independientes de la ubicación real en memoria. Esta dirección pasa por un proceso de
traducción para conseguir así la dirección física.
Dirección absoluta: Donde realmente se va a ubicar la dirección que estoy buscando.

50
Lucila Canalini

Maneras de cargar las bibliotecas


Enlace estático
Ventajas: Ya tengo todo disponible y consigo portabilidad.

Enlace dinámico
El código debe estar todo en memoria, incluso las bibliotecas compartidas, pero solo cargamos
una parte del programa. Dejamos pequeñas referencias dentro de nuestro programa que hace
que se cargue una biblioteca a medida que la vamos necesitando.
Las bibliotecas del sistema siguen estando en el proceso, por lo que siguen ocupando espacio
en el disco y en memoria, por lo que no es mucho mejor que el caso anterior.
Las bibliotecas que se van enlazando, se van agregando a la imagen del proceso, por lo que toda
la memoria se irá expandiendo.

Enlace dinámico (bibliotecas compartidas)


Bibliotecas que puede proveer el sistema operativo y permite que diferentes procesos puedan
acceder a distintas bibliotecas.
Mi programa ya no ocupará tanto lugar en memoria ni en disco, teniendo ventaja contra los
enlaces anteriores. Además, yo podría hacer actualizaciones en mi biblioteca compartida, sin
tener que hacer modificaciones en mi programa.

51
Lucila Canalini

Es en tiempo de ejecución el enlace dinámico porque cargaremos la biblioteca compartida a


medida que la vayamos necesitando.
No es portable porque quizás la biblioteca no está cargada en otro sistema.

¿Cómo se organiza el sistema operativo para que los procesos no se pisen entre
sí mientras utilizan la memoria?
Un proceso no puede acceder al espacio de direcciones de otro proceso, por default. Pero
existen mecanismos, como lo es la biblioteca compartida, que sí permite que dos procesos
accedan a una misma posición.
Una de las actividades/operaciones principales que tiene el sistema de gestión de la memoria
del sistema operativo tiene que ver con la carga de procesos en memoria, y cómo luego se
organizan para que no se pisen. Tener una buena gestión de memoria es que la
multiprogramación, la convivencia entre otros procesos, sea lo más eficiente posible.

Fragmentación
Fragmentación externa: Este tipo de fragmentación se genera por la aparición de huecos a
medida que voy asignando los procesos.
Fragmentación interna: Espacio de una partición que no podrá usar otro proceso. Es un
problema que puede aparecer varias veces, o en varios esquemas en los que tengamos algún
tipo de particionamiento fijo. Las particiones dinámicas no sufren fragmentación interna
debido a que se asigna a cada proceso, el espacio que necesita. La compactación es un
procedimiento que se utiliza para generar huecos más grandes en memoria para reducir la
fragmentación externa.

Particionamiento fijo
Es el más simple de todos. Se divide la memoria en particiones de tamaños fijos y contiguo. En
cada uno de estos espacios puedo cargar un solo proceso. El proceso se ubica en alguna
partición del mismo tamaño o menor que el proceso. Un proceso no puede cargarse en más de
una partición, por lo que habrá una relación de uno a uno entre el proceso y la partición.
Este esquema tiene fragmentación interna, pero no tiene problemas de fragmentación
externa.

52
Lucila Canalini

Dos maneras de organizar el particionamiento fijo. Ya no se usan porque ninguno de los dos es
muy eficiente.

 Todas las particiones del mismo tamaño: Las limitaciones de este ejemplo es que, si
tengo un proceso que ocupa más lugar que el tamaño fijado, no puedo almacenarlo.
Además, hay otro problema es que no puedo agregar procesos si ya se ocuparon todas
las particiones.
 Particiones de tamaños diferentes: Tengo número fijo de particiones, y si tengo un
proceso de 11 megas, solo podre ponerlo en la partición que tenga mínimo este tamaño,
entonces hasta que esta no se libere, no podre guardarlo. Lo mismo pasa si tengo un
proceso que usa espacio que no hay partición que pueda soportarlo.

Para este último, cuando las particiones son de diferentes tamaños, puedo tener colas para ir
asignando los procesos a cada partición. Es efectivo porque aprovecho el espacio de mejor
manera, pero podría pasar que un proceso podría ubicarlo en una partición muy grande.
Esto puede solucionarse si tengo una única cola, por lo que, si entra un proceso chico, podre
cargarlo en cualquier partición libre. Esto permitiría el multiprocesamiento al máximo.

53
Lucila Canalini

Particionamiento dinámico
A cada proceso se le va a asignar la memoria que esté disponible según lo que necesita. No tengo
una cantidad de particiones disponibles, sino que tengo toda la memoria para poder cargar
procesos, siempre y cuando haya espacio. A cada proceso le asigno exactamente lo que va a
usar. A diferencia del particionamiento fijo, este tiene fragmentación externa, pero no interna.
A medida que los procesos se cargan y se descargan en la memoria, se irán formando diferentes
huecos. Ahora tendré un inicio y un tamaño, sobre la información de la ocupación de memoria
de cada proceso.
No hay fragmentación interna porque lo que va a pasar es que no va a ocupar exactamente todos
los megas del hueco (según el caso) y el resto se convertirá en un nuevo hueco, de los megas
restantes que no ocupo el nuevo proceso.
Para saber el tamaño de un proceso, lo sabe el sistema operativo de entrada.
Con las tablas de procesos y huecos es que puedo hacer el seguimiento de los huecos de
memoria disponibles dentro del sistema operativo.

Algoritmos de ubicación cuando llega un nuevo proceso:


 Primer ajuste: Busca el primer hueco disponible desde el comienzo de la memoria.
Tiene que ver con empezar desde la posición física 0 de la memoria y buscar cual es el
primer hueco que encuentro donde puedo cargar el proceso. Si el primer hueco que
encuentra no tiene tamaño suficiente para el proceso, sigue buscando. Es el más rápido
y el que genera menos overhead.
 Siguiente ajuste: Busca el primer hueco disponible desde la posición de la última
asignación. Es igual que el primer ajuste, pero en lugar de empezar desde el principio,
empiezo a buscar huecos desde el primer ajuste que hice, sin importar si hay huecos
previos.
 Mejor ajuste: Busca el hueco más chico donde pueda ubicarse el proceso. Aprovecha lo
mejor posible la relación proceso-tamaño del hueco.
 Peor ajuste: Busca el hueco más grande donde pueda ubicarse el proceso. Hace lo
contrario al mejor ajuste.

54
Lucila Canalini

Los últimos dos tienen el problema que después de mucha carga y descarga, tendré muchos
huecos y de pequeños tamaños. Por esta razón mejor ajuste y peor ajuste son los peores
algoritmos.

Problema:

Solución:
Compactación: Aumenta el grado de multiprogramación porque permite que se puedan ubicar
más procesos al sistema. Reubica a todos los procesos en una de las esquinas de la memoria (la
parte más baja o la más alta). Así, genero huecos más grandes para que entren procesos que
antes no podían.
El problema es que no reservo espacio para ningún proceso en memoria que quiera crecer. Otro
problema es que no puedo usar la memoria mientras haga la compactación, por lo que no podré
ejecutar los procesos porque las instrucciones de los procesos se encuentran en memoria.
Entonces, no podré utilizar los procesos hasta que la compactación no termine. Por lo tanto,
habrá mucho overhead.

55
Lucila Canalini

Buddy System
Compensa desventajas de particionamiento fijo y dinámico. Para esto se asigna a los procesos
tamaños de memoria que son potencias de dos (2^n). La memoria asignada es según el tamaño
del proceso y se redondea a la siguiente potencia de dos. Tiene tanto fragmentación interna
como externa.
Buddy System sufre fragmentación interna y externa porque utiliza particiones de tamaño
fijo (potencias de 2) y porque, según como se dividan, podría ser que no queden particiones
contiguas.
Ejemplo: Tengo una memoria de 1024 MB y llega un proceso de tamaño 200 MB. Lo que tendré
que hacer es dividir mi memoria hasta llegar a tener partición de 256 MB al ser la siguiente
potencia de 2 viéndolo desde el tamaño del proceso que quiero ingresar.
La divido en 2 una vez y estará dividida en dos particiones de 512 MB. Lo divido una vez más y
tendré dos de 256 MB (porque no es necesario dividir las dos divisiones de 512 MB). Ahora
asignaré el proceso en una de las particiones de 256 MB.

Si llega uno de 100, deberé ubicarlo en una partición de 128 MB al ser esta la siguiente potencia
de 2, por lo que vuelvo a dividir. Divido la partición que me quedó de 256 MB sin ocupar, y al
tener las dos divisiones de 128, agrego el de 100 en una de ellas.
Tratamos de darle al proceso exactamente lo que necesita. Para que sea exactamente, el tamaño
del proceso debe ser potencia de 2, como lo es el proceso 4, pero no suele pasar que justo sea la
misma. Así, ayuda al problema que traía la compactación. La consolidación es tan solo un
movimiento de punteros.
La consolidación se hará siempre y es cuando se libera un espacio y se une con uno o dos
espacios libres que tiene a sus costados.

Segmentación
Primero de los esquemas donde el proceso no necesita estar contiguo en memoria para poder
cargarse. En los otros tres esquemas mencionados, necesitamos tener un hueco con la
capacidad suficiente para que el proceso pueda entrar de manera completa. En la segmentación,
el proceso se puede dividir en dos y poner una división en un hueco, y otra en otro.

56
Lucila Canalini

El proceso se divide en segmentos de tamaño variable, y cada segmento representa una parte
del proceso desde la visión del programador: código, pila, datos, biblioteca, heap.
La segmentación sufre fragmentación externa pero menos que el Particionamiento Dinámico.
Esto es debido a que al dividir los procesos en fragmentos más pequeños (segmentos), es más
probable encontrar huecos para cada uno de los segmentos del proceso. Cada segmento tendrá,
exactamente el espacio que necesita.

En la tabla de segmentos del proceso, a diferencia de las tablas que teníamos en los otros
esquemas, la cual relacionaba al proceso con el espacio de memoria que iba a utilizar según el
esquema, se tiene el inicio y el fin del segmento. El número de cada segmento de la tabla, se
relaciona con el índice de la tabla.
Muy parecido a lo que pasaba en el particionamiento dinámico, este esquema tiene
fragmentación externa. Es bueno porque se evita hacer proceso de compactación tan seguido.
Para poder calcular la dirección física, debo utilizar esta tabla de segmentos.

Este procedimiento de buscar en los datos de la tabla de segmentos y luego sumar el


desplazamiento, lo hace la MMU. Aporta la búsqueda y el cálculo. Lo que provee el sistema
operativo en este caso es la tabla.
La dirección lógica va a representar una cierta cantidad de bits, por lo que, si divido esa cantidad
de bits, tendré por un lado una cierta cantidad de bits para indicar el segmento y otra cierta
cantidad de bits para expresar lo máximo que me puedo desplazar en ese segmento.

57
Lucila Canalini

1 byte = 8 bits

Si tengo un sistema operativo de 32 bits, mis direcciones serán de 32 bits y no cambiarán hasta
que no cambie el sistema operativo.

Paginación
A diferencia de la segmentación, en la paginación se divide al proceso en partes iguales
(páginas), pero al igual que el anterior, no estará contiguo en memoria.
La memoria se divide en marcos, del mismo tamaño que las páginas, por lo que también son
fijos. Este tamaño suele ser chico. Al ser tan chico en comparación al tamaño de la memoria,
siempre se encontrará una disponible. El tamaño de cada página lo define el sistema operativo,
pero no puede elegir cualquier tamaño. El procesador indica el tamaño máximo y mínimo que
puede tener cada página. Ya de por si estos tamaños son potencias de 2.
En la última página puede que haya un pedazo que quede sin usar. Esa será la fragmentación
interna, y solo ocurrirá en la última página de cada proceso. No hay fragmentación externa.
Esto es porque cualquier página puede ir a cualquier marco que este disponible. Si no hay
disponible es otro problema.

Cada proceso tendrá su propia tabla de páginas. La MMU necesitará un acceso para leer la tabla
de páginas y determinar en qué marco de la memoria se encuentra. Luego se hará un segundo
acceso para obtener el dato solicitado. La compartición es simple. Los procesos pueden
compartir marcos de memoria, simplemente ubicando el mismo marco en tablas de páginas
diferentes.
Habrá una relacion entre cada página y el frame que ocupa, para saber en qué espacio de
memoria se encuentra la página que estoy buscando. Esta tabla es una estructura que necesito
hacer.

58
Lucila Canalini

Como dirección lógica encontaremos número de página y desplazamiento, parecido a la


direccion logica cuando el esquema utilizado es el de segmentación. Cuando traduzco a la
direccion fisica, tengo que ir al frame donde se encuentra dicha página y desplazarme la misma
cantidad de bytes dentro de ese frame.
Para saber el inicio del marco, lo que tengo que hacer es multiplicar el numero de marco por el
tamaño asignado para las páginas. Mi proceso empieza en el desplazamiento 0 de la página 0.

La cantidad de bits asignados al numero de pagina me dira la cantidad maxima de paginas por
proceso. La cantidad de bits asignados al desplazamiento, será exactamente el tamaño de la
pagina.

Si mi desplazamiento se pasa del tamaño de páginas, no habrá segmentation fault, porque mi


desplazamiento nunca superará el tamaño de la pagina, como pasaba con la segmentacion al
tener tamaños variables. Solo puede pasar si estoy en la ultima pagina del proceso. Igualmente,
no le llamamos segmentation fault a esto, sino que decimos que es un acceso a una direccion
invalida.
El concepto de page fault se utiliza para algo completamente diferente al segmentation fault, y
no indica un error. Hay page fault cuando se necesita una página que no tengo en memoria y
debo ir a buscarla a disco.
Del lado de la direccion logica hablo de procesos y del lado de la direccion fisica hablo de
la memoria real.

59
Lucila Canalini

Protección: Al estar dividido en paginas, podria pasar que, teniendo mi codigo y mi pila, quizas
me quda una pagina ocupando un poco de código y un poco de pila, se queda en el medio. Ahí,
la proteccion no es tan eficiente como lo es para la segmentacion.

Compartición: Cuando dos paginas de dos procesos distintos apuntan al mismo frame, estan
compartiendo memoria.
Tabla de marcos libres: Estructura adicional a la tabla de paginas por procesos. No es mas que
cualquier estructura que me permite diferenciar qué marco esta libre y cual esta ocupado. No
necesariamente tiene que ser un mapa de bits como en el ejemplo, por mas que sean los mas
adecuados al ser rapidos de leer.

Ejemplo de Paginacion:

Si cada pagina tiene un tamaño de 512 bytes, entonces las primeras 511 direcciones logicas
seran: 0-0, 0-1, 0-2, …, 0-511. Esto es 0 por el número de página, y el otro número es el
desplazamiento. La siguiente direccion logica sera 1-0, y la siguiente 1-1, 1-2, …, 1-511. Por lo
tanto, la direccion logica 1-258 es en realidad (1x512) + 258.
Ejemplo de un proceso: Direcciones de 4 bits y Máximo tamaño de un proceso de 16 bits.
Dividido en páginas de 4 bytes.

60
Lucila Canalini

Sabemos que la direccion es de 4 bits, y sabemos que las paginas son de 4 bytes, entonces el
tamaño de pagina es 2^2, por lo tanto, 2 bits. Para saber los bits del número de página tengo
que hacer direccion logica = numero de pagina – offset, osea, que si la dirección lógica es de 4
bits y mi tamaño de página es de 2 bits, tendré otros 2 bits para el numero de pagina.
Si la paginación fuese jerárquica de 2 niveles, entonces la direccion logica no seria la misma.
El numero de pagina se dividiria en dos, por lo tanto, será 1 bit para cada uno. Hay que hacer
tres accesos, mientras que antes eran solo dos. Es util para cuando el proceso tiene muchas
paginas.

Segmentación paginada
Los procesos se dividen en segmentos como ocurría en la segmentación, los cuales podían tener
tamaños variables. A su vez, esos segmentos se dividiran en paginas, de tamaño fijo. Combina
las ventajas de la segmentacion y las de la paginacion. Así, me quedo con un poco de
fragmentacion interna pero sin fragmentacion externa. Tiene el problema extra que para
llegar a una posicion de memoria hay que hacer mucha busqueda, teniendo menos rendimiento.

61
Lucila Canalini

La direccion logica se dividira en tres posiciones: numero de segmento, numero de pagina, y


desplazamiento. Por cada segmento perteneciente al proceso, tendremos una tabla de páginas.

En la segmentación paginada la dirección lógica contiene un índice a una tabla de segmentos y


otro a una tabla de páginas. No sufre fragmentación externa porque divide a toda la memoria
en marcos. Además genera fragmentación interna en la última página de cada segmento.
05/06/2020

Memoria virtual
La memoria virtual el es espacio de memoria secundaria (el disco) que puede ser direccionado
como si fuese memoria real. Hoy en dia, la falta de memoria no es un problema tan caro.
Nos permite agrandar nuestra memoria. Para hacer esto, necesita dos características. Una es la
traducción de direcciones, que si o si se debe calcular en tiempo de ejecucion. La otra es que
el proceso debe estar dividido en partes (paginas o segmentos). Constantemente estaremos
pasando partes de un proceso en disco (es decir, memoria virtual) a memoria principal.
Necesito que cuando los procesos vuelvan a memoria puedan entrar en diferentes lugares de la
memoria, no necesariamente al lugar donde estaban antes.
Motivaciones:

 Durante la ejecución del proceso no se usan todas sus partes (páginas o segmentos).
 Espacio reservado sin usar. Puedo usarlo para otras cosas.

Ventajas
 Un proceso puede ser más grande que la memoria principal. Esto es porque lo puedo
cargar en memoria virtual, y en memoria real solo tengo las paginas que voy
necesitando (si utilizo paginacion).
 Más procesos en memoria. Permite aumentar el grado de multiprogramacion.
 Menos restricciones para el programador.

62
Lucila Canalini

Mecanismos de búsqueda de paginas


Si el bit de presencia es 0, quiere decir que el número de marco es basura, y que el número de
página no está en memoria principal. El fallo de página no es un error, sino que dice que no
hay que buscar en memoria, sino que hay que buscar en disco, dicha página.
Ante una referencia a una página que no existe en memoria principal, es la MMU la que realiza
la interrupción. Es la encargada de realizar la traducción de direcciones.

1. Primero hay que realizar una referencia a memoria. Verificar la presencia de la


página en memoria. Si no está, entonces hay un fallo de página (Page Fault).
2. Interrupción por fallo de página. Se bloquea el proceso y mientras tanto otro proceso
puede utilizar el CPU.
3. Solicitud de página. Se determina en qué marco ubicar la página faltante. Se solicita la
página faltante (E/S).
4. Se carga la página en memoria y se produce una interrupción para que el Sistema
Operativo tome control.
5. El Sistema Operativo atiende la interrupción. Actualiza la tabla de páginas y
desbloquea al proceso (cambiando su estado a listo).
6. Se ejecuta nuevamente la instrucción que provocó el fallo de página.

Estructura de tabla de páginas


Se agrega una columna a la tabla de páginas. Esta es el bit de modificado. Si no tengo espacio de
memoria, elijo una página cargada en algún frame de la memoria para pasarlo a la memoria
virtual y traer la que necesito que está en la memoria virtual a la memoria real. Si se modifica
la página, necesito actualizar lo que tengo en memoria virtual. Pero si no, no. Por esto, el bit de
modificado me dice si se modificó. Esto es una mejora para la memoria virtual.
El rendimiento se vuelve cada vez un poco más bajo cando se usa la memoria virtual porque
debo hacer más consultas para poder acceder a la memoria.
En memoria virtual, la entrada en la tabla de páginas debería tener como mínimo dos bits: el de
presencia y modificado.

63
Lucila Canalini

Eficiencia
 Requiere más accesos a memoria.
 Requiere más accesos a disco.
 No mejora el rendimiento para la ejecución del proceso.
No es beneficioso para la ejecución del proceso en sí. Este es el costo que tengo que pagar para
poder tener las ventajas anteriormente mencionadas. La conclusión seria que no es muy
eficiente.

Principio de localidad o proximidad


Permite que la memoria virtual funcione y que no genere bajo rendimiento. El motivo es que
durante un intervalo de tiempo sólo se usan unas páginas de forma activa. No se usan todas las
páginas. A este conjunto se lo denomina localidad.

Lo que va a pasar es que en un intervalo de tiempo voy a utilizar un conjunto de páginas.


Durante ciertos intervalos de tiempo el comportamiento de los programas es el mismo, por lo
que no habrá mucho page fault.
Al inicio de cada intervalo se cargarán algunas páginas, pero en lo que dura el intervalo no se
volverá a cargar nada. Es decir, salvo al principio, no habrá fallos de páginas durante todo el
intervalo.
Conjunto residente: Conjunto de páginas que están cargadas en memoria principal.

Otras estructuras para tablas de páginas


Es una mejora de paginación y paginación segmentada. Ahora que nuestros procesos pueden
ser muy grande, puede pasar que haya muchas páginas por procesos. Puedo llegar a tener hasta
2^52 páginas y mis paginas suelen tener 4 KB según el siguiente ejemplo:

Las páginas suelen tener tamaño 2^n.

64
Lucila Canalini

Paginación jerárquica o por niveles


A la tabla de páginas la paginamos y la guardamos en memoria virtual. Con este esquema
podemos hacer que la tabla de páginas esté en memoria virtual. Por lo tanto, una tabla de
páginas de dos niveles, permite ahorrar espacio en memoria principal, ubicando partes de las
tablas de páginas en disco.
En la paginación simple tenemos una tabla de páginas donde buscamos el marco donde está la
página que necesito. Esto sigue estando, pero esta página es tan grande que ocuparía mucho
espacio en memoria. Por lo tanto, la memoria virtual permite que dividamos la tabla de páginas
en páginas.
Ahora en la nueva tabla de páginas (la principal), tendré en cada página en la que fue dividida,
un puntero a la primera página donde está la primera página de su respectiva tabla de páginas.
En la segunda página tendré un puntero al inicio de donde comienza la primera página de la
tabla de páginas de la segunda página de la tabla principal, y así.
Si la tabla de punteros queda muy grande, también podría volver a paginarla. Igualmente, por
ejemplo, Linux únicamente permite 3 niveles.

Cambiará mi dirección lógica. El puntero a tabla será un índice que apunta a alguna de las
posiciones de la tabla de punteros a tablas de páginas.
Con el número de página busco el desplazamiento dentro de la tabla de páginas, para encontrar
el marco que realmente necesito. Una vez obtenido el marco, puedo convertir la dirección lógica
en dirección física, que al igual que en la paginación, será el número de marco y el
desplazamiento.

65
Lucila Canalini

Tabla de páginas invertida


Hay una sola tabla de páginas para todos los procesos. La cantidad de entradas de la tabla es
igual a la cantidad de marcos en memoria. Por cada fila de la tabla, un marco de la memoria
real. Por lo tanto, la tabla tendrá tantas entradas como lo permita la memoria principal.
Para buscar una página que estoy necesitando, el Sistema Operativo arma la tabla de páginas
invertidas para que el MMU la recorra secuencialmente hasta que se encuentre el número de
página y el PID del proceso que la solicita, y ver en qué marco se encuentra.

Si otro proceso requiere también una página 10 pero que nada tiene que ver con la pagina 10
que solicito el proceso anterior, se puede utilizar una función de hash para hacer un acceso a la
tabla y no una búsqueda secuencial, devolviéndonos el marco donde se encuentra dicha página
de dicho proceso. Puede que la función de hash nos devuelva la misma posición que al proceso
anterior, por lo que se generaría una colisión. Para evitar esto, se agrega una nueva columna a
la tabla de páginas invertida, la cual contendrá un puntero.

TLB: Buffer de Traducción Anticipada


Componente del hardware que lo que hace es guardar entradas de la tabla de páginas. Esto sirve
principalmente para reducir la cantidad de accesos en la memoria porque hacer un acceso
a la TLB es muchísimo más rápido que hacer un acceso a la memoria. Mejora el rendimiento de
la traducción de direcciones.
Necesitamos mínimo dos accesos a memoria para acceder al dato que necesitamos: uno para
acceder a la tabla de páginas y otro para acceder a memoria y leer el dato.

66
Lucila Canalini

Siempre que se busca un marco se deberá hacer un acceso a la TLB. Si no se encuentra la página
ahí, debo hacer un acceso a la Tabla de Paginas. Al tener la TLB, obtendremos el marco que
buscamos mucho más rápido. Es una memoria cache, pero está dentro del procesador.
No guarda páginas, sino que guarda partes de la tabla de páginas, que es la información que
relaciona a la página y al número de marco para poder encontrarlo.

Si la MMU consulta a la TLB y encuentra lo que busca, se ahorrara el acceso a memoria. Lo cual
es muy beneficioso porque estamos hablando de un acceso a memoria que son nano segundos,
pero hay miles de accesos ocurriendo en un segundo. Así, mejora bastante el rendimiento
general del sistema.
El problema que tiene es que es chica. No entra toda una tabla de páginas, sino que tiene pocas
entradas.
Tanto la MMU y el Sistema Operativo pueden acceder a la TLB. La MMU entra para buscar
páginas, y el SO para actualizarlas y hacer cambios.

Diseño del Sistema Operativo


Software: Hardware:

 Políticas para la gestión de memoria  Soporta o no memoria virtual.


virtual.  Soporta o no paginación,
 Objetivo: Mejorar el rendimiento. segmentación o ambas.

Al momento de diseñar un sistema operativo tenemos que fijarnos algunas cuestiones de


hardware. Con respecto al software tiene varias políticas en cuanto a la administración de
memoria. Las políticas son de recuperación, de ubicación, de reemplazo/sustitución, del
conjunto residente y de limpieza.

67
Lucila Canalini

Política de recuperación
Esta es la política de traer paginas a memoria.
Tenemos dos técnicas al momento de iniciar la carga de un proceso de disco a memoria. Uno es
paginación bajo demanda, que es por default. Este es que cuando se genera un fallo de página,
traigo a memoria la página que necesito.
El otro es la paginación adelantada, que se basa en que cuando ocurre el fallo de página, traigo
la página que necesito y por las dudas traigo unas más. Esto es porque existe la posibilidad de
que las necesite más adelante. El disco se divide en bloques de tamaño fijo, y quizás en uno de
esos entra más de una página. Por lo tanto, cuando me traigo un bloque, me traigo varias
páginas.

Política de ubicación
Hasta el momento vimos que la memoria virtual fueron todos sobre paginación, pero la
memoria virtual también es válida cuando hablamos de segmentación pura, y esta política está
relacionada principalmente con esta.
Aquí, tendremos un segmento de memoria cuyo tamaño desconocemos, y debemos ubicar en
algún hueco de memoria. Para hacerlo, usamos los algoritmos del particionamiento dinámico:
best fit, first fit, next fit, y worst fit.
Esta política únicamente aplica a segmentación porque hay que buscar un hueco que se
ajuste al tamaño del segmento que quiero traer de disco a memoria.

Políticas de reemplazo/sustitución
Una de las más importantes al momento de diseñar el sistema
operativo.
La definición de algoritmos que me permitan elegir el marco
que será la víctima, que pasará de la memoria al disco cuando
quiera traer un marco de disco a memoria, pero no tengo más lugar
para ubicarlo.
Dichos algoritmos son, entre otros: optimo, FIFO, LRU, Clock, Clock
mejorado. El objetivo de estos algoritmos es reducir los fallos de
página.
El mejor de todos estos algoritmos es el óptimo. Lo que hace es seleccionar a la víctima a partir
de la elección a la página a la que se realizara una referencia en el futuro más lejano.
De las páginas que tengo en memoria real, llevaré una a disco para poder traer otra. Eligirá la
que no se va a utilizar en el futuro más cercano. Esto es elegir la que genere menos page fault
mas adelante.
Si bien es el que mejores resultados trae, no puede implementarse. Solo se tiene para
compararse con otros algoritmos. Esto es porque si en una situación determinada me genera
10 fallos de página el algoritmo óptimo, y encuentro otro que genera 11, puedo decir que dicho
algoritmo es bueno, porque genera casi tanto page fault como el algoritmo óptimo.

68
Lucila Canalini

En el algoritmo FIFO elijo como víctima la página que más tiempo lleva en memoria.
Lo único que necesito para implementarlo con respecto a la tabla de páginas es actualizar un
puntero a la página próxima que será reemplazada. No requiere un formato diferente ni mucha
información adicional.
El LRU (Least Recently Used) lo que hace es elegir el menos recientemente usado, es decir, el
que se usó hace más tiempo en comparación al resto de las páginas. Esto es la página que hace
más tiempo no es referenciada.
Su ventaja con respecto al FIFO es que tal vez no se usó todavía el que acaba de entrar. FIFO
sacaría el que primero llegó, por más que todavía no se haya utilizado, mientras que LRU sacaría
el que ya utilizó.
Para este algoritmo, mi tabla de página tiene que ser más compleja. Mínimamente tiene un
numero de marco, un bit de presencia, y el bit de modificado. Pero en LRU deberá tener
además el instante de referencia, para poder compararlos y elegir a la víctima.

Tiene más overhead que el resto de los algoritmos. Esto es porque tenemos una tabla que nos
indica cuándo fue utilizada cada página. Constantemente, y miles de veces por segundo, se
comparan dos números para fijarse cuál es el más grande y para ver cuál dejar.
Luego está el algoritmo de Reloj o de Segunda Oportunidad (Clock). En este algoritmo, el menos
recientemente usado (LRU), lo reduzco a lo máximo que es 1 bit. Por lo tanto, en la tabla de
páginas de un proceso, cada vez que cargue o use una página (leerla o escribirla), el bit de uso
se pondrá en 1.
Tengo un puntero y pregunto si el Bit de uso está en 0 o en 1. Así sucesivamente hasta que el
Bit de uso esté en 0. Ese será el elegido como víctima para sacar la página de memoria y llevarla
a disco.
 Si (Bit de uso == 0)  Se reemplaza el marco.
 Si (Bit de uso == 1)  Bit de Uso = 0 y se apunta al siguiente marco, volviendo a
preguntar.
Si se analizan todos y ninguno está en 0, se vuelve a empezar, por lo que, si o si encontraré uno
en 0 porque si eran 1 en la primera vuelta, los cambié a 0 antes de pasar al siguiente marco.
Su tabla de páginas tendrá una columna nueva que será el bit de uso. Dicha columna no genera
mucho overhead.

69
Lucila Canalini

Ejemplo:

Retoma el algoritmo a partir de donde se quedó la aguja del reloj. Es decir, cada vez que hay
page fault, se fijará en donde está apuntando el puntero para evaluar cuál será la víctima. Si
antes de que haya un page fault, la pagina 45 en el marco 2 se utilizó, su Bit de uso cambiará a
1, por lo que se le dará una segunda oportunidad porque se lo habría utilizado como víctima si
antes de su utilización hubiese habido un page fault.
Por cada page fault me llevo una única página a disco para hacer lugar para esta nueva página.
El algoritmo de Clock Mejorado, además de tener el Bit de uso, tendrá una columna extra que
es el Bit de modificado.
 (u=0; m=0): No accedido recientemente, no modificado.
 (u=1; m=0): Accedido recientemente, no modificado.
 (u=0; m=1): No accedido recientemente, modificado.
 (u=1; m=1): Accedido recientemente, modificado.
Estas distinciones son para que, cuando elijo una víctima que fue modificada, tengo el acceso
adicional a disco para actualizar. Entonces, tal vez me conviene elegir una que no fue
recientemente usada, y que además no haya sido modificada.
Cuando se produzca un page fault, voy a recorrer todo el reloj hasta encontrar uno que cumpla
(u=0;m=0), para seleccionarlo como víctima. Si no lo encuentra, recorre los marcos y selecciona
el primero que cumpla con (u=0;m=1). A medida que recorre, al igual que el algoritmo de Clock,
modifica el bit de uso de cada marca de 1 a 0, pero eso lo hace en la segunda vuelta, es decir,
cuando empieza a verificar si hay alguno que cumpla que (u=0;m=1). A medida que ve que no
cumple, le apaga el bit de uso. Pero cuando hace la primera vuelta verificando si alguno cumple
(u=0;m=u), no modifica nada.
Puede que tampoco encuentre a nadie durante la segunda vuelta, por lo tanto, vuelve a repetir
el primer paso, y de ser necesario, el segundo paso también. Esto asegura que se encuentre una
víctima. Cuando elijo la víctima, la saco de memoria, pongo en el mismo lugar la página que
traigo de disco, y paso mi puntero a que apunte a la siguiente posición, cosa de que cuando haya
otro page fault, empiece a evaluar desde ahí.
El overhead en comparación al algoritmo de Clock, dependerá. En el peor de los casos
tendremos que dar 4 vueltas, mientras que en el Clock en el peor de los casos tendremos que
dar 2 vueltas. Parecería que genera más overhead pero al mismo tiempo, este algoritmo analiza
si hay que hacer escrituras en disco. Entonces, tiene más overhead a la hora de usar el algoritmo,
pero me ahorro acceso a disco.

70
Lucila Canalini

Ejemplo:

Tanto para este algoritmo como para el de Clock, el puntero comienza a moverse cuando haya
page fault.

Política del conjunto residente


Hay que tener en cuenta dos cuestiones con respecto al reemplazo y el tipo de asignación. El
reemplazo tiene que ver con que si la página victima la voy a buscar dentro del conjunto
residente, o dentro del conjunto residente de cualquier proceso.
La asignación de refiere a la cantidad de páginas que el SO le asigna a cada proceso como
conjunto residente. Si la asignación es fija, es decir que el SO me asigno un número fijo de
marcos, y tengo, por ejemplo, un proceso que tiene hasta 4 marcos asignados. Si están todos
ocupados, no tiene la posibilidad de sacarle un marco a otro proceso. Si la asignación es de tipo
variable, sí tiene esta posibilidad. Puede ser que me agreguen o me saquen páginas.

La asignación fija y reemplazo global no es posible porque si le saco una página o un marco a
otro proceso y me lo asigno, paso a tener un marco más asignado, por lo que deja de ser fija.

71
Lucila Canalini

Política de limpieza
 Limpieza bajo demanda.
 Limpieza adelantada.

Consideraciones
Sobrepaginación/Trashing (Trasiego)
Una de las ventajas de la memoria es aumentar el grado de multiprogramación. Si tenemos
muchos procesos en memoria y por cada proceso hay pocos marcos, a medida que el proceso
vaya ejecutando, existe la posibilidad de que se produzcan más fallos de página. Esto significa
que voy a estar mucho tiempo trasladando o moviendo páginas de disco a memoria.
Si no tengo algún tipo de métrica con recomendaciones, podemos pensar que si usamos poco la
CPU es porque tenemos pocos procesos en memoria. Si es baja mi tasa de uso de CPU, puedo
aumentar el grado de multiprogramación. Pero si agrego más procesos a memoria, tendré más
fallos de página, porque la cantidad de marcos no aumenta. Llegaré a una situación en la que
tendré más fallos de páginas que lo que avanzo en la ejecución de procesos.
Este traslado de páginas de memoria a disco se lo conoce como sobrepaginacion. Donde
simplemente el problema es que hay muchos fallos de página, significando que hay mucha
entrada y salida, es decir, alta utilización del disco y bajo uso de la CPU. Se invierte más
tiempo en el mecanismo de paginación que en la ejecución del proceso.

Solución: Para solucionar esto se pueden hacer dos cosas. Una es en la que se usan muchos
recursos, y la solución es comprar más memoria. La que usa menos recursos es ir liberando
procesos, lo que no es muy recomendable, por lo que la opción anterior sería la mejor.
No es una solución agregar un procesador. Esto es porque no solo sería más caro, sino que,
además, la curva sería parecida pero el trashing ocurriría más rápido. Tener más procesador
hace que el problema llegue más rápido nada más.
Tamaño de las páginas
Si bien el hardware nos ofrece el tamaño de páginas que podemos usar, es el Sistema Operativo
quien elige el tamaño. El tamaño estándar suele ser páginas de 4 KB, pero pueden ser de menos
o de más.
Estas son características que se dan dependiendo de si el tamaño de página es grande o chico:

72
Lucila Canalini

Si elegimos tablas de páginas que tengan pocas entradas porque las paginas son grandes, nos
pueden generar algunos problemas que no ocurrirían si tenemos tablas grandes con paginas
chicas. Este tipo de desventajas vienen de la mano de los fallos de páginas. Si tenemos paginas
chicas (muchas páginas para el proceso) hay más chances de tener fallos de páginas. El mismo
razonamiento se utiliza para los fallos de TLB.
En la paginación solo tenemos fragmentación interna en la última página del proceso. Si las
paginas son más grandes, hay chandes de que la fragmentación sea más grande.
Con respecto a la localidad es más preciso porque tengo menos espacio en memoria.
La transferencia de E/S de la tabla es con un fallo de página.
Bloqueo de páginas
Se tiene un proceso A de alta prioridad y uno B de baja prioridad, y está ejecutando el B.
Mientras ejecuta genera un fallo de página por lo que es bloqueado, y pasa a ejecutar el A. Puede
pasar que en algún momento se atienda el fallo de página del proceso B y este pase a estar listo
para ejecutar. Pero también puede pasar que el A genere un fallo de página, y cuando se atiende,
podría ser que, cuando todos vuelven a memoria, el proceso B pueda sufrir inanición por ser un
proceso de baja prioridad.
La página que se trajo para el proceso B va a ser una página que no se usa hace mucho tiempo
y que además no fue modificada. Por lo tanto, esa página será elegida como víctima
seguramente. Se da esta situación por la inanición del proceso B. Para estos casos se puede
bloquear la página hasta que el proceso B pueda usarlo, porque si ya la tiene en memoria, y es
elegida como víctima, cuando vuelva va a pasar lo mismo.
Esto es lo que pasa:
1. PB provoca un fallo de página.
2. PB es bloqueado hasta tener la página solicitada.
3. PA es asignado al CPU.
4. PA provoca un fallo de página.
5. La página solicitada por PB se carga en memoria y PB se desbloquea.
6. PB puede sufrir inanición y la página que solicitó no fue modificada y permanece mucho
tiempo en memoria.
7. La página solicitada por PA sustituye a la de PB.

73
Lucila Canalini

Así se soluciona:

 Se utiliza un bit de bloqueo de marcos.


 Evita que una página que aún no fue utilizada sea sustituida.
 Se utiliza para marcos de memoria pertenecientes al SO.

Compartición de páginas: Copia durante escritura


Paginación permite compartir memoria.
Se ejecuta un fork() para crear un proceso hijo duplicado. Para mejorar el rendimiento, padre e
hijo comparten memoria.

Mientras la página A no se modifique, siempre la van a compartir. Pero si el proceso 1 quiere


modificar la página C, se creará una página nueva “Copia de C”. Es decir, medida que se generen
escrituras en las páginas, se generan nuevos marcos. Pero si son solo lecturas, compartirán los
marcos.

Estructura de programas
A nivel hardware, las matrices no son más que memoria. Entonces, habrá una diferencia si lo
recorremos por fila o por columnas.

Por cada fila hay una página. Por lo tanto, si tenemos memoria virtual, si leo por fila, cargo la
primera página y leo por completo. Cargo la segunda página y leo por completo. Y así.
Pero el problema estará si leo por columna. Lo que pasara es que habrá un page fault por cada
lectura.

74
Lucila Canalini

De todas maneras, este problema ya no existe porque el mismo compilador hace modificaciones
para que el recorrido tenga que hacerse por filas. Por lo tanto, el problema se resuelve en la
etapa de compilación.

Cómo en diferentes instantes de tiempo se altera la memoria según el algoritmo


Los números de arriba son las páginas que se van requiriendo, y los cuadrados se van llenando
a medida que traigo las páginas de disco. Solo tengo 3 marcos para cada caso.

Para los instantes 1, 2 y 4 tengo page fault porque necesito dos páginas que no tengo en la
memoria principal. En el instante 3 no porque solicito el uso de la página 2 pero ya la tengo en
memoria. En el instante 5 tengo page fault y decidó sacar a la página 1 para poner la página 5
porque si miro el futuro, no necesitaré esa página, al menos en esta traza.
Los primeros tres PF son obligatorios, por eso cuando se hace la suma total para la conclusión
la divido en 3PF + 3PF = 6PF.

El principio será igual al caso anterior. En el instante 5 reemplazo la página 2 por la 5 porque
esa fue la primera que entró (FIFO).
Vemos el problema en el instante 6, porque en el instante anterior justo reemplazó la que se
estaba por usar en el instante siguiente.
Lo normal sería que ningún algoritmo genere menos fallos de página que el algoritmo óptimo.

75
Lucila Canalini

Los primeros cuatro pasos son iguales. En el instante 5 se fija cual fue la que usó hace más
tiempo de las tres que tiene en memoria. La 3 la usó en el instante dos, la 2 la usó en el instante
tres, y la 1 la usó en el instante 4, por lo que la que hace más tiempo que no usa es la 3, así que
la reemplaza por esa.

El asterisco indica que el bit de uso está en 1. En el instante 5 hay page fault y evalúa todas las
páginas que tiene en memoria. Las tres tienen el bit de uso en 1, entonces evalúa uno a uno, y
pasa su bit de uso a 0. Cuando termina de evaluar la tercera página, vuelve a evaluar porque no
encontró ninguna en cero. Cuando vuelve a empezar, ve que la primera está en 0, por lo que
será la víctima, y el puntero pasará a apuntar a la siguiente página.
Las páginas siempre entran con el bit de uso igualado a 1. Y cuando se vuelve a usar una página
que ya está en memoria, pero su bit de uso está en 0, la uso y le aumento el bit de uso a 1.
Conclusión: El mejor de todos será el algoritmo óptimo, que no se puede implementar. Luego,
LRU será el segundo mejor, el Clock el siguiente, y el FIFO será el peor.
LRU es más preciso que el algoritmo de Clock porque usa para la selección de la víctima,
exactamente el último momento en que se usó. En cambio, el clock, apenas, aproxima si se
utilizó o no recientemente usando un bit de uso. Con respecto a la eficiencia desde el punto de
vista del overhead, el algoritmo Clock genera menos overhead que LRU. Pero desde el punto de
vista de los fallos de página, LRU es más eficiente que Clock.
12/06/2020

File System
Es una abstracción que tiene el Sistema Operativo para poder almacenar todo lo que
tenemos en memoria, persistirlo, por el hecho de que, si apagamos la máquina, todo lo que
tenemos en memoria se pierde, y no es la idea tener que regenerarlo cada vez que la volvemos
a encender.
Le permite gestionar el almacenamiento de datos y programas tanto al Sistema Operativo como
a los usuarios. A estos últimos les permite que, si están trabajando en un documento, a través
de un programa, lo que fuese, todo lo que va procesando, se va almacenando para tomarlo en
un siguiente punto y seguir ejecutando. Básicamente, permite que no se pierdan los datos.

76
Lucila Canalini

Objetivos:

 Almacenar datos y operar con ellos.

 Soporte para varios usuarios. Implica protección. Si dos personas están trabajando y
tienen archivos que no quieren que el otro vea, entonces el File System provee un
mecanismo mediante el cual se asegura de que esto se cumpla. Permite a ciertos
usuarios que tienen permiso operar, y a otros se les restringe.

 Minimizar la posibilidad de pérdida de datos. Mecanismos por los cuales, si hay un


corte de luz, algún programa que se corrompe, o se reinicia la máquina de golpe, y yo
tengo información que se estaba guardando en el File System, no se corrompa toda la
información que ya tengo guardada en el disco.

 Maximizar el desempeño del sistema. Que sea lo más rápido y ágil posible.
o SO: Administrar espacio en disco y aprovecharlo. Cuando el Sistema
Operativo nos gestione el file system, el almacenamiento se haga de la mejor
manera para que los megas que se tiene disponibles no los desperdicie por tener
una mala administración.
o Usuario: Tiempo de respuesta. Si guardo un archivo o lo leo, que se pueda
hacer lo más rápido posible.

 Soporte para distintos tipos de dispositivos. Uno no tiene que andar haciendo
operativas. Solo se necesita que el Sistema Operativo lo monte y lo disponga para que
uno lo pueda usar. Nos crea una interfaz estandarizada para los procesos de los
usuarios. Y a los dispositivos los abstrae, permitiéndonos operar con el File System de
manera independiente, sin importar el dispositivo del otro lado.

 Garantizar la integridad o coherencia de datos. Cuando se almacenan los datos, uno


los puede recuperar, y de la forma en la que estaban.

Archivos
La estructura más básica para poder almacenar cualquier dato en el File System, es un archivo.
Todo lo que queramos almacenar mediante el File System, ya sea en un disco rígido, en un
pendrive, lo haremos a través de un archivo. Los archivos son un conjunto de datos
relacionados y se persiste en el tiempo dentro de un dispositivo de almacenamiento. Esto
quiere decir que sin importar cuanto tiempo pase sin abrirlo, se mantendrá igual.
Los archivos tienen ciertos atributos: nombre, identificador, tipo, ubicación, tamaño, permisos,
fechas, propietario.
El nombre en general es para el usuario, mientras que el Sistema Operativo puede operar a
través del identificador numérico. El tamaño es coherente con la cantidad de datos
almacenados dentro de él.
Los permisos se basan en quienes pueden leerlos, escribirlos, o ejecutarlos (en el caso de
Linux).

77
Lucila Canalini

La fecha es para tener una traza de la actualización y del uso del archivo.
El propietario es quien lo crea y lo tiene en su poder. Este brinda los permisos para el acceso
al archivo.
La ubicación en si es algo que, aunque no se ve, uno sabe que está dentro de un directorio, y
dentro de esta ubicación se encuentran los datos.
Los archivos no tienen un único formato. Según el formato tendremos diferentes tipos de
archivos. Algunos son únicos para el Sistema Operativo, que el usuario no conoce. Otros son
propios de uso del usuario.
Todas las operaciones que queramos persistir, vamos a guardarla en dichos archivos, y los
mismos vamos a operarlos. Las operaciones se representan a través de llamadas al sistema.

 Operaciones básicas: Crear, abrir, leer, renombrar (mover), truncar, borrar, cerrar,
escribir, reposicionar.
Crear es definir un nuevo archivo y posicionarlo dentro de la estructura del File System.
Para abrir el archivo este debe estar creado. Abrirlo es traer ciertas estructuras del archivo a
memoria para poder operar con él.
Cerrarlo es cuando ya no necesito usarlo, y se lo saca de dicha posición dentro del File System.
Cuando uno lo cierra, debe guardar los datos. Para el File System esto es quitar de memoria la
estructura que tenía dicho archivo representándolo, y actualizar los nuevos datos guardados.
Leer un archivo implica ir a buscar los datos que contiene, que están en el File System, de alguna
manera persistidos en algún dispositivo mecánico o electrónico, y traerlos a memoria para
poder utilizarlos.
Para escribir, debo haber traído algo, lo modifico y lo guardo, o es algo nuevo que no tenía
contenido. Agregar contenido implica múltiples operaciones para que eso que teníamos en
memoria persista en disco en alguna parte del File System y que sea de manera óptima para
que, si necesitamos agregar más información, o si necesitamos ir a buscarlo, sea lo más rápido
posible.
Reposicionar es la operación que utilizamos para ir a cierta parte del contenido del archivo,
sin tener que pasar por todo el contenido inicial, calculando a donde ir según algunos
parámetros.
Truncar es una operación que agrega contenido al final de un archivo.

 Operaciones combinadas: renombrar (mover), copiar.


Renombrar es una operación que puede estar mezclada con el manejo de directorios porque
cuando se hace, se le cambia el nombre, pero el contenido no cambia, por lo que para el Sistema
Operativo implica no tener que estar moviendo la información persistida, sino que únicamente
cambia la identificación del mismo.
Por último, copiar es una operación compuesta. Implica crear un archivo nuevo, abrir un
archivo que existe, leer el contenido de dicho archivo, escribirlo, y cerrar. Entonces, dicha
operación es una combinación de otras: crear, abrir, leer, escribir y otras.

78
Lucila Canalini

Apertura de archivos
 Modos de apertura. Lectura, escritura, append (agregar al final, no permite modificar
el contenido anterior, únicamente ampliarlo), etc.

 Tabla global de archivos abiertos. El Sistema Operativo trabaja con esta tabla, que es
una estructura auxiliar para trabajar con los archivos. Para que pueda trabajar el
Sistema Operativo, los archivos deben estar abiertos, por eso es que esta tabla es
de archivos abiertos. Esto implica ir a buscarlos a disco y ponerlos en memoria. Si no
están en memoria, el Sistema Operativo no lo puede ver, por lo que no puede trabajar
contra los archivos estando en disco, como lo hace con procesos.
En esta tabla se tiene una entrada por cada archivo abierto en el sistema, ya sea
del lado usuario o del lado kernel. Esta tabla contiene el contador de aperturas, el
tipo, y la fecha de modificación. No contiene el puntero de archivo. El puntero
actual es específico y diferente a cada proceso que abre el archivo. Debe formar parte
de la tabla de archivos por proceso.
La tabla se utiliza a medida que se abren y cierran los archivos. No es necesario
persistirla en disco ya que en caso que se desmonten el FS, no quedarán archivos
abiertos del mismo.

 Tabla de archivos abiertos por proceso. Por cada proceso tenemos una tabla de
archivos abiertos. Se reduce a aquellos archivos que se fueron abriendo por cada
proceso, en el modo que fuese. Lleva una cuenta de la cantidad de aperturas que tuvo
un archivo.
Cada una de las entradas es un File Control Block, que es un bloque de control
de archivos que tiene los atributos del archivo, los permisos, etc. A su vez, es un puntero
a la tabla principal de la entrada de ese archivo. Internamente, la tabla de archivo para
un proceso, tiene un puntero que indica donde está parado dentro de ese archivo, y
también indica el modo de apertura.
Estas dos tablas se van completando a medida que uno abre y cierra archivos. Cuando uno
ejecuta la operación “abrir”, indica completar esta tabla global de archivo, para que mi Sistema
Operativo y los procesos tengan a mano los atributos de cada uno de los archivos que abre. Esto
es porque si no, debe ir a buscar los atributos al disco, que es mucho más costoso que buscarlos
en memoria.

Tipos de bloqueos
Los archivos pueden estar abiertos por más de un proceso, por lo que debe haber bloqueos
para que no acceda más de un proceso al mismo tiempo, a menos que solo se pretenda hacer
lectura.
Es parecido al tema de sincronización (los mutex). Pero, a diferencia de los mutex, con los
bloqueos no debo bloquear todo el archivo, sino que con bloquear la porción de archivo que
necesito, es suficiente. Por lo tanto, permite las múltiples operaciones sobre un mismo archivo,
siempre y cuando las partes bloqueadas no sean las mismas, y dos procesos no intenten hacer
operaciones sobre la misma porción. Entonces, si las operaciones son sobre dos porciones
bloqueadas distintas del archivo, podrán acceder al mismo tiempo tranquilamente.

79
Lucila Canalini

En general, el Sistema Operativo es el que dice que se aplique el tipo de bloqueo.


 Compartido/Exclusivo. Se puede bloquear para que se pueda compartir el archivo, y
varios procesos puedan acceder, o puedo bloquearlo para que haya un único proceso
trabajándolo, hasta que lo libera. Dependen de si quiero que el archivo lo pueda trabajar
un único proceso (el que lo abre), y hasta que no lo libere no lo puede usar otro proceso,
o lo quiere compartir.

 Obligatorios/Sugerido. El bloqueo obligatorio implica que cuando el proceso abre el


archivo, se bloqueará para el resto de los procesos, por lo que otros procesos no podrán
abrir el archivo si ya está siendo utilizado. El Sistema Operativo nos dice que, si vas a
abrir el archivo, habrá un bloqueo. Para el bloqueo sugerido, el Sistema Operativo no
garantiza el bloqueo, lo que hace es sugerir que se bloquee, pero si no se hace, vas a
correr un riesgo porque otros procesos querrán acceder. Esto implica que el
programador que hizo una aplicación que trabaja sobre un archivo, deberá declarar el
bloqueo, y cuándo debe pasar. Por ejemplo, en Windows, el bloqueo es obligatorio.
Cuando una aplicación abre un archivo, el Sistema Operativo impone el bloqueo y ese
archivo es de uno, no lo podrá usar otro proceso. En Unix no, hay que declararlo.

Tipos de archivos
En el sistema en general, para lo que es file system, tenemos distintos tipos de archivos. El
Sistema Operativo tiene algunos tipos de archivo que le permite trabajar de diferente manera,
y le permite presentar diferentes vistas al usuario, o le permite generar diferentes operaciones.

 Propios del sistema operativo: Regulares, directorios (tienen un formato en el cual se


hace referencia –nombre y puntero- a otros archivos), dispositivo, links, sockets (para
transmitir datos entre procesos bidireccional), terminal.

 Archivos ejecutables: Son potenciales procesos. El sistema los puede convertir en


procesos y estos operan en base a la definición de la lógica interna haciendo uso de
recursos (memoria y demás). En Linux, cualquier archivo es ejecutable.
Dependiendo de cada sistema operativo, los ejecutables tienen un formato
diferente a los archivos regulares. Son estructuras que contienen el ejecutable, la
estructura donde va la data, etc., que le permite al Sistema Operativo cargarlo en
memoria y él mismo sabe dónde poner cada parte para trabajarlas. En general es el
compilador el que se encarga de armar este tipo de archivo.
El Sistema Operativo los ve como potenciales para poder ser transformados en
procesos. Según el Sistema Operativo, las extensiones están atadas al programa o no.

 Archivos regulares (de texto o binarios): Aquellos que contienen estructuras, donde
almaceno la estructura de dato y el archivo tendrá iguales estructuras de datos iguales,
pero con diferente información almacenada en sí misma.
Son los que en general maneja un usuario común y corriente, permitiéndole
trabajar y persistir datos en el file system. Se pueden abrir con aplicaciones del sistema
o propias del usuario.
Ejemplo: Una imagen, un gif, un pdf, un Word.

80
Lucila Canalini

Tipos de accesos
Cuando uno abre un archivo, tiene que poder procesarlo. Se pueden leer de distinta forma.
o Secuencial: Se lee desde el principio del archivo hasta la posición que yo requiero.
Podría tranquilamente ir a alguna parte del archivo, pero se necesita alguna
información para poder hacerlo, haciendo algún cálculo, por lo que igualmente tendré
que recorrerlo completo.

o Acceso directo: Es un tipo de acceso en el cual tengo algún mecanismo o dispositivo


que me permite hacer un cálculo, sin necesidad de recorrer todo el archivo completo, y
acceder a la parte que quiero. Este tipo de acceso se suele utilizar indexado con una
tabla o alguna estructura intermedia.

Manejo de rutas
Para poder hablar de rutas hay que hablar de directorios.
Cuando trabajamos en cualquier sistema, sabemos que
hay carpetas, que son archivos de tipo especial, de tipo
sistema operativo, que contiene un listado de otros
archivos y directorios posiblemente. Nos permite hacer
una clasificación, poder separar, poder colocar dentro de
diferentes directorios diferentes archivos, y nos permite
encontrar el archivo dentro del File System.
Un directorio entonces es un tipo de archivo que
adentro tiene una lista con el nombre del archivo, un
indicador hacia el FCB si existe, y algún dato o atributo
extra que uno puede ver cuando abre la carpeta y ve
los archivos. Estos datos le permiten al Sistema Operativo
leerlos rápido sin tener que ir a buscar el archivo
propiamente dicho para mostrar ese tipo de información.
 Ruta absoluta: Aquella en la cual uno lista donde está a part ir del directorio raíz.
Si estamos parados dentro de la carpeta “Finales 2017 diciembre”, y queremos obtener la ruta
absoluta, muy probable es que, como suelen estar dentro de la carpeta de usuario dentro del
File System, la ruta será /home/*nombre de usuario*/finales/2017/diciembre. Por lo tanto,
ruta absoluta hace referencia al archivo con respecto al directorio raíz del sistema.
 Ruta relativa: Es relativa a un punto. Tendré que estar parado dentro de otro
directorio, para poder trabajar con rutas relativas. Puedo trabajar con una ruta relativa
a un directorio en particular, no necesariamente el directorio raíz.
Si tomamos el archivo de antes y quiero el archivo que está dentro de la carpeta marzo, puedo:
hacer referencia de la ruta absoluta desde el directorio raíz, o hago referencia directamente con
respecto al directorio anterior.

81
Lucila Canalini

Siempre habrá un directorio de referencia, que puede ser el raíz o no. Es importante cuando
se hace un cambio de ubicación, para no tener que modificar los accesos directos. Va de acuerdo
al Working Directory, que es donde estamos parados.
Habitualmente decimos que dos archivos no pueden tener el mismo nombre. Para diferenciarlo
de otro, el sistema operativo toma como nombre la ruta absoluta, entonces si no se encuentran
en la misma ruta, pueden llamarse igual.

Directorios
Lista de archivos donde se asocia el nombre de ese archivo con atributos. Esto nos da la
particularidad de que los directorios son archivos y su contenido interno es un listado de los
archivos que contiene, los cuales también pueden ser directorios.
Los atributos más importantes son el nombre, la identificación para el usuario, y el id,
identificador interno propio del Sistema Operativo para ese archivo.
Los directorios tienen operaciones particulares para poder trabajarlos: búsqueda de un
archivo, crear un archivo, renombrar un archivo, borrar un archivo, listar un directorio (saber
todos los archivos que tenemos, en forma de árbol, viendo directorios, subdirectorios, y los
archivos finales), recorrer el File System.
Crear un archivo dentro de un directorio, del tipo que fuese, implica una operación sobre el
directorio. A este se le agrega la referencia al archivo nuevo que hago, y a su vez le pone una
referencia al FCB dentro del File System, la fecha de creación, entre otros datos que se crean en
ese momento.
Con respecto a las búsquedas, los directorios permiten operar en búsqueda para poder traer
todo el contenido y que sea mucho más rápido y no tener que ir buscando uno a uno.
En general, el Sistema Operativo, cuando va a leer un directorio, lo abre, y al abrirlo le da una
entrada dentro de la tabla de archivos generales que tiene. A su vez, levanta los datos que
componen al directorio (el listado de archivos y directorios internos), y para poder operar con
las operaciones mencionadas (buscar, crear entrada nueva, borrar, hacer listado, etc.), tiene que
trabajar con una estructura afín. Esto le permite una búsqueda mucho más rápida.
En general, se utilizan directorios de formato árbol o en formato grafo. Las hojas suelen ser
archivos regulares, o del tipo que fuese, o podrían ser algún tipo de directorio.

82
Lucila Canalini

Los nodos internos son directorios y las hojas son archivos finales (o también podrían ser
directorios). Los arboles no pueden tener ciclos, por lo que, si lo represento como un árbol, no
podría compartir de ninguna manera un archivo que está dentro de una rama que no
corresponde a una rama actual. Por eso aparecieron los de forma de grafo general. Esta es una
estructura similar a un árbol, pero con accesos directos.

Montaje de File System


Los directorios y todos los archivos están dentro del File System. Este se puede montar. Implica
poder verlo desde el lado del Sistema Operativo y que lo pueda utilizar. Para poder hacer esto
y poder trabajar con esta estructura con archivos, necesitamos un lugar donde montarlo.
Punto de montaje: Es aquel punto en el cual uno coloca el File System y le permite al Sistema
Operativo poder leerlo y trabajarlo, levantar sus estructuras y ponerlas en memoria.
En Linux se puede montar sobre directorios que estén libres, o no. Si no están libres, se los
monta encima y no se podrá ver el directorio actual hasta que se lo desmonte. En general se lo
monta sobre directorios vacíos para no tener el problema de no poder acceder a los archivos
que estaban en dicho directorio (si no estaba vacío).

Los File Systems tienen dentro de su estructura un bloque llamado Master Boot Record, con
cierta información que le permite al Sistema Operativo poder leer el File System en general,
sabiendo qué estructuras tiene adentro. El Sistema Operativo sabe levantarlas, juntarlas y
poder trabajar en memoria con este File System.

Protección
Cuando tenemos sistemas donde somos usuarios y se permite a una única persona, no es tan
útil. Se puede utilizar la protección de acceso total. Pero si al sistema se pueden conectar varias
personas, como lo es un servidor, sí.
Para esto, existen distintos tipos de protección:
 Acceso total: Cualquiera que prenda la máquina y acceda lo pueda leer.
 Acceso restringido: Solo el que lo creó tiene acceso a tal.
 Acceso controlado (permisos de acceso): Quien brinda la restricción es aquel que lo
crea. El creador lo lee, lo escribe y lo ejecuta, y además le da permiso a quienes pueden
acceder. Entonces, si más de una persona tiene acceso, puedo elegir una restricción
especifica. Sacar el permiso de lectura, escritura, y/o ejecución a dicho archivo a
usuarios específicos, y a otros darles dicho acceso. Según el sistema en el que
trabajemos, existen distintos tipos de permisos de accesos:

83
Lucila Canalini

Unix: Creo el archivo, por lo que tendré acceso, elijo un grupo (limitado) al que le daré acceso,
y al resto no le daré acceso. Tengo la posibilidad de darle ciertos permisos a algunos, ciertos
permisos a otros, pero no tendré algo más granular. Sólo permite definir permisos para el
propietario, un solo grupo y el resto de los usuarios que no sean el propietario y no formen
parte del grupo, no tendrán permisos.

Matriz de accesos: Por cada archivo o directorio en el sistema, y por cada usuario, da un tipo
de protección. Es muy granular porque tengo un permiso para cada usuario por cada archivo,
pero es imposible de mantener. Ocupa mucho espacio la matriz de acceso, porque una matriz
de acceso hay que persistirla. No se puede implementar.
Listas de control de acceso (ACL): Linux la implementa como complemento al tipo de usuario
“grupo y otros” (tipo Unix). Hace una lista de control de acceso, conformada por nodos en los
cuales dice el usuario, el permiso, y nada más. Por lo cual sobre los archivos habrá una
combinación de tipo Unix y un ACL. Esta es una lista enlazada. Permite personalizar los accesos
para los usuarios. Le daré permisos a los usuarios que yo requiero que hagan cada tipo de
acceso (lectura, escritura o el que fuera). Es ilimitada. Permite algo más granular que el tipo
Unix y sin tener que implementar la matriz de acceso previamente mencionada. Cuando uno va
a leer un archivo, y lo trae de memoria, trae esta lista, la cual no implicará leer mucha más data.

Contraseñas: El común y corriente. La contraseña tendría que estar almacenada dentro del
disco, el algún lado que no sea dentro del archivo. Es más controversial. Ya no se usa este tipo
de protección, sino que la protección va de la mano del usuario.

Disco lógico
El File System es un disco lógico que está compuesto por bloques lógicos. Un bloque es aquella
porción que forma al archivo. Es una representación de una cantidad de un tamaño de bytes a
los cuales el Sistema Operativo opera.
A los bloques puedo leerlos, reservarlos, escribirlos. El último bloque que almacena datos de un
archivo, no tiene por qué estar lleno, por lo tanto, puede tener fragmentación interna. Los
bloques adentro pueden tener cadenas de caracteres, registros.
Los bloques lógicos son de tamaño fijo y cada uno puede contener información sobre un
solo archivo. Algunas implementaciones permiten el uso de bloques de tamaño variable y de
tamaño variable y expandible.

84
Lucila Canalini

Un archivo está compuesto por uno o más bloques. Todo lo que se vaya a almacenar en un disco
lógico ira a parar dentro de un bloque. El disco lógico toma a todos los bloques como si fueran
un array y sabe que ese volumen está compuesto por tales bloques de datos.

El Sistema Operativo lo utiliza para abstraerse de lo que son las implementaciones propiamente
dichas del File System, del disco físico.
Cuando uno escribe en un disco o en un File System, siempre se hace de a bloques. Si quiero
modificar un byte de un archivo, tengo que encontrar el bloque, modificar el byte en memoria,
y luego modificar el bloque entero.

Partición
Los dispositivos de almacenamiento son una tira de bytes. La partición será una porción de
bytes.
Una computadora para poder leer un dispositivo que tiene particiones, necesita una tabla de
particiones. Esta tabla está en el primer sector del dispositivo e indica que de qué posición
(byte) hasta cuál ocupa la partición. Así, se puede hacer referencia a las particiones.

Las particiones en sí no sirven de nada si no le doy una forma. Para esto, se lo formatea
(FAT, UFS, etc.), con un tipo de File System, y ahí se le da sentido al conjunto de bytes. Esto es
porque se les da un formato a ciertos bytes en cierta posición. Una vez que se le da formato a
una partición, se convertirá en volumen.

85
Lucila Canalini

Entonces, una partición con un formato específico de File System es un volumen. Los File
Systems internamente contienen estructuras a grandes rasgos para que los sistemas operativos
los puedan trabajar sin ningún problema.

Estructuras de un File System


o Bloque de arranque o Booteo: Le da toda la información del File System al Sistema
Operativo para que pueda levantarlo en memoria y trabajar con el mismo.

o Bloque de control del archivo (FCB): Una estructura que nos permite almacenar
archivos (con sus datos, información persistida) y todos los metadatos de los archivos
(fecha de creación, modificación, ultimo acceso, permisos, etc.). Los FCB pueden estar
asociados a un solo archivo.
Para las implementaciones en que los FCB están definidos desde la creación del File
System, podrían haber FCB asociados a ningún archivo.

o Bloque de control de volumen: Está dentro de cada uno de los volúmenes. Contiene
información administrativa y le permite al Sistema Operativo saber, cuando se lee dicho
volumen, cuántos bloques de datos están escritos, cuáles son, cuáles bloques están
libres, cuántos, qué cantidad de archivos tiene, qué cantidad de FCB están disponibles,
etc. Sirve para la administración en general para que el Sistema Operativo pueda operar
con el File System.

o Estructura de directorios: Siempre tenemos un directorio principal al cual están


anidados otros directorios. Nos permite encontrar todos los archivos que se encuentran
internamente y trabajar con ellos. Dentro de la estructura de directorios podemos tener
archivos y directorios, y cada una de las entradas de los directorios es como un
listado.

 Entradas de directorio: Nombre de archivo + Atributos (fechas, permisos,


identificador) o puntero al FCB. Esto es porque los directorios en general no
tienen los datos propiamente dichos de los archivos ni los atributos, porque si
no sería muy costoso cada vez que mapeamos los directorios en memoria para
poder operar con ellos. Además, uno no quiere toda la información de todos los
archivos, tal vez se quiere uno solo.

86
Lucila Canalini

En un sistema se puede crear una cantidad limitada de archivos, aunque fuesen vacíos. Esto es
porque tenemos un número limitado de FCB para poder manejarlos.

Estructuras de un File System en memoria


Si las estructuras no están en memoria, no sirve. Esto es porque el procesador puede leer
únicamente lo que está en memoria, y no lo que está en disco.
Por lo tanto, el Sistema Operativo, para poder trabajar con esto tiene que traer las estructuras
del File System y cargarlas en memoria en estructuras muy similares, con agregados para el
manejo (para acotar pasos).
Tabla de montaje: Lo que hace es, cargarse en memoria con otras estructuras, y decirnos
dónde se encuentra cada File System montado dentro del Sistema Operativo, con qué formato,
y qué permisos de lectura tiene.
Me sirve tenerla cada vez que hago referencia a un archivo o a un directorio dentro del File
System que está montado. Me hace más rápido la búsqueda de datos. Tiene datos sobre cada
volumen montado dentro del sistema. Entonces, la tabla de montaje se utiliza para trabajar
con el File System actual y con el File System que yo vaya montando.
A su vez, tiene las siguientes estructuras:

 Estructura de directorios: Para poder acceder a los directorios, hay que ponerlos en
algún lado. Entonces, cuando se monta el File System, algunos sistemas los ponen por
fuera del File System actual (como Windows), o montan su volumen dentro de algún
directorio del File System actual (como Linux y Unix), permitiendo operar a través de
ese directorio con la estructura de directorios que trae el volumen que se acaba de
montar.
 Tabla o lista global de archivos abiertos.
 Tabla o lista de archivos abiertos por proceso.
El File System donde está montado el propio Sistema Operativo es el que arranca cuando
arranca el sistema, siendo el primero que se carga. Está montado dentro de un volumen con las
estructuras, y cuando carga la tabla de montaje, o las entradas que tenga (porque puede estar
formado por más de un volumen), va a tener las propias de su sistema.

Implementación de directorios
Los directorios tienen su manera específica de operar. A medida que se lee un directorio, se
abre el archivo que corresponde al directorio, se lo carga en memoria y se lo carga en una
estructura de las siguientes (es decir, se puede representar en memoria los directorios de las
siguientes formas):
 Lista lineal: No tiene ningún tipo de orden, por lo que es muy costoso si la lista es
grande porque hace búsquedas secuenciales. Bajo rendimiento.
Si se borra, se puede ir a buscar el archivo, y se quita el nodo.

 Lista ordenada: Cuando quiero agregar un nuevo nodo, debo buscar en qué posición
tengo que agregar el nodo, para mantenerla ordenada. También es costoso.

87
Lucila Canalini

Si se borra, el borrado es lógico. Se hace una marca de que no se utiliza más, y cuando
se quiere agregar un nodo que iría en ese lugar, se reutilizará el nodo con la nueva
información.

 Árbol: La búsqueda de un elemento será no más que cuatro iteraciones.


La inserción o actualización de un nodo es mucho más rápido que cuando se
implementa una lista.

 Tabla de hash: Hay una función unívoca en la que ingreso un nombre y me devuelve la
posición en la tabla. La función tiene una cantidad finita, por la que debo saber el tamaño
del directorio, y debo limitar la cantidad. Si hay colisiones, se complica.

Métodos de asignación
El Sistema Operativo ve a los archivos como un bloque de datos, además del Control Block, que
son los metadatos de dicho archivo.
Los archivos los mapea en su totalidad dentro de los bloques de datos, que básicamente tienen
un tamaño fijo. Al mapear un archivo, se debe particionar en bloques. Al dividirlo en estos
bloques fijos, para este ejemplo, ocupa cuatro bloques.
Se puede ver que en el cuarto bloque al final, no lo completa
totalmente (padeciendo fragmentación interna). Este lugar no
es reutilizable por otro archivo, porque solo un archivo puede
utilizar el conjunto de bloques que le fue asignado.
Si tengo que modificar una línea del main.c, desde la vista del
usuario, se modifica la línea y listo. Pero cuando se guarda,
internamente el Sistema Operativo, actualiza en memoria el
bloque correspondiente a la línea modificada, y lo baja a disco,
para actualizarlo en el bloque correspondiente que fue
asignado al disco lógico. Este disco lógico se corresponde con
alguna parte de un disco mecánico o un disco electrónico.
El Sistema Operativo asigna bloques de la manera más eficiente para poder utilizarlos de la
mejor manera posible, sin perder espacio.
El main.c es un tipo de archivo regular. Si uno lista los
directorios, verá un listado como el siguiente (próxima
página). Esto es porque el Sistema Operativo lo almacenó
dentro de bloques como un listado con el nombre, tipo de
archivos, y el id que es un puntero al FCB dentro del volumen.
El tercer bloque no está completo, por lo que, si yo sigo
agregando archivos, o moviéndolos de otro directorio a este,
se agregaran entradas, una debajo de la otra, hasta completar
el bloque. Si tengo el tercer bloque completo y quiero agregar
una entrada más, el Sistema Operativo buscará un bloque
vacío, le asignará al directorio /home/user un bloque nuevo, y
agregará una entrada para este archivo.

88
Lucila Canalini

Cuando creo un archivo debo darle un nombre y asignarle un FCB. Este último tiene que poder
hacer un seguimiento y dar referencia a los datos que va almacenando. Con esto, da una noción
de que necesito tener una manera de recuperar esos bloques que componen al archivo.

 Asignación contigua
Uno cuando crea un archivo, crea una entrada en el directorio, y busca el primer bloque
disponible (que no esté utilizando otro archivo), e intenta asignárselo al archivo recién creado
mediante un FCB.
Entonces, asignación contigua, cuando lo guarde, buscara la cantidad de bloques necesarios
para guardarlo, y utilizará los primeros que estén libres y contiguos. Una vez encontrados,
recién ahí asigna los datos en los bloques.
La entrada de directorio para esta asignación incluye el nombre de
archivo, el número de bloque en donde empieza, y cuantos bloques
ocupa.
La ventaja de esto es que cuando se necesita recuperar el contenido
del archivo, es fácil porque al leer la entrada de directorio, se en que
bloque debo pedir y cuantos bloques más tengo que traer a memoria
para poder visualizarlo. A su vez, con algún calculo extra, y sabiendo
el tamaño de los bloques, podría posicionarme en alguna parte del
archivo y el acceso directo estaría disponible.
Sin embargo, si tengo que agregar información al archivo que
sobrepasa la cantidad de bloques reservados, pero el siguiente bloque está ocupado, no podré
agregar esta información. Es decir, solo podré agregar cosas si existen más espacios contiguos.
Además, tiene problemas del lado del Sistema Operativo, relacionado a cómo va a buscar un
espacio donde entre.
Este tipo de asignación padece fragmentación externa porque estará llena de bloques libres y
ocupados intercalados. Cuando se quiera guardar un archivo, habrá espacio libre, pero los
bloques contiguos no serán suficientes para guardarlo, por lo que no se podrá.

89
Lucila Canalini

 Asignación enlazada o encadenada


Este es el tipo de asignación que utiliza FAT. Para un mismo archivo
se asigna un bloque, pero ese bloque que corresponde a datos,
también tiene metadata. Tiene un puntero que apunta al bloque que
le sigue. Entonces se tiene una cadena de bloques de datos.
Se pierde la fragmentación externa porque no tengo que agarrar
bloques que estén contiguos. El archivo se puede expandir todo lo
que quiera, siempre y cuando haya bloques disponibles.
La entrada de directorio, entonces, será distinta. Alcanza con saber el
bloque inicial y el bloque final, para no pasarme al momento de leer,
y para saber dónde empezar a hacerlo. No hay acceso directo.
Sin embargo, si se quiere ir a algún lugar específico, deberé llevar a
memoria todo el archivo y recorrerlo secuencialmente hasta encontrar lo que quiero.
Desde el lado estructural, hay problemas si un bloque de dato asignado se corrompe. Si empiezo
a leerlo, podré hacerlo a medias.

 Indexada
Es el tipo de asignación que utiliza UFS. Es una mejora de la asignación anterior. Dado un
archivo, le extraigo toda la metadata y la pongo en un único bloque. Tendré un bloque índice o
bloques que solo tendrán punteros a bloque de datos. Se tienen de forma secuencial, por lo que
puedo hacer el mismo recorrido que hacía con la enlazada, sin tener metadata dentro de los
bloques de datos.
Si bien mejora el tener los bloques de datos libres de tener metadata,
y se utilizan completos sin esta, tendré bloques de índices para cada
archivo. Este bloque índice estará asociado al archivo y a nada más.
La entrada de directorio será el nombre y la referencia o número de
bloque correspondiente al bloque índice.
Si hay un archivo con un único bloque asociado y con una única
entrada, habrá fragmentación interna en general para este bloque, y
tendré un bloque índice solo para tener una entrada y el resto del
bloque lo desperdicio. No sufre fragmentación externa porque cualquier bloque libre puede ser
asignado a un archivo.
Si se tiene un archivo con más bloques asignados, con lo cual un bloque índice no alcanza, habrá
que encadenar bloques índices. Así, el ultimo índice de un bloque de índices encadenados, va a
ser el puntero al siguiente bloque índice. Por esto se tendrá un listado de bloques índices, y el
listado que esta internamente referenciado por los números de bloques dentro del bloque
índice.
Es adecuado para el acceso directo y para el secuencial. Si se daña un bloque, no pasa nada,
puedo leer el resto del archivo. Sin embargo, requiero espacio adicional: no solo para datos,
sino que también para los bloques índice.

90
Lucila Canalini

Gestión de espacio libre


Existen bloques asignados y bloques libres. El Sistema Operativo debe distinguir y gestionar los
bloques libres. Para esto, se utiliza una lista de bloques o de posiciones libres. Se tiene en
memoria un listado de bloques que se sabe que están vacíos (no asignados a ningún archivo).
Cuando se monta el volumen, hay una estructura principal con toda la gestión administrativa.
Esta es la encargada de llevar un listado de este tipo de estructuras cuando se apaga y enciende
la máquina para gestionar el espacio libre y actualizarse.
La gestión de espacios libres se puede trabajar con:
Lista de bloques libres: Como es una lista de bloques en blanco, podemos agarrar el primero,
sacarlo, liberar la lista y listo. Si hay asignación contigua se complica. Por lo tanto, no es lo más
recomendable para este último tipo de asignación.
Lista de porciones libres: Es más adecuada para la asignación contigua. También es una lista
donde dice el número de bloque y, a partir de ese bloque, cuantos bloques libres contiguos hay.
Por lo tanto, si uno tiene un archivo que ocupa 5 bloques, deberá fijarse en ese atributo para
ver si puede ponerlo en dicho lugar.
Bitmap: Estructuras que permiten que, dentro de un byte, donde se representan 8 bits, cada
bit representa un bloque, y puedo saber si cada bloque está ocupado o libre. Siendo el 0 ocupado
y el 1 libre. Tendré una mejora que es que la máquina provee operaciones para trabajar con
bits, por lo que me permitiría buscar el primer bloque libre haciendo un for sobre los bits. Linux
trabaja con bitmap.
Indexada (como archivo indexado): Parecido a la asignación indexada. Tendré un bloque con
un listado de bloques libres.
Agrupamiento por bloques: Listado de bloques libres. El agrupamiento apunta a un bloque
que contiene otra lista de bloques libres y así sucesivamente. Tendremos bloques indexados en
forma de lista.

Escritura de un archivo nuevo


Escribir un archivo que está en memoria a disco implica varios pasos. Cuando voy a guardar el
archivo, le pongo el nombre, y pasa lo siguiente:
1. Crear el archivo: Verificar que exista FCB disponible para poder almacenar todo el
archivo y, de ser así, asigna el FCB y crear la entrada de directorio (que no exista otro
con el mismo nombre). Por ahora el puntero a bloques no se asigna.

2. Asignarle bloques requeridos: Tengo que llevar el FCB a memoria para luego
empezar a trabajar con los bloques de datos. Para esto, se abre el archivo y se agrega en
las listas de archivos abiertos. En esta tabla se le agregará la entrada y se pondrá el count
(cantidad de veces que fue abierto) en 1. El proceso que está escribiendo el archivo va
a tener en su tabla de archivos una entrada con este FCB. Se obtienen los bloques libres,
y asignarlos bloques al archivo. Para asignar los bloques de datos voy a tener que
agrandar el tamaño del archivo. Para esto, el Sistema Operativo lo que hace es truncarlo.

91
Lucila Canalini

3. Escribir en el archivo: Escribir los bloques y actualizar atributos (fecha, tamaño,


permisos). Hay que escribir el contenido de los bloques asignados en los bloques que
van al dispositivo, para persistir los datos. Se cargan los bloques a escribir en memoria,
y luego se envían al dispositivo a través del disco lógico. Todos los datos (atributos) se
modifican en la estructura que está en memoria.

4. Cerrar el archivo: Actualizar lista de archivos abiertos. La operación es bajar el archivo


a disco, y esto grabarlo desde el FCB, entonces al cerrarlo se lo elimina de la tabla de
archivos abiertos del proceso, y también lo eliminara si el contador en la tabla de
archivos abiertos está en 0. Por último, antes de eliminar la estructura, la guarda en el
disco.

Recuperación
Puede pasar que el procedimiento de escritura se corte por la mitad, o que maten al proceso
justo cuando estaba guardando.
Si hay alguna falla cuando hay un proceso de escritura, el archivo que se estaba bajando al
dispositivo que lo iba a persistir, en general termina corrupto. Cuando pasa esto, el archivo no
se podrá recuperar, por más que haya mecanismos de chequeo. Lo que sí se puede hacer es que
uno los puede excluir como corruptos. Para eso, el sistema corre algunos mecanismos para
detectar errores.

 Comprobación de coherencia: Existen mecanismos que permiten manejar la


coherencia dentro de los archivos y mejora el rendimiento cuando se guardan en
memoria. No siempre se persisten en disco. Estos son marcadores para saber que la
información que fue almacenada corresponde con la información que se tenía.

 Backups (copia de seguridad): Si se tiene una corrupción de datos, se puede recurrir


a una cinta de backup para recuperarnos ante un fallo. Hoy por hoy Windows trabaja
con puntos de restauración que son imágenes del sistema a cierto día.

 Journaling (estructura de registro): Lo que hace es trabajar a cada operación de


escritura como si fuera una tabla de tareas a la cual va a ir aplicando pasos. Cuando se
realiza una operación se la trata como una transacción de las bases de datos. Asegura
que se realicen de forma completa, asegurando la consistencia de los datos, y de no ser
así, no se hace. Entonces, luego de la falla quedan solamente las tareas confirmadas.
Sigue los siguientes pasos:
1. Registra secuencialmente los cambios, pero no se realizan.
2. Una vez que se escriben las tareas que se realizarán sobre diferentes bloques de
datos, se consideran como confirmadas.
3. Empiezan a realizarse, y se van marcando las tareas que fueron realizadas
mediante punteros (como un check).
4. Cuando todas las tareas del listado se dan como realizadas sin fallas, recién ahí
se confirman, y si no se confirman porque las tareas no fueron completas, se
hace un rollback.

92
Lucila Canalini

Área de swapping
En general es un archivo. En Linux se trabaja como una partición. Es un espacio con un formato
(es un volumen en el fondo). Se usa generalmente para hacer el swapping de lo que es la
memoria virtual. Tiene un tamaño determinado que podría llegar a expandir. No tiene ningún
tipo de formato.
Las particiones tienen un tamaño fijo. Cuando uno define un File System dentro de una
partición, File System estará atado a ese tamaño y si se quiere agrandar la partición, se puede
hacer con alguna herramienta. Deberá eliminar la partición contigua y el espacio libre deberá
tomarlo la partición actual, pero a su vez no alcanza porque el File System no va a reconocerlo
a menos que se haga un resize.
Con respecto al swap, funciona de la misma manera. Podría expandirse o no. Podría hacerse en
una partición o en un archivo.
Si se hace en una partición aparte, lo que nos da es que, si tenemos este tamaño fijo, sabemos
que puede trabajar internamente con bloques de datos continuos. Es un formato File System
propio que maneja el Sistema Operativo, y lo utiliza para hacer swap de páginas de procesos
que no se están usando memoria, entonces lo baja a esta partición. Esto lo hace porque es más
fácil que hacer una búsqueda de que bloque tiene tal parte.

El archivo va a recibir dentro del propio File System donde está levantado el propio sistema
operativo. El archivo es mucho más fácil de expandir el tamaño.
En Windows se utilizan archivos. Una de las desventajas que tiene es que para poder acceder a
estos archivos hay que hacer llamadas al sistema que afectan al mismo File System.

Mapeo de archivos en memoria


Mapear un archivo en memoria es tratar al archivo como si fuese un array. Se pueden
referenciar los bytes del archivo como si fuese un array. A medida que voy necesitando bloques
de datos, el sistema va a buscar los bloques que necesite y los va trayendo a memoria,
permitiendo que se trabaje con los datos ya en memoria.

93
Lucila Canalini

Así, se podrá escribir como si fuera un array, y


cuando haya que bajar esa página que estaba dentro
del proceso y correspondía a un archivo,
directamente la guarda en el File System, en el
bloque de dato. Esto da la posibilidad de no tener
que trabajar con las primitivas que son syscalls
(fwrite, fread, etc.), y directamente se trabaja con
mmap.
Tiene sus desventajas porque consume recurso. Si
bien utiliza un mecanismo muy usado por el Sistema
Operativo, trabajar con un archivo todo en memoria
no vale la pena si tengo que ir a modificar un byte y el archivo es muy grande. En ese caso sería
mejor recorrer con un fseek y modificarlo, sin tener que traerlo todo.
20/06/2020
Cualquier operación que se realice sobre un archive, ya sea de escritura o lectura, implica
llevarme el bloque complete a memoria. No se puede leer un byte directamente de un bloque
desde disco. De alguna manera tendré que calcular que bloque me tengo que llevar a memoria,
traerlo, y operarlo.

File Allocation Table (FAT)


Es una de las más conocidas implementaciones de File System comercialmente. Fue
desarrollado en 1997 utilizado en diskettes, pero actualmente se utiliza en algunas memorias
Flash. Se utiliza mucho para compartir archivos con diferentes sistemas operativos.
La partición es una porción del disco y de alguna manera le tengo que poder dar estructuras
que nos permita grabar cosas encima para después obtenerlas. Vamos a necesitar estructuras
administrativas: la que gestiona el volumen, el directorio raíz, la que maneja los bloques de
datos.
Cuando se formatea la partición con un volumen de tipo FAT, se crea el Boot Sector y
diferentes tablas FAT. Además, se tiene el directorio y el bloque de datos. FAT llama a los
bloques de datos “Cluster”.

El Boot Sector tiene información sobre el volumen. Esta información es el nombre, tipo,
cantidad de tablas que tiene de FAT, cantidad de Clusters que ocupa la FAT, tamaño de los
punteros –las entradas- de la FAT.

94
Lucila Canalini

La FAT es una tabla en la cual cada entrada es un puntero a cada uno de los Clusters dentro del
volumen. Entonces, si tengo 1000 Clusters, la tabla tendrá 1000 entradas. Esta es una tabla para
poder encontrar los archivos.
Los archivos están plasmados como entradas en la tabla de FAT y el directorio. Si pierdo las
tablas de FAT no tengo manera de poder seguir los bloques a un archivo, por más que vea la
entrada en el directorio. Se tendrá una o más copias. Solo se utilizará la primera, mientras que
las copias están solamente por si le pasa algo a la principal. Cada cierto tiempo se actualizan
dichas copias.
Dentro de los directorios de FAT hay un listado de archivos y directorios que contiene. Las
entradas del directorio son: tipo de archivo, nombre y extensión, primer Cluster archivo,
tamaño. Los directorios se trabajan distinto a otro tipo de archivo (archivos regulares).

La cantidad de entradas que puede tener un bloque que pertenece a un archivo de directorio,
se calcula haciendo el tamaño del bloque dividido por la cantidad de entradas.
No se tiene un FCB por cada archivo. Esta implementación de File System no trabaja con una
estructura para cada archivo, sino que es el directorio el que me da todos los datos del archivo.
Con el primer Cluster del archivo y combinado con la FAT de la tabla puede obtenerse.
Los bloques de datos pueden soportar archivos, pueden tener tamaños que van desde 512
bytes a 64 KB, y el tamaño del bloque.
Si el archivo ocupa 2000 bytes y el tamaño de Cluster (bloque) es de 1kb, entonces para saber
cuántos Clusters debo leer para leer todo el archivo, debo hacer tamaño del archivo/tamaño
del Cluster, es decir, 2000/1024, y el resultado me dirá el máximo de Clusters que habrá que
leer. Cuando se lee un archivo, se mira la tabla FAT.

95
Lucila Canalini

Cuando quiera leer el archivo arc.txt, va a ir al Cluster 7, y para saber cual tiene que seguir
leyendo, se fijara en la tabla. Ve que tiene que leer el 6, y cuando lo lee, ve que no hay más por
leer, por lo que se termina. El fin está marcado con todos 1s, o con F si se lo ve en hexadecimal.
El tp.c empieza en el Cluster 5, va a la tabla, ve que el próximo Cluster es el 4, entonces como le
sigue en datos, se lee el bloque 4 luego de levantarlo, y leo dentro de la tabla cual le sigue, veo
que es el 9, lo levanto, y me fijo en la tabla si necesito leer el próximo, y me dice que no hay más
para leer. Entonces, levante estos tres Clusters que, según el tamaño del archivo, son suficientes.
Para este archivo tp.c, de tamaño 3000, si usa 3 Clusters, tendrá como espacio 3x1024 por ser
el tamaño del Cluster 1kb. Entonces, tendrá un tamaño de 3072 bytes, pero solo necesita 3000,
por lo que ahí notamos la fragmentación interna.
Si, por ejemplo, para el archivo arc.txt, se corrompe el bloque 7, podré de todas formas leer el
bloque 6, por lo que tenemos una mejora a la asignación enlazada, porque por más que esté
corrupto, podre al menos salvar parte del archivo.
Cuando se crea la tabla, es decir, cuando se formatea el sistema, solo estarán ocupados los
Clusters respectivos a la estructura administrativa, mientras que los que están disponibles, los
marca como libres. El Master Boot Record, que maneja el volumen, por ejemplo, ocupa uno o
dos Clusters. Los Clusters se empiezan a enumerar a partir del primero que esté disponible para
almacenar archivos o directorios.
Cuando se quiera asignar un bloque, se debe mirar la File Allocation Table para ver si la entrada
está en libre o está con error. La tabla se encarga de manejar tanto los bloques libres como los
ocupados. Arma una cadena de Clusters. Si hay algún bloque que tiene un error porque al
Cluster no se le puede marcar nada por algún problema del disco, le permite no elegirlo a la
hora de asignarlo.
Es fácil de manejar porque se puede leer archivo de manera indexada, con solamente hacer un
seguimiento de los Clusters indexados en la tabla FAT.

Tipos de FATs
Si la tabla de la FAT me da una entrada por cada Cluster que tiene el sistema, tengo que poder
referenciar a todos los Clusters dentro del volumen.

 FAT8: Es la FAT común. Quiere decir que tiene un puntero de 8 bits. Puedo tener
2^8 = 256 entradas.

 FAT12: Punteros de 12 bits. Ocuparan 2 bytes. Permitía 4096 entradas.

 FAT16: Punteros de 16 bits. Ocupare 4 bytes por cada uno de los punteros. Me da 2^16
entradas.

 FAT32: Punteros de 32 bits. Solo se usan 28 bits para el puntero. Quien implemento
FAT32 se comió 4 bits de los 32 para almacenarlos por alguna cuestión. Algunos libros
dicen que es para manejarse dentro de Clusters muy grandes. Cada entrada mide 4
bytes. Por lo que la tabla, solamente, pesará 1 GB.

96
Lucila Canalini

Los tamaños de la entrada, es decir, la cantidad de bytes que tengo, me dirá la cantidad de
Clusters que podre referenciar.
Si el Cluster, por ejemplo, tiene tamaño de 1kb, y trabajo con FAT8, quiere decir que no podré
trabajar con File System con más de 256 KB.

Desventajas
 FAT no tiene seguridad.
 No gestiona los espacios libres aparte, sino que lo hace la misma FAT. Lo malo de esto
es que sí o sí hay que recorrer toda la tabla hasta encontrar una posición libre (de todos
ceros).
 Como no hay FCB, no tengo una estructura en la cual agrupe por cada uno de los
archivos los datos (atributos de creación, modificación, último acceso, permisos).
 No tiene backup.

Unix File System (ext2/ext3) (UFS)


En general es reconocido por Linux y Mac. Para Windows hay que instalar un driver para que
lo reconozca.
Al igual que FAT, se parte de una partición vacía. Ahora, hay que crear un volumen de tipo
Extended. El Unix File System tiene un formato distinto a FAT y debe cumplir con las
estructuras que vimos. Debe tener bloque de arranque, bloques con los que va a trabajar, para
que el Sistema Operativo pueda leer y operar con archivos (sean comunes y corrientes o propios
del sistema como lo es el directorio).

UFS trabaja con grupos de bloques. En una partición se graba un bloque de arranque con cierta
información sobre todo el grupo de bloques, es decir, información global sobre el volumen. Cada
uno de los bloques tiene el mismo formato de estructura interna, pero con diferente
información.
El súper bloque, al igual que el Boot Sector, tiene el tamaño del bloque, el nombre del File
System, la cantidad de bloques libres, estados (correcto/incorrecto). A su vez, llevara ciertas
métricas de cantidad de nodos ocupados o libres, en que bloque se encuentra el directorio raíz.
El descriptor de grupos tiene información sobre los grupos, y a su vez tiene punteros a los
bloques siguientes. El súper bloque y el descriptor de grupos es igual en todos los grupos.

97
Lucila Canalini

El bitmap de bloques, será uno o varios bloques que estarán formateados en formato bitmap.
Todos los unos y ceros que tiene a dentro marcarán qué bloque está libre y qué bloque está
ocupado dentro de los bloques de datos. Por el otro lado, el bitmap de nodos, tiene la misma
función, pero en lugar de hacerlo con el bloque de datos lo hace con la tabla de nodos.
Cada archivo del sistema tendrá asociado un FCB, a diferencia de FAT que no tiene File Control
Block. El FCB tendrá los atributos del archivo y los punteros a los bloques de datos.
La entrada no tiene un tamaño fijo.
Los directorios en UFS ahora, a diferencia de FAT, perderán cierta información, que ahora
estará almacenada en FCB. Es por esto que, al no tener tanta información, se reducen. Los
directorios tienen un formato como el siguiente: el nombre de identificador del FCB, el nombre
del archivo, y un indicador más que será el tipo, para identificar si es directorio, archivo regular,
socket, etc. Este número de identificador de nodo nos servirá para buscar el nodo que le
corresponde al archivo con dicho nombre.

Inodos
Son el FCB del File System y existe uno por cada archivo. La entrada de la tabla de archivos
globales para el archivo que traigo de memoria, será un inodo representado en memoria, y será
similar (no igual) al que está almacenado en el File System.
Un inodo tiene un identificador que se corresponde con el id que está en la entrada del
directorio. Dentro del FCB, que en este caso es el Inodo, hay muchos más datos que el directorio
en FAT no tenía. Tales como el propietario, el tamaño del archivo, los permisos.

El tamaño del archivo podrá hacer varios cambios dentro del archivo. Al tener un FCB y no tener
una limitación en la entrada de directorio, se puede jugar con la cantidad de campos dentro del
inodo, y nos permite tener tamaños de archivo muchos mayores. En el FCB destinamos el
manejo de archivos a esta estructura, la cual tiene un tamaño fijo (en general, de 128 bytes).

98
Lucila Canalini

Si tengo este tamaño fijo, y tengo entradas de 4 bytes para cada puntero de datos, habrá un
problema.
Los punteros son los números de bloques donde están los datos. Se dicen punteros, pero en
realidad tienen los números asignados.
El inodo utiliza un sistema de punteros a demanda utilizando bloques de datos. Se maneja
como el sistema de enlazado indexado. Mientras no se necesiten los punteros, no se usan.
Trabaja con tipos de punteros en el inodo:
 Punteros directos: Apuntan a un bloque de datos directamente.
 Punteros indirectos: Apuntan a un bloque de punteros. Pueden ser simples, dobles,
triples.

La cantidad de punteros que puedo tener por cada bloque dependerá del tamaño. Si divido el
tamaño del bloque por el tamaño de cada puntero, y tendré la cantidad de punteros que
tendré. Si son a bloques índices o a bloques de datos, dependerá de donde estén.
Permite trabajar con bloques de datos chicos, y no perderé ningún bloque de dato indexado,
por tenerlo en el inodo.
El tamaño máximo teórico de un archivo, no está limitado por el tamaño del directorio como en
FAT. Este se calcula con los bloques directos totales que puede llegar a almacenar a través de
un inodo.

99
Lucila Canalini

Cada puntero de dirección directo aporta un bloque.


Por el otro lado, como para este caso el tamaño de un bloque es de 1 KB y el tamaño de puntero
es de 4 Bytes, habrá 256 punteros por bloque. Entonces, un puntero indirecto simple, aporta
256 bloques de datos. El indirecto doble aporta 256^2 bloques de datos. En esta, los bloques de
datos están en las hojas. Por lo tanto, no miro la metadata que utiliza. Por último, el indirecto
triple aporte 256^3 bloques de datos.
Por último, para calcular el tamaño máximo teórico de un archivo, sumo la cantidad de bloques
aportados y lo multiplico por el tamaño de cada bloque.

Accesos directos (LINKs)


Ambos tipos de LINKs son archivos y son soportados en extended. Se crean mediante ln.

Soft LINK / Symbolic LINK: Es un archivo que en su contenido es una ruta a otro archivo, es
decir, una ruta de directorio. Nos permite poder compartir un archivo a través de soft LINK, y
acceder al archivo que está en otra parte, mediante la apertura del archivo actual. El Soft Link
no está acoplado al File System.
Cuando se crea, nos genera una entada en el directorio con el nombre que asignamos, tendrá
asignado un inodo, y al inodo se le agregara en sus datos el contenido de la ruta que se le aporto.
Por su naturaleza, tiene una ruta al archivo, por lo que, si borro el archivo original, la ruta
apuntara a algo que no existe. El sistema no actualiza ese link.
Ejemplo:

Si quiero crear dentro de /usr un Soft LINK a tp_v2.c, que tiene el inodo 20, hago referencia a la
ruta del archivo con los comandos correctos y se creara una entrada en el directorio /usr. Se
creará un archivo que tendrá otro id en el FCB. Internamente, dentro del inodo, en uno de los
tantos atributos, se aclara si es Soft Link o Symbolic Link. En el primer bloque de datos se asigna
la ruta.
Esto nos muestra que cada vez que tenga que acceder al archivo, tendrá un doble acceso a disco.
Esto es porque hay que buscar el inodo (el 33) almacenado en el File System, traerlo a memoria.
El Sistema Operativo se percata de que es Symbolic LINK. Ve la ruta y con esta ruta va a buscar
el inodo correspondiente al archivo que está en esta ruta. Así, tenemos dos accesos al archivo.
Si esto se hace con Hard Link, en lugar de 33 veríamos un 20, y se tendría un contador.

100
Lucila Canalini

Hard LINK: Es una marca dentro del inodo (del FCB) y se maneja como referencia al archivo.
Nos permite trabajar con una copia del archivo, que no realmente es el archivo.
Cuando se crea, crea una entrada al directorio que aportamos, y agrega un inodo que
corresponde al archivo original al que estoy apuntando. La herramienta le aumenta el contador
de referencia hacia el archivo a dicho inodo. Por lo tanto, no tenemos un archivo propiamente
dicho, sino que tenemos una referencia al archivo original, sin tener problemas de pasar por
otro archivo intermedio.
Si elimino el archivo, la persona a la que le compartí el archivo, podrá acceder igualmente. Esto
es porque la operación de borrarlo es descontar el contador de referencia que tiene asociado el
archivo. A menos que esté en cero, no se borrará.
Ejemplo:

Si yo quisiera crear en /usr un Hard Link de tp_v2.c y le agregará el inodo igual a 20. Por lo
tanto, será una referencia al FCB dentro del File System correspondiente a ese archivo.
Entonces, no se pasará por un archivo intermedio. Lo busca ahí directamente.
Trabajan internamente dentro del File System, no hace referencias a través de directorios, y no
se pueden hacer Hard LINKs a archivos que están montados dentro de otro File System. Esto es
porque no pueden trabajar con estructuras externas, por más que sea FAT o Extended.
No podemos saber cuál es el archivo original. Lo único que tendremos es el contador. Si
obligamos que este está en cero, entonces es porque no hay ninguna referencia a ese inodo, y
se puede eliminar.

Tamaño máximo teórico de un File System


Es el mismo calculo, ya sea FAT o UFS. Se calcula como el tamaño máximo de entradas que puede
tener la tabla por el tamaño de cada bloque.
Ejemplo: Se tiene punteros de 32 bits, por ser FAT32 y el
tamaño de Cluster es de 2KB = 2*2^10 = 2^11 =
1024+1024 bytes. El tamaño máximo teórico del File
System será: 2^28 * 2^11 = 2^39 = 512GB.
No es lo mismo el tamaño máximo teórico del File System
que el de un archivo. El del archivo lo calculamos de
acuerdo a la composición que puede tener el inodo,
mientras que el del File System lo calculamos a partir del tamaño del puntero y del bloque.

101
Lucila Canalini

Agregar información en un archivo


El Sistema Operativo hará lo siguiente:
1. Localiza el archivo: Busca a través de los directorios por medio de la ruta.
2. Le asigna el espacio: Si es necesario, asigna bloques libres al archivo. Para esto busca
en el bitmap de bloques cual está libre. Luego, deberá modificar el bitmap de bloques y
los punteros en inodo.
3. Escribir los datos en el nuevo archivo: Modificar los atributos del archivo (tamaño,
fechas).

FAT vs. UFS

Ejemplo FAT:
La FAT 2 es una copia de la FAT 1 por seguridad. Esto es porque en la FAT están los bloques,
que se pueden dañar, y no podré leerlos. Pero si tengo una copia, puedo recuperarlo. Por defecto
se crean dos FATs (una copia), pero hay parámetros que nos permite elegir cuantas copias de
la FAT queremos. Mientras más cantidad de FAT más seguro será el File System, pero
igualmente es una estructura grande que ocupa espacio.
El directorio Raíz es por el que accederé a mis bloques. Si quiero saber lo que hay en dir1, tengo
que buscar el bloque 3 y ver lo que tiene adentro, porque indica que el contenido está en el
bloque 3. Cuando vemos el bloque 3, vemos que tiene el dir2 y el archivo2, y que
respectivamente están en el bloque 8 y en el 4.
Tanto el bloque 3 como el bloque 8 son bloques que contienen directorio: lo único que tienen
son archivos u otros directorios.
El archivo1 está en el directorio raíz, por eso tiene la R, y se encuentra en el bloque 7, o al menos
ahí se encuentra su primer bloque de datos. Para ver el siguiente bloque, busco en la posición 7
de la FAT, y encontrare el número de bloque donde sigue el archivo (y así…).
D es tipo Directorio, R es tipo regular (archivo), B representa otro tipo de archivo.
¿Cómo saber si el bloque de directorio raíz está lleno y es necesario otro bloque? Cada entrada
de directorio ocupa 32 bytes en FAT (siempre). Si tenemos bloques de 512, tengo que hacer
512/32. Esto me da la cantidad de entradas. Si tengo en un bloque esa cantidad de entradas,
entonces necesitaré uno nuevo.

102
Lucila Canalini

¿Cómo crear un archivo en FAT?


1) Crear el archivo: Verificar que exista FCB disponible. Crear entrada de Directorio.
Sabré si el bloque está libre porque leo la FAT y debo encontrar un 0.
2) Asignarle bloques requeridos: Abro el archivo y agrego las listas de archivos abiertos,
obtengo bloques libres, y asigno los bloques al archivo.
3) Escribir en el archivo: Escribir los bloques en donde solía estar vacío/basura, y
actualizar atributos (fechas, tamaño, permisos). Si el bloque 5 lo escribí con 512 bytes
(completo) pero el segundo con 400, debo poner en los atributos que el tamaño del
archivo es de 912 bytes, y que el tamaño que ocupa es de 1024 bytes porque ocupa dos
bloques. Tendré fragmentación interna de 112 bytes.
4) Cerrar el archivo: Actualizar la lista de archivos abiertos. No es una operación que
tenga algún tipo de representación en el File System, sino que es una representación
lógica para el Sistema Operativo.

103
Lucila Canalini

Entrada/Salida
Los dispositivos de entrada salida son muy diferentes entre sí, a tal punto de que uno tiene un
mouse, un teclado, un disco rígido, y para el Sistema Operativo son dispositivos de E/S e intenta
tratarlos todos de la misma manera.
Toda nuestra relación con la computadora es a través de dispositivos de E/S. Son todos muy
importantes desde el punto de vista del usuario principalmente.

Tipos:
 Comprensibles para el usuario: Los que el usuario puede leer y entender. Un mouse,
una impresora.
 Comprensibles para el sistema: Por ejemplo, un disco, para un usuario es solo una
caja mecánica que no sabe lo que tiene, mientras que el disco se conecta con el sistema.
 De comunicación: Permite comunicarse con el usuario o incluso con otros sistemas.
Un modem, una placa de red, etc.

Diferencias
La diferencia de estos tipos de entradas/salidas son: la velocidad de transferencia, el uso, la
complejidad, la unidad de transferencia, las condiciones de error, si son bloqueantes o no
bloqueantes, y si son síncronas o asíncronas.
La velocidad de transferencia en los dispositivos es muy notoria. Mientras más cerca están
del usuario más lentos son, y mientras más cerca están de otros sistemas para comunicarse son
mas rápidos. El usuario necesita ir más despacio que la computadora.
Como dispositivo lento tenemos el teclado y el mouse, mientras que los mas rápidos son las
redes y los dispositivos gráficos, que son los que pueden procesar más bits por segundo.

104
Lucila Canalini

Con respecto al uso, es variado también. Un mouse, un teclado, todos sirven para cosas
diferentes.
Un mismo dispositivo se puede utilizar para diferentes cosas. Podemos usar un mouse para leer
programas y para dibujar en una pantalla. El disco rígido puede servir para los usuarios, para
que guarden sus propios archivos, o para que el SO extienda la memoria.
La complejidad de un disco rígido, que tiene una controladora, lógica, plaquetas, cables
internos, movimientos mecánicos, discos que giran a velocidades imposibles de notar para el
ojo humano, es mucho mayor que la del mouse, que tiene una plaqueta con una bolita que se
mueve, súper simple.
La unidad de transferencia no necesariamente es siempre el byte, sino que hay dos tipos de
unidades. Una es por carácter, el caso del teclado o el mouse. La otra es por bloque, donde la
unidad de transferencia mínima deja de ser un byte, sino que la información se mueve de un
lugar a otro en tamaños más grandes. En el caso del disco se mueve en sectores. Los sectores
son por defecto de 512 bytes.
Las condiciones de errores varían porque no es lo mismo que se rompa un mouse o que se
rompa un disco.
Existen otro tipo de diferencias:
Acceso aleatorio o secuencial. En el acceso secuencial se tiene que dar en orden, como en
cintas, mientras que los discos, por ejemplo, pueden acceder a un punto específico sin necesidad
de acceder a la información anterior.
Compartible o dedicado. Puede ser usado por muchos usuarios o por uno a la vez.
Lectura, escritura, o ambos. Es decir, de entrada, salida, o ambos. Un teclado y un mouse son
de lectura, y la escritura (salida) es que se muestre en la pantalla. El disco rígido es de ambos
tipos.
Las E/S bloqueantes son cuando un proceso que está ejecutando su
código, realiza la solicitud de entrada-salida, entonces el proceso se
quedará bloqueado esperando la
respuesta. Cuando esta llegue, por medio
de una interrupción, que el proceso pasa de
estar bloqueado a estar listo, y seguirá
ejecutando.
Por el otro lado, las E/S no bloqueantes
son cuando el proceso hace la solicitud y puede seguir ejecutando
código sin necesidad de parar para esperar la respuesta. Esto trae
varias ventajas, pero la lógica del programa debe ser más compleja.
La relación con el dispositivo es síncrona cuando necesito o tengo que esperar, si o si, la
respuesta para poder continuar. Si no, no se podrá avanzar. Por el otro lado, el método
asíncrono es donde hago la solicitud, pero no necesito la respuesta inmediatamente, sino que
puedo continuar con otra tarea, y nada tiene que ver con la respuesta, por lo que puedo seguir
trabajando. En algún momento habrá que consultar si la respuesta la tengo o no.

105
Lucila Canalini

Estructura de un módulo de E/S


La información puede viajar de arriba hacia abajo o de abajo hacia arriba.
Si quisiera hacer una lectura de un disco,
primero debería hacer un read en el sistema
operativo, y según el descriptor que use
conoceré a que módulo de E/S se refiere, es
decir, a través de que driver podré
comunicarme con el dispositivo. El driver es
un software que le permite comunicarse con
el hardware del dispositivo. Están
relacionados con una controladora, una
plaqueta, un chip. Entonces, el driver
traduce en un idioma que el dispositivo
pueda entender, y luego le dará la orden a
la controladora.
Este tipo de estructuras se suele mantener en todos los Sistemas Operativos, con el objetivo de
que pueda tratarlos a todos de la misma manera, sin importar la complejidad o la función de
cada uno. Si por cada funcionalidad hubiese un funcionamiento diferente, el Sistema Operativo
se volvería más complejo.

Organización del sistema de E/S


Existen tres técnicas para transferir información hacia o desde la entrada-salida.
1) E/S programada. El procesador es el encargado de pasar
la información que tenga que escribir o leer de la E/S a la
memoria del proceso que lo haya solicitado. Para hacer
esto realiza cuatro operaciones: Activar el dispositivo (ver
que esté listo), ver que tarea se va a realizar, comprobar el
estado, y la transferencia. La desventaja de este tipo de
técnica, es que desperdicia muchos recursos porque el

106
Lucila Canalini

procesador está constantemente viendo si está listo o no. Cuando hay mucha
información para transferir, no es la mejor técnica.

2) E/S por interrupciones. El procesador tiene la


posibilidad de quedarse bloqueado hasta tener
disponible toda la información que necesita. La
desventaja es que el CPU es el responsable de enviar o
recibir la información del dispositivo de E/S hacia la
memoria. El problema es que el procesador debería
utilizarse para ejecutar instrucciones de un programa
en particular, que este ejecutando en ese momento, por
lo que se puede considerar una pérdida de tiempo.

3) Acceso directo a memoria (DMA). Permite desligar al procesador de llevar y traer


información constantemente. Hace uso de un procesador extra que tiene la
computadora, y termina siendo uno muy simple en comparación al procesador que
procesa instrucciones, ya que este procesador DMA solo entiende como llevar y traer
información, por lo que será el encargado transferir la
información desde la memoria hacia la E/S. Por lo
tanto, el procesador únicamente dará la orden de
hacer la transferencia, y cuando esté lista se enterará
por medio de una interrupción, pero no participara en
nada más.
Los pasos que realiza el procesador es definir el tipo
de operación se quiere hacer en el dispositivo de E/S
(Lectura o Escritura), analizar la dirección del
dispositivo (desde donde se va a escribir o leer), la
cantidad de bytes a leer o escribir, y la ubicación de
memoria donde debe escribir o leer.
El DMA utiliza el mismo boot del sistema, por lo que
mientras lo esté usando para transferir información, el procesador no podrá hacerlo,
por lo que esto puede traer un problema.
Resumen:

Buffering
Los buffers son espacios de memoria dentro del kernel del sistema operativo, reservado para
ciertos casos. Es un área de memoria, que no es ajena a la RAM, que almacena datos mientras
se transfieren entre disposiivos o entre un dispositivo y una aplicación.

107
Lucila Canalini

Sus dos funciones principales son que: Adapta diferencias de velocidades y adapta unidades
de transferencia.
La primera se refiere a que, por ejemplo, la computadora escribe rapidísimo lo que quiere
imprimir, mientras que la impresora tarda más en imprimirlo. Así, el proceso quedaría
bloqueado hasta que se termine de imprimir. Sin embargo, puedo escribir toda la información
a imprimir en un buffer, y poder seguir haciendo otras cosas mientras la impresora imprime.
Los buffers permiten que la información no desborde.
La segunda se refiere a que cuando quiero leer x bytes, pero del filesystem recibo más. Ahí se
adapta la información que se tiene para pasarle al usuario.

Una aplicación del buffer es cuando se hace el reemplazo de páginas en memoria virtual.
Cuando se reemplaza una página, esta se guarda en el espacio de memoria del SO. El page fault
ocurre igual, pero ahorramos el acceso a disco con los buffers. Estos tienen marcos reservados,
que nada tiene que ver con los marcos que utilizan los procesos.
La ventaja de esto es que si ya tengo todos los marcos victima agrupados, en algún momento
los puedo escribir todos juntos, siendo escrituras más eficientes, porque pueden ser
consecutivas. Además, si la página que acaba de ser reemplazada vuelve a ser solicitada antes
de escribirse en disco, me ahorro el acceso a disco, y ya lo tengo en un buffer aparte en la
memoria. Por último, evita el uso de bit de bloqueo de páginas.

Planificación de disco
Esto se refiere principalmente a los discos magnéticos. Es importante planificarlos porque si lo
hacemos, podemos tener mayor rendimiento. El disco se usa muchas veces, ya que todos
nuestros archivos, programas, Sistema Operativo, están en disco, además de ser utilizado como
memoria virtual.

108
Lucila Canalini

No es un dispositivo como otros donde el tiempo de acceso a un sector (unidad mínima de


lectura y escritura de un disco) es el mismo para todos, sino que es una suma de diferentes
tiempos.

Estructura de un disco
Los discos pueden dar entre 90 y 120 vueltas por segundo. Si bien el giro se hace a velocidad
constante, a menos que haya algún inconveniente, el brazo es quien entrega la información.
Físicamente hay tres platos en un disco, pero lógicamente pueden ser más. Cada uno de estos
platos, en cada una de sus caras, que suelen ser dos, encontramos la siguiente estructura, donde
tenemos pistas y sectores:

Tanto las pistas como los sectores están enumerados. Por cada cara existe un cabezal, que es
quien termina realizando la operación de lectura o escritura, y, además, la transferencia.
Un cilindro es un conjunto de pistas. Un cilindro está compuesto, por ejemplo, de todas las pistas
número 10 de todas las caras. Por lo tanto, para hacer referencia a un sector particular, hay que
hacerlo de acuerdo al número de cilindro al que pertenece, el número de cabezal que hay que
utilizar para leer, y el número de sector (que es el número de sectores por pista).

Estructura lógica de un disco


Es como lo va a ver el File System. No será del tipo cilindro, cabezal y sector, sino que será un
numero lógico.

Para hacer un matcheo entre el sector lógico y la geometría de cilindro-cabezal-sector, tengo


que ir rellenando por cilindro, siendo el 0 el que se encuentra en la primera cara, en el primer
cilindro y en el primer sector. Hasta no terminar con un cilindro, no cambio de pista.

109
Lucila Canalini

Tiempo de acceso a un sector


Es la suma del tiempo de búsqueda (tiempo para posicionar el brazo en el cilindro o pista
deseada), latencia rotacional (tiempo en que tarda el sector en posicionarse debajo de la cabeza,
que suele variar entre 0 y el tiempo que tarda el disco en dar una vuelta) y tiempo de
transferencia. Este último es un tiempo fijo que no se puede manipular, y es lo que tarda el
cabezal en pasar por arriba del sector para poder leerlo, y luego transferirlo a nuestra
controladora. No es lo que tarda en llegar a la memoria. Ocurre todo dentro del disco.
Dependiendo el sector, se tardará más o menos en acceder a él. La latencia rotacional no
podemos manejarla, pero como Sistema Operativo se puede decidir el orden en que se leen los
sectores.

Planificación de disco
No se tiene en cuenta el tiempo de transferencia ni la latencia rotacional para los ejercicios,
porque son tiempos que no se pueden manipular.
Para planificar e n qué orden se leerá cada sector, existen ocho algoritmos de planificación, cuyo
objetivo de todos ellos es reducir el tiempo de búsqueda.
A medida que pasa el tiempo, los pedidos se van actualizando, por lo tanto, cada vez que me
paro en una nueva pista, aparecen nuevos pedidos. Entonces luego de atenderlos, tengo que
volver a preguntar que pedidos hay.

 FCFS (FIFO): El primer pedido que recibo es el primero que atiendo.

110
Lucila Canalini

 SSTF (Shortest Seek Time First): Busca el pedido de pista más cercano al cabezal. Es
mucho más eficiente que el FIFO en cuanto velocidad. La desventaja es que sin importar
el orden en que lleguen, se atienden en el mismo orden. Por lo tanto, hay inanición.
Si se tiene dos sectores a la misma distancia de la posición del cabezal, se tiene
en cuenta el movimiento del brazo. Si el brazo estaba subiendo, se seguirá subiendo, Si
estaba bajando, se seguirá bajando.

 SCAN: El cabezal se mueve constantemente hacia arriba y una vez que llega al tope
empieza a bajar, y una vez que baja, lo hace hasta llegar al tope. No es que comienza a
subir o bajar apenas termina con una pista (a menos que se encuentre en el tope). Sube
y baja únicamente si hay pedidos o no, por lo que se forman “mesetas”, que se generan
porque mientras no haya pedidos, el brazo no se mueve. Es por esto, se necesita un dato
adicional: la dirección del cabezal.
Este algoritmo no tiene inanición porque tarde o temprano se llega a todos los
pedidos.
Las desventajas de este algoritmo es que hay mucho tiempo perdido, como se lo
puede ver en el trayecto del 99 al 30. Por el otro lado, este tipo de algoritmos, y casi
todos los que vienen después, van a tener el mismo problema de inanición. Este
problema es que, si estoy en la pista 85 y empiezo a recibir pedidos constantemente en
dicha pista, entonces el brazo se quedara parado en la pista 85 durante mucho tiempo.

111
Lucila Canalini

 C-SCAN: Scan circular. A diferencia del SCAN, es que cuando se llega al tope (sea arriba
o abajo), no se empieza a bajar, sino que el brazo cae casi en un tiempo de 0 ms (pasa
de 99 a 0 en un tiempo completamente despreciable. Por lo tanto, el brazo siempre va a
ascender (o descender, según sea el ejercicio).
Sufre la misma inanición que el SCAN. Si recibo infinitos pedidos de la pista 85,
nunca podré mover el cabezal de dicha pista.

 LOOK: Casi igual al SCAN, con la diferencia que no llega hasta los topes. Si luego del
pedido de la pista 10, hubiese uno en la 50, no va a ir hasta la pista 0 para luego subir,
sino que va directamente.
También sufre inanición como los dos algoritmos previos.

 C-LOOK: Hace lo mismo que el C-SCAN pero sin llegar a los topes. Cuando llega al 85 cae
hasta el 10, no hasta el 0. También sufre inanición.
Es el de menor tiempo siempre, pero hay algunas cuestiones de
implementaciones mecánicas de los discos que puede no permitir esta planificación.

112
Lucila Canalini

 FSCAN: Utiliza dos colas de pedidos. La primera es la cola activa, van a estar los pedidos
que se está atendiendo en el momento. La segunda es la cola pasiva, están los pedidos
que voy a recibir mientras atiendo los de la lista activa. Los pedidos se van guardando y
hasta no terminar con una lista no sigo con la otra.
Se atienden los pedidos de la cola activa utilizando el algoritmo SCAN.
Lleva más tiempo que los anteriores, pero ya no hay más inanición, por el tema
de las dos listas de atención. Es una mezcla entre FIFO y SCAN.

 N step SCAN: Utiliza colas de N pedidos o menos. Los pedidos se acumulan en varias
colas de tamaño N. Voy armando listas de tamaño N. Cada cola se atiende utilizando el
algoritmo SCAN. Es posible que las listas no queden completas, porque pasan de ser
pasivas a activas antes de que lleguen pedidos para completarlas y no pueden entrar si
ya es activa.
Es un algoritmo más justo que el anterior porque el orden de atención de las
colas es FIFO, y dentro de cada lista se utiliza el SCAN.
Si N = 2:

113
Lucila Canalini

Sea cual sea la planificación, si estaba en la pista 20 y estoy yendo a buscar la pista 25, pero
mientras lo hago, llega un pedido en la pista 23, no importa. Primero se debe terminar con el
pedido que se estaba atendiendo, luego se verá cuándo se atiende el pedido de la pista 23.

Sector lógico a CHS


Estos pedidos con los que estuvimos trabajando, son pedidos al número de cilindro o al número
de pista, no al sector lógico (que va de 0 a la cantidad de sectores que haya en disco). Para
encontrar dicho número, hago la siguiente cuenta:

A menos que se diga lo contrario, el tamaño de un sector del disco es de 512 bytes. Si hago
Cant. de Sectores * 512 bytes = Capacidad Total del Disco
Cant. de Sectores = Cant. de Cilindros * Cant. de Cabezas * Cant. de Sectores por Pista
RAID (Redundant Array of Independent Disks)
Conjunto de discos que inicialmente se formaron porque el disco es muchísimo más lento que
el resto de dispositivos de E/S (más lento que la memoria, que el procesador, etc.). Para mejorar
la velocidad de atención de los pedidos, apareció RAID que son un conjunto de discos que tienen
cierta información. En todos los RAIDs los discos se dividen en bandas (stripes).

114
Lucila Canalini

En el RAID 0 lugar de tener toda la información en un solo disco, y lo que sobra en otro, por
ejemplo, la información se encuentra distribuida.

La ventaja es que en vez de atender cuatro pedidos de un disco, hago cuatro simultáneos en ¼
de tiempo. Por lo tanto, se ahorra mucho tiempo.
Con el paso del tiempo vieron que sería conveniente tener varios discos extras para tener más
seguridad. Los discos, al ser un dispositivo mecánico, tienen más chances de gastarse que los
dispositivos electrónicos. Por lo tanto, las posibilidades de una falla mecánica eran mayores.
El RAID 1 es el disco espejado. Tengo un disco con información, y tengo un segundo disco con
exactamente la misma información, los mismos archivos, idénticos, con la particularidad que
cada vez que hago una escritura tengo que escribir ambos. Agrega seguridad en cuanto que si
se me rompe el disco no pierdo información, sino que tengo que comprar otro disco, conectarlo,
y que se copie la información de nuevo.
El RAID 0+1 y el RAID 1+0, son una combinación del RAID 0 y el RAID 1, donde tengo
información distribuida en diferentes discos, y además tengo copia exacta de la información de
cada disco. Se vuelve muy costoso porque necesito un disco más por cada uno que tengo.
De esta forma, tenemos más velocidad al tener la información distribuida en diferentes discos,
y además tenemos más seguridad por tener las copias.

En el caso del RAID 1+0, si se me rompe un disco, lo reemplazo por uno vacío, y lo sincronizo
con la copia que tenía su copia de seguridad. Ni siquiera es necesario apagar la computadora
para hacer esto.
El RAID 2 es donde empiezo a mantener la seguridad, pero necesito menos discos. Por ejemplo,
para mantener la seguridad de 4 discos necesito 3. Para mantener la seguridad de 7 discos
necesito 4. Esto es muy específico por la forma que tiene de funcionar RAID 2, que utiliza algo
que se llama el código de haming. Gracias a este código tengo menos cantidad de discos para
recuperar las cosas.

115
Lucila Canalini

El RAID 3, para un conjunto de bandas, tendré discos con


información, y un disco extra que tendrá información de paridad,
por lo cual, si se me rompe un disco, puedo buscar la información
en el otro.
La idea es que, si en algún momento se rompe el tercer disco, y
sé que la paridad es par, cuando tenga que recuperarlo con
información de paridad, sé cuál es el valor que tengo que completar.
En el RAID 3 la paridad es por bit y los cabezales de los discos están sincronizados, mientras
que en el RAID 4 la paridad es por bloque y los cabezales no están sincronizados, lo que nos da
una mejor eficiencia a la hora de mejorar el tiempo de búsqueda.
Ambos RAIDs tienen un pequeño defecto en el disco de paridad. Cada vez que se hace una
escritura en algún disco hay que modificar la paridad. Por lo que, si hago una escritura en cada
disco, tengo que hacer una escritura por cada una en el de paridad. Termina siendo un cuello
de botella, y por el otro lado se va a gastar más rápido, por tener más uso.
Tanto RAID 3, como RAID 4 y RAID 5, con respecto a la seguridad, no importa la cantidad de
discos con datos que tengo, siempre tendrá uno extra para la paridad. Ventaja que tienen sobre
el RAID 2 y RAID 1+0 o RAID 0+1.
El RAID 5 es una variante del RAID 4 pero con la mejora de que la paridad está en los diferentes
discos, por lo que no habrá un cuello de botella por cada escritura que hago. Funciona igual que
el RAID 4 pero con la paridad distribuida. Así, las escrituras se dispersan de mejor manera.

El RAID 6 es muy parecido al 5, pero en vez de agregar un disco de paridad, agrega dos. Esto es
porque en los RAIDs anteriores si se rompe un disco lo podemos recuperar, pero si se rompen
dos no. En este RAID si se puede.

El RAID 2, 3 y 4 ya casi no se usan. El RAID 0 se puede llegar a usar en algún ambiente que
necesita mucho rendimiento y velocidad. El RAID 1 se puede llegar a usar en un pequeño
servidor. Normalmente en empresas se utiliza RAID 5, RAID 6 o combinaciones, como lo es RAID
5+0.
Lo bueno de tener un RAID en el Sistema Operativo, es que podré tener más espacio, de forma
casera.

116

También podría gustarte