Sistemas Operativos 2
Sistemas Operativos 2
M3.
                                                    Espacio de direcciones
Cuando un programa accede directamente a la memoria física, se dice que no hay ninguna abstracción de memoria. Los
programas se escriben referenciando directamente a direcciones físicas de memoria, que serían las celdas de la memoria.
Algunas opciones para organizar la memoria cuando solo la física está disponible (no hay memoria virtual). Si el SO está en
la RAM es posible borrarlo, no así cuando se encuentra en la ROM.
Bajo el esquema sin abstracción de memoria, normalmente un sistema solo puede ejecutar un proceso, aunque no es imposible
ejecutar varios. Lo que se debe hacer es guardar toda la información que un determinado proceso está utilizando en algún
archivo en disco, para liberar la memora y poder cargar un segundo proceso.
Otra solución que evita el intercambio, es implementar, un sistema de llaves que consiste en dividir la memoria en bloques y
asignarle, a cada bloque, una llave. Todas las llaves se almacenan en registros que permiten controlar que un proceso esté
usando determinado bloque de memoria, lo que evita que otros sobrescriban. La desventaja, es que, si se cargan varios procesos,
aunque no haya sobrescritura, puede haber referencias a datos equivocados.
Inconvenientes debido a referencias absolutas:
Se cargan los programas de a y b en la memoria. En c, se observan ambos
programas cargados, y el inconveniente se produce cuando se ejecuta JMP28.
Como este hace referencia al número 18, se ejecuta la instrucción ADD en
lugar de CMP.
Abstracción de memoria.
Para evitar inconvenientes debidos a las referencias directas a la memoria física, se utiliza una abstracción de memoria
denominada espacio de direcciones, el cual es asignado a cada programa y no hace referencia directa a la memoria física.
La forma más simple es utilizar dos registros: el base y el límite. El funcionamiento es similar al de la parte (c) de la Figura
anterior. El registro base del Programa 1 sería 0, y el límite, 16384. El registro base del Programa 2 sería 16384, y el límite
tendría también el valor 16384.
Lo que el CPU hace cuando debe realizar alguna operación con la memoria es sumar la dirección base. En el caso del ejemplo,
cuando se lee JMP 28 en la dirección 16384, en lugar de saltar a la ubicación 28, se debe sumar el registro base 16384. El
resultado es 16412, precisamente la ubicación de CMP.
Particionamiento fijo.
La memoria se divide en tamaños fijos (pueden ser todos iguales, o no), que pueden ser asignados a diferentes procesos. Un
proceso, entonces, requiere una región cuyo tamaño sea, como mínimo, el que requiere. Si un proceso ocupa más tamaño que
la partición más grande, se deberá corregir mediante el uso de overlays en la etapa de programación.
La desventaja es el desperdicio de espacio. Si un proceso requiere menos tamaño del que ofrece una partición, el resto quedara
inusable, lo cual se denomina fragmentación interna. Es sencillo, sin embargo, implementar esta para el sistema operativo.
Particionamiento dinámico.
El espacio asignado a cada proceso es el que el proceso requiere de forma dinámica, es decir que no existen particiones previas
que ofrecer. El uso es más eficiente y, además, no existen las fragmentaciones internas que se producen en el método anterior.
Tiene como desventaja la fragmentación externa, que implica que existen muchos huecos en la memoria.
                                                  La memoria como recurso escaso
Los programas demandan cada vez más memoria, y los usuarios demandan cada vez más programas que funcionen en
simultáneo. Si bien las memorias crecen en tamaño y disminuyen sus costos, nunca es suficiente. Para lidiar con el problema
del agotamiento de la memoria RAM, existen dos opciones: el intercambio y la memoria virtual.
Intercambio.
En el momento (a), solo el proceso A está cargado en memoria
RAM. En los momentos (b) y (c), los procesos B y C se cargan
también a la memoria RAM, la cual todavía no está llena. Sin
embargo, por decisión del sistema operativo, en el momento (d)
el proceso A es intercambiado al disco y libera el espacio que
consumía de la memoria RAM. En el momento (e), el proceso
D ingresa a RAM y consume parte del espacio que dejó A. En
el momento (f), el proceso B abandona la memoria y libera
espacio. Y, finalmente, en el momento (g), el proceso A regresa
a la RAM y ocupa el espacio que liberó B, más parte del espacio
que liberó él mismo anteriormente.
En general, los procesos entran y salen, y generan pequeños huecos (fragmentación externa) que luego no les sirven a otros
procesos que requieren mayor espacio. También puede darse el caso de que un determinado proceso necesite crecer y consumir
más espacio de direcciones. En este caso, dicho proceso utilizará el espacio contiguo, si es que lo hay. Pero si no lo hay, se
debe intercambiar otros procesos hasta generar un hueco suficiente para el nuevo tamaño deseado. Pensar en el futuro
crecimiento de los procesos, y asignarles a estos espacios de más, es una solución a este desafío.
                                                     Ubicar procesos en memoria
Si se utilizó una partición de memoria con tamaños iguales, la ubicación es sencilla. Se debe seleccionar cualquier sector libre
para ubicar un determinado proceso.
Si la memoria está llena y se debe realizar un intercambio, el planificador deberá seleccionar algún sector cuyo proceso no se
encuentre listo.
Si la memoria se parte en sectores de diferente tamaño, la primera opción consiste en ubicar un determinado proceso en el
sector más pequeño posible, para evitar desperdiciar recursos. La desventaja es que pueden quedar sectores grandes sin usar,
debido a que el tamaño requerido por algún proceso es menor al tamaño de otros sectores. Esto se soluciona con una única cola
de procesos, que selecciona el sector más pequeño posible o recurre a un intercambio a disco para hacer lugar.
   Cuando se utiliza el particionamiento dinámico, se requiere ubicar procesos de forma eficiente. Para lograr esta tarea, existen
   tres algoritmos.
 Mejor ajuste (best-fit): busca al bloque de memoria que más se aproxime al tamaño requerido por el proceso.
 Primer ajuste (first-fit): comienza su búsqueda en el inicio de la memoria y se detiene apenas consigue un bloque
  suficientemente grande como para cumplir con la solicitud del proceso.
 Siguiente ajuste (next-fit): al igual que el algoritmo anterior, este se detiene cuando consigue un bloque lo suficientemente
  grande para la solicitud del proceso, pero en lugar de comenzar al inicio de la memoria, comienza su búsqueda desde la última
  colocación.
   Lec. 2
                                                    Paginación y segmentación
   Cuando se divide la memoria principal en regiones, ya sean fijas o variables, surge el problema de la fragmentación, lo cual
   hace que la utilización de la memoria no sea la óptima. Pero, en realidad, el problema surge porque los tamaños de las regiones
   y de las solicitudes que hacen los procesos no son lo suficientemente pequeñas como para evitar dicha fragmentación.
   Paginación, consiste en dividir los procesos en pequeñas partes, denominadas páginas. Cada una tendrá asignada una porción
   de igual tamaño en la memoria principal, la cual se denomina marco de página. Como ambos tamaños son iguales, ya que las
   particiones son de tamaño fijo, se elimina la fragmentación externa.
   Cuando se utiliza la segmentación, los programas se dividen en segmentos, que, a diferencia de las paginas, son variables,
   algo que asemeja esta técnica con el particionamiento dinámico.
Paginación.
La memoria principal consta de 15 marcos disponibles, los
  cuales se encuentran desocupados en el momento a. el
proceso A ingresa en memoria principal en el momento b y
                 consume cuatro marcos.
   En los momentos c y d, los procesos B y C ingresan a
        memoria y consumen tres y cuatro páginas.
    En el momento f, el proceso D ingresa a la memoria
                         principal.
 Como este proceso ocupa cinco páginas, puede utilizar los
 tres espacios que libero el proceso B, más otros dos. No es
       necesario que estos espacios estén todos juntos.
Protección de memoria.
Para evitar que un proceso sobrescriba a otro en una implementación con paginación, se utiliza un bit de protección asociado a
cada marco, los cuales normalmente se almacenan en la tabla de páginas. Este bit indica si es posible leer y escribir, o solo
leer.
Los marcos 0, 1, 2, 3, 4 y 5 tienen el bit V (valido), es decir que es posible
leer y escribir. En cambio, los marcos 6 y 7 son inválidos, por lo que, si se
intentara escribir allí, se generaría un trap o una violación a la protección de
memoria.
En este ejemplo, el proceso utiliza de 0 a 10 468. Al no utilizar entre 10 468
y 12 287, se genera fragmentación, ya que este espacio no puede ser
utilizado por otro proceso.
Paginas compartidas.
En determinadas situaciones como, por ejemplo, cuando múltiples usuarios utilizan la misma aplicación, es posible, si el
código del programa lo permite, que estos compartan información en memoria. Esta información es el código de ejecución
del programa, que no cambia.
Todas las tablas de páginas de los diferentes procesos que usen la aplicación compartida harán referencia a los mismos marcos
de memoria para el código, mientras que utilizarán marcos distintos para la información propia. Con este esquema, el ahorro
de memoria principal es significativo.
Segmentación.
Los segmentos de un programa no requieren espacios contiguos de memoria principal. Es una gran ventaja, ya que permiten un
uso más eficiente de la memoria. Además, como es posible dividir los programas en fragmentos más pequeños que las secciones
de un particionamiento dinámico, la fragmentación externa es, menor.
A diferencia de la paginación, la segmentación se basa en la forma en que un programador ve la memoria: un conjunto de
segmentos de tamaño variable, que no están necesariamente en orden. Entonces, en este tipo de gestión de memoria, las
direcciones especifican tanto el nombre de un segmento como su longitud. Este nombre, por razones de simplicidad, es tratado
como un número.
Se requiere, además, un mecanismo que mapee estas direcciones con dos
variables en direcciones de una sola dimensión, que es como se identifica
a las direcciones físicas de la memoria principal.
Esto se logra mediante una tabla de segmentos:
Cada segmento se identifica en la tabla con un número (de 0 a 4) y con
sus dos dimensiones (base y limite). Por ej., el segmento 0 tiene su base
de la memoria principal en 1000, y su límite es 1400, por lo que puede
consumir hasta 1400. Cualquier referencia a una dirección de memoria
que se encuentre fuera de este límite generara un trap.
En el ejemplo, se generaría un trap si hubiera una referencia al byte 1300
del segmento 0. Si sumamos 1300 más 1400, obtenemos por resultado
2700, que está fuera del rango que ocupa el segmento.
Lec.3
                                                     Memoria virtual
Para que un proceso pueda ejecutarse, debe estar en la memoria principal.
Puede suceder, debido a la voracidad de las aplicaciones, que un proceso necesite más memoria que la que existe físicamente
en una computadora. El programador de dicha aplicación puede usar el concepto de overlays para dividir este tamaño en otros
más pequeños, pero, para evitar que el programador sea el encargado de dicha tarea, se emplea el concepto de memoria virtual.
Esta memoria toma su nombre del hecho de que un programador ve una memoria superior a la memoria física real. Esto es
posible porque utiliza espacio en el disco o en la memoria secundaria.
Resulta más eficiente dejar datos o instrucciones no necesarios en la memoria secundaria y solicitarlos cuando el procesador
los requiere, que tener todo en la memoria principal, y desperdiciar espacio que podría ser usado por un proceso que realmente
debe ser procesado.
Lo que el sistema operativo debe evitar es el efecto denominado thrashing, por el que, debido a la cantidad de intercambios
entre las memorias principal y secundaria, el sistema se pasa más tiempo intercambiando qué procesando. Para evitar este
efecto, se utilizan diversos algoritmos.
Paginación en la memoria virtual
Si bien se mantiene una tabla por proceso, ahora debe indicarse si la página está en la memoria principal o en la secundaria. En
el caso de que esté en la memoria principal, se indicará el marco, al igual que en el caso de la memoria real. También se utiliza
un bit adicional que indica si los datos de la entrada que contiene el bit fueron modificados cuando estuvieron en la memoria
principal.
Bit P para indicar si la página está o no en la memoria principal, el bit M para
indicar si fue modificada.
Como los procesos pueden disponer ahora de mucho espacio virtual, la cantidad de
páginas en una tabla puede ser muy grande. Sería un gran problema que las tablas de página completas se almacenaran en la
memoria principal, porque gran parte de esa memoria estaría destinada a almacenar información de las tablas, y no al
almacenamiento de instrucciones y de los datos. Para evitar esto, una parte de las tablas de páginas también se almacena en la
memoria virtual.
Tabla de páginas con jerarquía.
El procesador utiliza un esquema de dos niveles. Cada entrada
de un directorio general apunta a una tabla de páginas. Si la
extensión del directorio es X, y la longitud máxima de la tabla
de páginas es Y, entonces un proceso consistirá en X=Y
páginas.
En la figura se observa el mecanismo utilizado para traducir
una dirección virtual. La página raíz siempre se mantiene en
la memoria principal. Los primeros 10 bits de la dirección
virtual se pueden usar para indexar en la tabla de páginas raíz,
a fin de encontrar la ETP (entrada de tabla de página) para la página en la que está la tabla de páginas de usuario. Si la página
no está en la memoria principal, se produce un fallo de página. Si la página está en la memoria principal, los siguientes 10 bits
de la dirección virtual se usan para indexar la tabla de páginas de usuario, a fin de encontrar la ETP de la página a la cual se
hace referencia desde la dirección virtual original.
Implementación de la traducción de direcciones.
Mientras menos marcos se reserven, más notoria es la diferencia a favor del algoritmo OPT, el cual, debemos recordar, no es
posible que sea implementado. Pero, a medida que aumenta la cantidad de marcos reservados, la diferencia no es tan notoria,
aunque se mantiene el orden OPT, LRU, Reloj y FIFO.
Debido a la utilización necesaria del bit que indica si una página fue modificada o no en la memoria, ahora es posible disponer
de cuatro estados para optimizar el funcionamiento del algoritmo del reloj:
00 = No se accedió recientemente, no se modificó
10 = Accedida recientemente, no se modificó
01 = No se accedió recientemente, modificada
11 = Accedida recientemente, modificada.
    1. Comenzando por la posición actual del puntero, recorremos el buffer de marcos. Durante el recorrido, no se hace ningún
       cambio en el bit de usado. El primer marco que se encuentre con (u = 0; m = 0) se selecciona para reemplazo.
    2. Si el paso 1 falla, se recorre el buffer de nuevo, en busca de un marco con (u = 0; m = 1). El primer marco que se
       encuentre se seleccionará para reemplazo. Durante el recorrido, se pondrá el bit de usado a 0 en cada uno de los marcos
       que se vayan saltando.
    3. Si el paso 2 también falla, el puntero debe haber vuelto a la posición original, y todos los marcos del conjunto tendrán
       el bit de usado a 0. Se repite el paso 1 y, si resulta necesario, también el paso 2. Esta vez, se encontrará un marco para
       reemplazo.
En la primera vuelta del buffer, el algoritmo busca reemplazar la opción 00 (no modificadas, no accedidas recientemente). Al
no tener que escribir en el disco, esto mejora el rendimiento. Si no hay candidatos en su segunda vuelta, buscará la combinación
01 (modificada, no accedida recientemente); se le da más valor al hecho de que la página probablemente no vuelva a ser usada,
que a la demora que implica tener que escribir en el disco.
Buffering. Para aprovechar la simpleza de implementación del algoritmo FIFO, el buffering permite que una página que deba
ser reemplazada vaya a la lista de páginas modificadas o a la lista de no modificadas. La ventaja es que esa página permanece
en la memoria principal.
M4
                                                     Sistema de archivos
Los archivos son fundamentales para la mayoría de las aplicaciones, ya que estas obtienen información que requiere ser
procesada desde un archivo o bien, una vez procesada la información, las aplicaciones deben almacenarla en almacenamiento
secundario a fin de no perder datos ante falta de energía. Asimismo, para evitar que cada aplicación deba disponer de un código
para interactuar con los archivos, se crea una abstracción que permite, por ejemplo, crear archivos, guardar información,
copiarlos o eliminarlos.
Niveles de gestión de archivos.
Desde el programa de usuario hasta un medio de almacenamiento
secundario. A medida que se sube de nivel, hay más interacción con el
software que con el hardware. Los manejadores (nivel inferior) deben
interactuar de forma directa con el hardware. Así, inician peticiones de
E/S y las finalizan.
Este nivel es gestionado por el sistema operativo. El nivel sistema de
ficheros (archivos) básico maneja bloques entre la memoria principal y el
almacenamiento secundario. También se lo considera parte del sistema
operativo.
El supervisor de E/S básico se encarga de todas las iniciaciones y
finalizaciones de E/S. Permite, además, obtener mejores rendimientos a partir del empleo de algoritmos de planificación. Al
igual que los niveles anteriores, es parte del sistema operativo. El sistema de ficheros básicos se maneja con bloques, mientras
que el nivel E/S lógico se maneja con registros y su acceso.
Los registros son conjuntos de campos relacionados y tratados como una única unidad. Por su parte, un campo es la unidad
mínima de datos. Finalmente, el nivel superior se denomina método de acceso y permite diferentes maneras de acceder a un
archivo.
Funciones de un sistema de archivos.
Cuando los programas o usuarios necesitan acceder a un
archivo, un software de gestión de directorios lo ubica y un
software de control de acceso de usuario válida que lo que
usuario esté intentando hacer sea posible. Una vez ubicado el
archivo, se accede mediante un método de acceso a los
registros. A partir de este momento deben convertirse los
registros en bloques, la unidad utilizada por las peticiones de
E/S. Así, se debe ubicar el lugar del almacenamiento
secundario en el que se grabará ese bloque o aquel donde
actualmente se encuentra para ser leído. Un planificador hará
este trabajo lo más eficiente posible.
Acceso a archivos.
Los archivos están formados por registros, los cuales luego son convertidos en bloques para ser almacenados en el disco. La
forma en que se accede a un registro (no a los bloques en el disco) determina la estructura lógica de un archivo.
Diversas formas de acceso:
     Pila. forma más simple de organizar un archivo. Los datos van llegando al archivo y en ese orden se va formando una
      pila de registros. Como los registros pueden tener diferentes tipos de campos, estos deben autodescribirse. Su longitud
      debe estar indicada de manera explícita, de modo que luego sea posible utilizar el método de búsqueda exhaustiva para
      obtener un dato particular. Esta búsqueda revisa todos los registros y busca coincidencias entre registro, campo y valor.
      No obstante, como en general debe recorrerse gran parte del archivo (o todo) para encontrar el dato buscado, este
      método no es el más usado por la mayoría de las aplicaciones.
     Archivo secuencial. En un archivo secuencial todos los registros son de igual tamaño. Cada registro está compuesto
      por un número predefinido de campos de igual tamaño. No es necesario, entonces, identificar información adicional
      sobre el tamaño. Se denomina campo clave al primer campo de cada registro, el cual identifica de forma única a cada
      registro y sirve, además, para realizar un orden, ya sea alfabético o numérico. Si bien el rendimiento no es bueno para
  aplicaciones interactivas que requieren consultar y actualizar registros individuales, es ideal para aplicaciones por lotes.
  Aun así, el rendimiento no es bueno, ya que se debe buscar la clave, lo cual lleva tiempo.
 Archivo secuencial indexado. Para mejorar el rendimiento del archivo secuencial, se agregan en este caso dos
  funcionalidades: índice y archivo de desbordamiento.
  El índice funciona como el de un libro: es mucho más rápido buscar contenido en el índice que si se recorren todas las
  hojas del libro. Además, proporciona acceso aleatorio. El índice se forma con un archivo secuencial, cuyos registros se
  forman por dos campos: el campo clave, igual al campo clave del registro del archivo que contiene todos los datos
  (denominado principal), y un puntero a dicho archivo principal. De esta forma, ubicar un campo clave en el archivo
  índice es mucho más rápido que hacerlo en el archivo principal. El archivo de desbordamiento es útil para agregar
  información al archivo.
 Archivo indexado. Permite realizar búsquedas por atributos que no sean el campo clave. Para lograrlo, se debe utilizar
  un índice por cada atributo que puede utilizarse para la búsqueda. Un índice exhaustivo contiene una entrada por cada
  registro del fichero principal. Para facilitar la búsqueda, el índice, a su vez, está organizado como un fichero secuencial.
  Un índice parcial contiene entradas a los registros donde el campo de interés existe.
                        Comparación indexado, secuencial indexado:
El sistema de archivos es la forma en que el sistema operativo va a organizar la información dentro de un disco para su
grabación y posterior recuperación. Cada sistema operativo tiene su propio y único sistema de archivos, lo que hace que no
pueda funcionar con otros. Por ejemplo:
                 DOS y Windows hasta 3.11: FAT 8 o 12.
                 Windows 95: FAT 16 o 32.
                 Windows 98, ME, XP: FAT 32.
                 Windows XP, 2000, NT: NTFS.
                 Linux, Unix.
                 FAT (File Allocation Table – Tabla de Asignación de Archivos): consiste en una serie de sectores (que se
                    agrupan bajo el nombre de clusters) que alojan la mínima porción de información, y una tabla que enlista
                    los sectores libres y los ocupados. Los sectores tienen dos características que, con el tiempo, se les fueron
                    en contra. Una, que son de tamaño fijo; la otra, que cuanto más grande sea el disco, mayor es su tamaño.
                 FAT16
                 FAT 32
Los sistemas operativos de Microsoft distinguen el tipo de FAT (12-16-32) utilizado en un volumen mediante la siguiente regla:
       se obtiene el número total de sectores en el volumen.
       Se le resta el espacio de sectores reservados.
       Se le resta el espacio ocupado por las FAT.
       Se le resta el espacio ocupado por el directorio raíz.
       El total anterior se divide por el número de sectores en un cluster redondeando hacia abajo. El resultado R es el número
        de clusters en el área de datos.
                 NTFS (new technology file system). soporta completa seguridad. Puede decidir los tipos de acceso a archivos
                  y directorios. Guarda un LOG (archivo) de actividades para reconstruir el disco en el caso de problemas
                  eléctricos. La madre de todo volumen formateado con NTFS es la Master File Table, una base de datos que
                  contiene los atributos de todos los ficheros. Podríamos considerarlo similar en funciones a la FAT, aunque
                  hace mucho más.
                      Cada fichero tiene asociada una entrada en la MFT que contiene una serie de atributos. Debemos distinguir
                      entre atributos internos (almacenados en el propio registro de la MFT) y externos, que son referenciados
                      mediante punteros en la MFT. Casi todos los atributos de cada fichero pueden ser internos o externos. En
                      cada fichero se almacenan atributos como: Una cabecera, que es siempre interna; un atributo con
                      información estándar (timestamps para creación, modificación y acceso de cada fichero), así como si un
                      fichero es de solo lectura, oculto y demás; otro atributo con el nombre del fichero (teniendo en cuenta que
                      es posible que cada fichero tenga muchos nombres, dado que podemos realizar hard links en distintos
                      directorios a un mismo archivo); otro atributo con los datos del propio fichero, y un descriptor de seguridad
                      (como las listas de control de acceso).
                      Adicionalmente, los directorios indexan los archivos en estructuras más complejas que en el caso de FAT.
                      De meras colecciones de registros pasamos a utilizar una estructura compleja como es el caso de un árbol
                      B+, ofreciendo un rendimiento bastante superior.
                      La principal desventaja de NTFS es que, como podemos imaginar, la MFT puede transformarse en un
                      verdadero monstruo (dado que controla todo el sistema de ficheros). En el momento de formatear un
                      volumen con este sistema de fichero se reserva aproximadamente un 12,5 % del tamaño del volumen para
                      la MFT. Esto hace de NTFS un sistema de ficheros poco adecuado para sistemas de archivos pequeños.
                 Ext. los sistemas de archivos de Linux, particularmente ext3 y ext4. Son similares porque existe una estructura
                  por cada volumen con información de los archivos. Son distintos, a su vez, por el tipo de estructura. Es
                  inevitable hablar de inodos: registros identificados por un número entero que contienen los metadatos de los
                  archivos.
Estructura del sistema de archivos en Linux.
Virtualización.
En la actualidad se torna fundamental en referencia a los sistemas operativos, especialmente en el papel de servidores.
Este concepto no se refiere a una única metodología o tecnología, sino que agrupa varias de ellas. En términos generales,
virtualizar consiste en proveer algo que no está ahí, para que parezca estarlo. Es decir, presentar a un sistema elementos
que se comporten de la misma forma que un componente físico (HW) sin que exista en realidad.
El concepto de virtualización se asocia siempre a dos partes:
    o   Anfitrión. Es el HW o sistema real que ofrece el mecanismo de virtualización. En ingles se denomina host.
    o   Huésped. Es el sistema o aplicaciones que se ejecutan en el entorno virtualizado. En ingles, guest.
Emulación.
La técnica de virtualización más sencilla, y que hace más tiempo tienen las computadoras personales, es la emulación. Emular
consiste en implementar en software algo que se presente como el hardware de un sistema completo, típicamente de una
arquitectura de hardware distinta a la del anfitrión (la arquitectura nativa). El emulador puede ser visto (de una forma
extremadamente simplificada) como una lista de equivalencias, de cada una de las instrucciones en la arquitectura huésped a la
arquitectura del sistema anfitrión.
Una emulación no se limita con traducir del lenguaje y la estructura de un procesador a otro —para que una computadora pueda
ser utilizada, requiere de una serie de chips de apoyo, desde los controladores de cada uno de los buses hasta los periféricos
básicos (teclado, video). Casi todas las emulaciones incluirán un paso más allá: los periféricos mismos (discos, interfaces de
red, puertos). Todo esto tiene que ser implementado por el emulador.
Resulta obvio que emular un sistema completo es altamente ineficiente. Los sistemas huéspedes resultantes típicamente tendrán
un rendimiento cientos o miles de veces menor al del anfitrión.
Hoy en día las máquinas virtuales implementan varias técnicas para reducir el tiempo que se desperdicia emulando.
     Traducción dinámica: Compilación parcial del código a ejecutar a formatos nativos, de modo que solo la primera
      vez que se ejecuta el código intermedio tiene que ser traducido.
     Traducción predictiva: Anticipar cuáles serán las siguientes secciones de código que tendrán que ser ejecutadas
      para, paralelamente al avance del programa, traducirlas a código nativo de forma preventiva.
     Compilación justo a tiempo (JIT): almacenar copia del código ya traducido de un programa, de modo que no tenga que
      hacerse ni siquiera en cada ejecución, sino que solo una vez en la vida de la máquina virtual.
Lec. 2
                                                Asignación de espacio a archivos
Es posible agregar a un archivo espacio en almacenamiento secundario de forma dinámica o mediante preasignación. La
segunda opción consiste en asignar el espacio total que va a requerir la aplicación. Esta es su desventaja, ya que en muchas
aplicaciones no es fácil estimar este espacio, y muy probablemente el programador asigne espacio de más, el cual termina por
ser desperdiciado. La asignación dinámica, va otorgando espacio a medida que la aplicación lo necesita.
Para elegir el método de asignación también hay que tener en cuenta el tamaño de la porción. Una porción puede ser tan grande
como el archivo o tan pequeña como el tamaño de un bloque.
Asignar de forma contigua mejora el rendimiento. Utilizar muchas porciones pequeñas incrementa la carga para la gestión. Si
las porciones son de tamaño fijo, se simplifica la reasignación. Usar porciones pequeñas o de tamaño fijo optimiza la utilización
de espacio cuando hay reasignaciones.
Para decidir el tamaño de la porción, se utilizan dos variables: mejor rendimiento (porciones variables, grandes y contiguas) y
mayor flexibilidad (pequeñas porciones fijas).
3 métodos para asignar espacio a los archivos: asignación contigua, encadenada, indexada.
Asignación contigua. Requiere que cada archivo utilice bloques contiguos en almacenamiento secundario. Esto permite menos
latencia por parte del disco, ya que los bloques se ubican en sectores contiguos de una misma pista o solo es necesario moverse
de una pista a la siguiente. Soporta acceso tanto secuencial como directo.
Asignación indexada. Cada archivo tiene su propio índice de bloques en una estructura similar a la de paginación de memoria.
Un archivo nuevo tendrá todos sus punteros nulos, pero cuando se utiliza el primer bloque se obtiene su ubicación y esta se
coloca como puntero. Este método no produce fragmentación externa, como la asignación continua. Y mejora la proximidad
sobre la asignación encadenada. Estas ventajas hacen que sea el método más utilizado.
                                                     Modelo cliente/servidor.
Revolucionó las comunicaciones y permitió que diferentes dispositivos interactúen entre sí a través de una red de
comunicaciones.
Para permitir la comunicación entre los procesos de dos computadoras, se utiliza un socket, el cual puede ser orientado a la
conexión (se establece un circuito virtual antes de transferir datos de usuario, por ejemplo, con el protocolo TCP) o no orientado
a la conexión (UDP). El servidor tiene abierto un socket que escucha en un determinado puerto. De esta manera, la aplicación
del cliente intentará conectarse al servidor usando ese número de puerto. Cuando un cliente se conecta, la comunicación se hace
por otro puerto del servidor y el primero se libera para una nueva conexión. Múltiples clientes pueden interactuar con una
aplicación de un servidor.
El socket contiene tres valores: el protocolo que se utiliza (UDP o TCP), la dirección IP y el puerto. Cuando el socket emplea
TCP, se denomina socket stream. Si es para UDP, se denomina socket datagrama y es utilizado como API (interfaz de
programación de aplicaciones) que necesitan usar los protocolos de la capa de transporte UDP o TCP.
Son ejemplos de aplicaciones que utilizan el modelo cliente-servidor el correo electrónico, con sus protocolos POP, SMTP o
IMAP, el servicio para transferencia de archivos FTP o el servicio de shell segura (SSH), utilizado para conectarse remotamente
a una consola. Todos estos protocolos mencionados corresponden a la capa de aplicación del modelo TCP/IP y requieren de
los servicios que ofrece la capa inmediata inferior (transporte y sus protocolos UDP y TCP) para poder funcionar.
Arquitectura cliente-servidor.
En la computadora del cliente, un servicio de presentación le ofrece una
interfaz amigable para su aplicación. Por debajo se encuentra la lógica de
dicha aplicación. Aquí se realiza la interacción al nivel de la aplicación, pero
recordemos que en realidad este es el nivel superior del modelo TCP/IP.
Realmente esa interacción debe utilizar todas las capas del modelo para
poder llegar a destino y ser procesada por el servidor. Los protocolos
permiten que sistemas operativos y hardware diferentes puedan interactuar
entre sí, ya que en esencia un protocolo es un lenguaje común que debe
implementarse.
Implementaciones.
     Procesamiento basado en host. El dispositivo cliente es una terminal boba, ya que todo se realiza en el servidor,
      inclusive la interfaz de usuario. La terminal solo se usa para acceder al dispositivo remoto y realizar todo allí.
     Procesamiento basado en servidor. El procesamiento se realiza en el servidor y para el cliente solo está disponible la
      interfaz para que acceda el usuario.
     Procesamiento cooperativo. Permite una mayor productividad, ya que utiliza recursos tanto del cliente como del
      servidor para realizar las operaciones necesarias. Sin embargo, es más compleja que el resto de las implementaciones.
     Procesamiento basado en el cliente. La mayoría (no todas) las operaciones se realizan en el cliente, lo que libera el uso
      de recursos del servidor y lo habilita para permitir más clientes conectados.
El modelo cliente-servidor clásico también puede estar compuesto por tres capas. Entre el cliente y el servidor clásico
se adiciona una capa central, que es otro servidor que puede ser utilizado para convertir protocolos o procesar datos
obtenidos del servidor clásico, lo que libera a este de dichas tareas para que especialice y mejore el rendimiento de otras.
Técnicas de envío de mensajes.
La primera técnica consiste en el envío y recepción simple de mensajes, los cuales se implementan básicamente con las
funciones send para enviar y receive para recibir. Lo que la función receive hace es indicar de quien se recibirá el mensaje y
definir espacio en un buffer donde llegaran los datos recibidos. Send especifica un destino y los datos que se van a transmitir.
Luego de construirse una unidad de datos mediante la función send, el conjunto de protocolos TCP/IP hará posible enviarla a
destino a través de una o más redes. Cuando llegue a destino, el mismo conjunto de protocolos TCP/IP recorrerá el camino
inverso a través de sus capas para entregar la unidad de datos, la cual es analizada para determinar cuál es el proceso que debe
utilizarla para luego pasarla a su respectivo buffer.
Este tipo de pase de mensajes puede ser fiable cuando el protocolo de la capa de transporte garantiza la entrega. La aplicación
puede dar por hecho que una vez que envía un dato, este llegará a destino o, en caso contrario, será informado el error. En el
caso de que no se utilice el protocolo TCP y se utilice UDP, no se garantiza la entrega de datos, por lo cual el pase de mensajes
pasa a ser no fiable y la aplicación debe realizar un control.
El pase de mensajes puede, además, ser bloqueante o no bloqueante. Un send bloqueante no devuelve el control al proceso
emisor hasta que el mensaje haya sido transmitido (servicio no fiable) o hasta que el mensaje haya sido enviado y se haya
recibido el acuse de recibo (servicio fiable). Un receive bloqueante no devuelve el control hasta que el mensaje haya sido
situado en su correspondiente buffer.
La segunda técnica consiste en llamadas a procedimientos remotos o remote procedure call (RPC). Los programas dentro de
una misma máquina utilizan este esquema. Entonces, por su gran aceptación y conocimiento, resulta conveniente llevarlo a un
sistema distribuido.
Política militar.
-Se basa en la clasificación de todos los recursos con requisitos de seguridad en alguno de los siguientes niveles: desclasificado,
restringido, confidencial, secreto, alto secreto.
- Los usuarios que tienen acceso a recursos del nivel I también lo tienen a los de nivel i+1.
-regla de lo que se necesita saber: solo se permite el acceso a datos sensibles a quien los necesita para hacer su trabajo.
Política comercial.
-se basan en la política militar, pero debilitan los requisitos.
-la muralla china clasifica a recursos y usuarios en 3 niveles de abstracción: objetos, grupos, clases de conflictos
-cada objeto pertenece a un único grupo y cada grupo a una única clase de conflicto.
-una clase de conflicto, sin embargo, puede incluir a varios grupos.
- política de control de acceso: una persona puede acceder a la información siempre que antes no haya accedido otro grupo de
la clase de conflicto a la que pertenece la información a la que quiere acceder.
Modelos de seguridad. Un modelo es un mecanismo que permite hacer explícita una política de seguridad.
   Modelos de seguridad multinivel: rangos de seguridad y separación rigurosa entre usuarios y objetos a los que no tienen
      acceso. Suelen ser modelos muy abstractos y costosos de implementar.
    Modelos de seguridad limitada: responden formalmente a las propiedades que un sistema seguro debe satisfacer. Se
     basan en dos principios:
     -usan la teoría general de sistemas para definir un sistema formal de reglas de protección.
     - Usan una matriz de control de acceso en cuyas filas están los usuarios y en las columnas los objetos.
Principios de seguridad de un sistema operativo.
   o   Diseño abierto.
   o   Exigir permisos.
   o   Privilegios mínimos.
   o   Mecanismos económicos.
   o   Compartición mínima.
   o   Fáciles de usar y adaptar.
   o   Separación de privilegios
Tareas de seguridad.
   o   Autenticación de recursos.
   o   Asignación de recursos.
   o   Control de acceso a los recursos.
   o   Control de compartición y comunicación entre procesos.
   o   Protección de datos.
Tareas de seguridad y componentes del sistema operativo.