2.19. EJEMPLO SISTEMAS DISTRIBUIDOS
MACH
2.19.1. PRESENTACION

Mach es un núcleo de sistema operativo desarrollado en la Carnegie-Mellon University (CMU) para soportar la investigación de sistemas operativos, principalmente computación distribuida y paralela. El proyecto en CMU se ejecutó desde 1985 hasta 1994.
Mach se desarrolló con la premisa de que todos los sistemas operativos modernos comparten una serie de características en común, o son deseadas si es que no las tienen aún.
OBJETIVOS:
w Base para la construcción de otros sistemas (UNIX).
w Espacio de direcciones de gran tamaño.
w Acceso transparente a los recursos de la red.
w Paralelismo del sistema y las aplicaciones.
w Escalabilidad (transportar mach a un número más grande de máquinas).
w Soporte para múltiples aplicaciones usando multitarea.
w Hilos, los cuales pueden ser pensados como las partes de una aplicación, o mini-aplicaciones cuando hay multitarea.
w Soporte multiprocesadores, en una máquina única o sobre una red.
w Comunicaciones interprocesos, enviando mensajes directamente entre aplicaciones.
w Protección y seguridad de memoria.
w La emulación del sistema operativo se lleva a cabo en el espacio del usuario.

HISTORIA:

Por la época, a inicios de la mitad de los '80, varios proyectos estuvieron intentando resolver uno de estos problemas. Esto típicamente significó tomar un sistema operativo existente – a menudo BSD (UNIX)- modificando partes del mismo. Después de cada modificación el sistema operativo era compilado, la máquina reiniciada, y se probaba el nuevo cambio. Había una serie de problemas con este enfoque, incluso los más insignificantes causarían que la máquina entera se colgara.

Mach explora el concepto al que ahora nos referimos como micronúcleo. En vez de tener todo el código para el sistema operativo en un gran programa único (llamado núcleo), la mayoría del código estaría ubicado en programas más pequeños conocidos como servidores, los cuales se ejecutarían como cualquier otro programa. El trabajo del núcleo se reduce esencialmente en "ser" el sistema operativo, a mantener los servidores y programar su acceso al hardware.


En teoría esto significa que los cambios al S.O. requerirían nada más que una recarga de ese único programa servidor, concepto opuesto a reconstruir el Sistema Operativo y reiniciar la máquina. Solo trabajar en el núcleo Mach en sí mismo requeriría un reinicio, y en teoría eso debería ser un hecho inusual.

Mach no es un sistema operativo en sí mismo, y es bastante inútil sin un conjunto de servidores (estos servidores no existen). De modo que para obtener un sistema útil y ejecutándose, los autores de Mach portaron el Unix BSD al núcleo Mach de forma rápida y simple: en vez de separar BSD en distintas partes y construir cada una de ellas como un servidor, simplemente compilaron el núcleo entero en un servidor y lo ejecutaron. El resultado era conocido como POE.

Con POE ejecutándose (efectivamente) entre las otras aplicaciones, el rendimiento fue pésimo. Cada llamada de una aplicación de usuario, digamos para obtener la hora, requería que el mensaje fuera enviado al núcleo (una operación simple conocida como cambio de contexto), el cual enviaría el pedido a la librería Unix con otro cambio de contexto y luego repetir todo de nuevo para la respuesta... Sin embargo, Mach, a pesar de que no era un fallo propio, era considerado muy poderoso, pero increíblemente lento.

Durante la década siguiente, el trabajo se orientó a mejorar el funcionamiento de estos mensajes varias veces, hasta el punto de que el rendimiento de estos sistemas operativos basados en Mach fuera a menudo mejor que el de los BSD en los que estaban basados. Sin embargo por ese tiempo el mundo académico había perdido en gran parte interés en la investigación de SSOO, y la promesa de Mach's siguió sin cumplirse.

En la actualidad A finales del siglo XX se ha pensado que el Mach asumiría lentamente el control del universo entero de sistemas operativos, pero esto no ha sucedido. Quizás la razón más grande del fracaso de Mach puede ser la "holgazanería": a todos les parecía que era el trabajo de otro entregar la biblioteca basada en el SO, y no lo hizo nadie. El esfuerzo más grande hasta la fecha es GNU Hurd, pero GNU Hurd está ahora alrededor de una década de atraso. Varios sistemas operativos propietarios han sido más acertados, incluyendo QNX que parece cumplir todas las promesas de Mach's.

El trabajo sobre Mach se llevó durante varios años en la CMU, para quedar finalmente inactivo cuando muchos de los desarrolladores dejaron la academia para trabajar en la industria. Mach fue brevemente revivido en la Universidad de Utah a mediados de los 90s y produjo el Mach 4 que tenía mejoras significativas, antes de otra vez volverse inactivo.

Mientras tanto varios vendedores tomaron enfoques prácticos para usar Mach. La capa del BSD (y otras) fue ejecutada directamente dentro del núcleo (lo que evita así intercambios de contexto) lo que dio lugar a un rendimiento razonable mientras que todavía conservaba las ventajas del multiprocesamiento y de un modelo de hilos fácil de usar. Sin embargo incluso estas ventajas se han erosionado tanto como el hecho de que varios vendedores de Unix que han trabajado para proporcionarlas en sus propios productos.
VENTAJAS:
· Mayor sencillez de cada parte.
· Independencia y portabilidad del sistema operativo.
· Ejecución de varios sistemas operativos a la vez.
· Mayor seguridad (cada proceso tiene su propio sistema operativo. Difícil husmear ficheros del otro sistema.)

2.19.2. ESTRUCTURA Y COMPONENTES DEL SISTEMA

MICRO NUCLEO:

  • El núcleo de Mach se encarga de las siguientes tareas:

o Administra los procesos.
o Administra la memoria.
o Controla la comunicación.
o Controla los servicios de E/S.
o La administración de la memoria se basa en los llamados objetos de memoria.
o Son estructuras de datos asociadas con el espacio de direcciones de un proceso. Al producirse un fallo de página puede enviar un mensaje a un servidor a nivel de usuario.
o La comunicación entre los procesos se realiza entre puertos que tienen asignados.
o En el espacio de usuario se controlan el resto de características de un sistema operativo como los archivos, directorios y otras funciones.

PRINCIPALES CARACTERÍSTICAS DEL DISEÑO:

• Operación multiprocesador: Mach fue diseñado para ejecutarse en un multiprocesador de memoria compartida de forma que tanto los hilos del núcleo como los hilos en modo usuario pueden ejecutarse en cualquier procesador. Mach proporciona un modelo multihilo para procesos de usuario, con entornos de ejecución llamados tareas.

• Extensión transparente para operar en red: Para permitir que los programas distribuidos se extiendan de forma transparente sobre mono y multiprocesadores en una red, Mach ha adoptado un modelo de comunicación independiente de la ubicación usando puertos como destino de la comunicación. El diseño de Mach confía en procesos servidores de red de nivel de usuario para el envío de mensajes de forma transparente sobre la red.

• Servidores de nivel de usuario: Mach implementa un modelo basado en objetos en el que los recursos se gestionan o bien por el núcleo, o bien mediante servidores cargados dinámicamente. Inicialmente solo se permitían servidores de nivel de usuario, pero posteriormente se adaptó Mach para acomodar servidores en el espacio de direcciones del núcleo. Con la excepción de algunos recursos gestionados por el núcleo, los recursos son accedidos de forma uniforme mediante paso de mensajes, independientemente de cómo sean gestionados.

• Emulación de sistema operativo: Para dar soporte a la emulación de nivel de usuario de UNIX y otros sistemas operativos, Mach permite la redirección transparente de las llamadas al sistema operativo sobre llamadas a una biblioteca de emulación y de ahí hacia los servidores del sistema operativo del nivel de usuario; a esta técnica se la conoce como trampolining.

• Implementación de memoria virtual flexible: Para dotar a Mach de la posibilidad de emular sistemas UNIX y dar soporte a otros subsistemas se realizó una aproximación flexible a la distribución del espacio de direcciones de un proceso. Mach soporta un espacio de direcciones grande y disperso, con capacidad potencial para contener múltiples regiones. Por ejemplo, tanto los mensajes como los archivos abiertos pueden aparecer como regiones de memoria virtual.

• Portabilidad: Mach fue diseñado para ser portable sobre varias plataformas hardware. Por esta razón, se trató de aislar, tanto como fue posible, el código dependiente de la máquina.
Principios de diseño
El sistema operativo Mach se diseñó para proporcionar algunos mecanismos básicos de los que carece la mayoría de los sistemas operativos actuales. El objetivo fue diseñar un sistema operativo compatible con BSD y además, sobresaliente en las áreas siguientes:
  • Apoyar arquitecturas diversas, incluyendo multiprocesadores UMA, NUMA Y NORMA (No Remote Memory Access, sin acceso a memoria remota).
  • Capacidad para funcionar con velocidades cambiantes en redes entre computadores, desde redes extendidas hasta redes locales de alta velocidad y multiprocesadores fuertemente acoplados.
  • Estructura simplificada del núcleo, con pocas abstracciones; se supone que las abstracciones son suficientemente generales para que puedan usarse en la implantación de otros sistemas operativos sobre Mach.
  • Operación distribuida para proporcionar a los clientes transparencia de la red, y una organización orientada a objetos, tanto interna como externamente.
  • Administración de memoria y comunicación entre procesos integradas para proporcionar un mecanismo de memoria y comunicación directo y eficiente con una sola construcción.
  • Apoyo a sistemas heterogéneos para que Mach sea ampliamente disponible y operante en sistemas de computación de fabricantes distintos.

2.19.2._Estructura_de_MACH_Release_3.0.JPG

Estructura de Mach Release 3.
Los diseñadores de Mach han tenido una gran influencia de BSD (y UNIX, en general), y los beneficios han sido:
  • Una sencilla interfaz con el programador, con un buen conjunto de primitivas o servicios básicos, y un conjunto consistente de interfaces con los recursos del sistema.
  • Fácil transportabilidad a una amplia gama de uniprocesadores.
  • Una extensa biblioteca de utilerías y aplicaciones.
  • La capacidad para combinar utilerías usando canales.
Por supuesto, se consideró que BSD presentaba varias desventajas que había que mejorar:
  • Un núcleo que se había convertido en depósito de muchas características que con frecuencia eran redundantes y, por tanto, difíciles de administrar y modificar.
  • Objetivos de diseño originales que hacían difícil proporcionar apoyo a multiprocesadores, sistemas distribuidos y bibliotecas de programa compartidas; por ejemplo, puesto que el núcleo estaba diseñado para uniprocesadores, no ofrecía capacidades para aplicar cerraduras a código o datos que podrían emplear otros procesadores.
  • Demasiadas abstracciones fundamentales que ofrecían una gran cantidad de medios similares y conflictivos para lograr la misma tarea.
Debe destacarse que el desarrollo de Mach continúa siendo una tarea de grandes proporciones; no obstante, los beneficios que se pueden obtener de un sistema de este tipo también son considerables. El sistema operativo se ejecuta en muchas arquitecturas de uno o varios multiprocesadores actuales, y debe ser fácil el transporte a los que aparezcan en el futuro. Permite que los especialistas en computación realicen experimentos en varias áreas, sin tener que desarrollar sus propios sistemas operativos a la medida.
Estas áreas incluyen sistemas operativos, bases de datos, sistemas distribuidos confiables, lenguajes multiprocesador, seguridad e inteligencia artificial distribuida. En su presentación actual, Mach es por lo menos tan eficiente como las principales versiones de UNIX al efectuar tareas similares, y muchas veces es más rápido, una ventaja adicional que no habían contemplado los diseñadores.
Componentes del sistema
Para que Mach logre los objetivos establecidos, la funcionalidad del sistema operativo debe reducirse a un pequeño conjunto de abstracciones básicas. (Éste fue también uno de los objetivos originales de ub", pero desde entonces ha arnpliado su funcionalidad.) A partir de estas abstracciones, debe derivarse cualquier otra funcionalidad; de lo contrario, el núcleo estará incompleto. Recuerde que un núcleo debe ofrecer un medio para que los usuarios realicen su trabajo. Esto generalmente se transforma en el requisito de que deben ofrecerse los servicios básicos: ejecución de programas, operaciones de E/s, manipulación del sistema de archivos, asignación de recursos y protección. Por supuesto, cada sistema operativo tiene su propio enfoque para lograr esta funcionalidad; en Mach, es colocar lo menos posible dentro del núcleo, pero hacer que lo que ahí está sea lo suficientemente poderoso como para poder derivar todas las demás características.
La filosofía de diseño de Mach es contar con un núcleo sencillo y extensible, centrado en los recursos de comunicación. Por ejemplo, todas las solicitudes para el núcleo, y todo el movimiento de datos entre procesos, se manejan a través del mismo mecanismo de comunicación. Al limitar las operaciones de datos a un mecanismo, Mach puede ofrecer protección para sus usuarios protegiendo el mecanismo de comunicación. Es extensible, va que muchas de las funciones que tradicionalmente se basaban en el núcleo pueden implantarse como servidores a nivel de usuario. Por ejemplo, aunque se cuenta con un paginador, es posible implantar externamente otros paginadores que llama el núcleo cuando el usuario lo indica.
Para facilitar el diseño y la modificación, Mach está basado en un paradigma orientado a objetos. Los sistemas tradicionales tienen datos y operaciones que manipulan estos datos. Los sistemas orientados a objetos unen estos dos componentes en un solo objeto abstracto, donde las operaciones del objeto sólo pueden actuar sobre las entidades que en él se definen. Los detalles de cómo se implantan estas operaciones están ocultos, lo mismo que las estructuras de datos. De esta manera, sólo podemos usar un objeto invocando sus operaciones definidas, exportadas. Podemos cambiar las operaciones internas sin modificar la definición de la interfaz, lo que libera al programador para que lleve a cabo el perfeccionamiento requerido sin afectar otros aspectos operativos del sistema. El enfoque orientado a objetos que apoya Mach permite que los objetos residan en cualquier lugar de una red de sistemas Mach en forma transparente para el usuario. Analizaremos estas técnicas cuando veamos el mecanismo de puertos.
Las abstracciones primitivas que apoya Mach son las siguientes:
  • Tarea: Se trata de un entorno de ejecución. Es la unidad básica de asignación de recursos y cuenta con espacio virtual de direcciones y acceso protegido a los recursos del sistema. Por lo general, una tarea está asociada a procesadores, puertos y memoria virtual.
  • Hilo: Es la unidad básica de ejecución, así como el objeto de trabajo más pequeño, y se ejecuta en el contexto de una tarea. Comparte los recursos de la tarea con otros hilos de la misma tarea. En Mach no existe el concepto de "proceso"; más bien se implantaría un proceso tradicional como una tarea con un solo hilo de control.
  • Puerto: Es el mecanismo básico de referencia a objetos en Mach. Toda la comunicación se lleva a cabo a través de puertos, canales de comunicación unidireccionales administrados y protegidos por el núcleo.
Funcionalmente, son colas de mensajes. Invocamos una operación sobre un objeto enviando un mensaje al puerto asociado a ese objeto; el objeto representado por un puerto recibe los mensajes. Tanto el emisor como el receptor deben tener derechos de puerto para tener acceso al puerto. Por ejemplo, un emisor debe tener capacidad para enviar un mensaje a un puerto, de la misma manera que un receptor requiere capacidad de recepción para extraer mensajes de la cola.
  • Conjunto de puertos: Se trata de un grupo de puertos que comparten una misma cola de mensajes. Un hilo puede recibir mensajes para un conjunto de puertos, y así atender a varios. Este hilo usaría la identidad del puerto destino para identificar la función que se solicita.
  • Mensaje: Es el método básico de comunicación entre hilos en Mach. Es una colección tipificada de objetos de datos, y puede contener los datos en sí, apuntadores a los datos o capacidades de puerto (para transferir los derechos de acceso a puertos a otro hilo).
  • Objeto de memoria: Es un elemento en almacenamiento secundario para el cual existe una correspondencia con el espacio de direcciones de una tarea. Un ejemplo es un archivo administrado por un servidor, pero un objeto de memoria puede ser cualquier objeto para el cual puedan manejarse solicitudes de lectura y escritura, como lo es un canal en UNIX.
Una característica poco usual de Mach, y una clave para su eficiencia, es su combinación de características de memoria y comunicación entre procesos. Mientras que otros sistemas distribuidos (como SunOS, con sus características NFS) cuentan con extensiones de propósito especial para que el sistema de archivos abarque toda una red, Mach ofrece una combinación extensible y de propósito general de la memoria y los mensajes en el corazón del núcleo. Esta característica no sólo permite usar Mach para la programación distribuida y en paralelo, sino también ayuda en la implantación del núcleo.
Pero, ¿cómo se relacionan la administración de memoria y la comunicación entre procesos (ipc)? La administración de memoria se lleva a cabo usando objetos de memoria. Un objeto de memoria está representado por un puerto (o varios), y los mensajes de comunicación entre procesos se envían al puerto para solicitar operaciones sobre el objeto. Puesto que se usa la ipc, los objetos de memoria pueden residir en sistemas remotos y lograr el acceso a ellos de manera transparente. A la inversa, las técnicas de administración de memoria se emplean para implantar la transmisión de mensajes. Ya hemos visto que los mensajes tienden a ocasionar un excesivo procesamiento adicional, y por lo general, son menos eficientes que, por ejemplo, la memoria compartida. Como Mach es un núcleo basado en mensajes, es importante que el manejo de mensajes se lleve a cabo con eficiencia.
Gran parte de la ineficiencia de los mensajes se debe a la copia de mensajes de un proceso a otro (si la transmisión se efectúa en un mismo computador) o la baja velocidad de procesamiento de la red (en el caso de mensajes entre computadores). En los sistemas UNIX surgen otras deficiencias de la analogía de sistemas de archivos sobre la que se basa la transmisión de mensajes en UNIX.
Para resolver estos problemas, Mach usa una nueva correspondencia de memoria virtual para la transferencia de mensajes de gran tamaño. Es decir, para transferir un mensaje entre dos tareas, Mach cambia el mapa de memoria de la tarea receptora para que incluya el área de memoria que contiene el mensaje en el espacio de direcciones del proceso emisor. Esta técnica evita copiar los datos .En el caso de mensajes entre anfitriones, se deben transferir los datos por la red; no obstante, los datos sólo se copian cuando se hace referencia a ellos. A esta técnica se le conoce como copia por referencia (o evaluación perezosa). Ya que los mensajes pueden ser tan grandes como el espacio de direcciones virtuales, este perfeccionamiento puede evitar la copia de miles de millones de bytes de datos en un mensaje. Aunque este Perfeccionamiento no se emplea actualmente en Mach, deberá estar disponible en próximas versiones.
Existen varias ventajas del enfoque de Mach:
  • Mach ofrece a los programas de usuario mayor flexibilidad en la administración de memoria.
  • El modelo es muy general, lo que permite su uso en computadores fuerte y débilmente acoplados.
  • Se emplean puertos para hacer referencias a objetos, lo que añade un nivel de abstracción que puede usarse para implantar la migración de tareas.
2.19.3. PLATAFORMAS SOBRE LAS QUE TRABAJA

Algunas plataformas en las que se usa MACH
· Mac OS X Server - Sistema operativo servidor basado en Mach 2.5 y BSD 4.4
Tras un largo período de espera ya está disponible en nuestro país uno de los sistemas operativos más esperados por los usuarios de Mac. ¿Por qué? Este sistema servidor supone un avance de lo que aportará el próximo cliente Mac OS X. Es el primer sistema operativo de Apple que aúna todas las características que los usuarios han estado demandando durante años: protección de memoria, multitarea preemptiva y compatibilidad con aplicaciones actuales; si bien se reserva al cliente Mac OS X la capacidad de ejecutar las aplicaciones “carbonizadas” que, en definitiva, ofrecerán un mejor rendimiento en aquellas máquinas utilizadas para su ejecución (todos los Power Macintosh de última generación).
Si bien el futuro sistema operativo de Apple comparte muchos elementos de este Mac OS X Server, en este Banco de pruebas nos centraremos exclusivamente en comentar las posibilidades de la versión de servidor. Como anticipo, el Mac OS X Server permitirá a los usuarios crear servicios Web, de vídeo (streaming de QuickTime) o, simplemente, ser utilizado como servidor de archivos; sin olvidarnos de una característica ligada a todos los iMac y actuales Power Mac G3: NetBoot, mediante la cual estos modelos pueden tener un comportamiento totalmente de terminal, demandando al servidor Mac OS X las aplicaciones que se deseen ejecutar, configuración de arranque y otros aspectos que trataremos posteriormente.
Rendimiento de Mac OS X como servidor.

¿Cómo se hicieron las pruebas?

Para medir el rendimiento del servicio Web en el servidor se utilizaron las operaciones de WebBench 3.0 (www.webbench.com). Los servidores fueron un Apple Power Macintosh G3/400 con Mac OS X Server y WebTen 2.11 de Tenon Intersystems; un Compaq 1850R multiprocesador a 500 MHz ejecutando Windows NT Server 4.0 Internet Information Server (IIS); y un Sun E250 ejecutando Solaris 2.6. Los 56 clientes (una mezcla de Pentimun II a 233 MHz, Pentium Pro a 200 MHz, y Pentium a 166 MHz ejecutando Windows 95) se conectaron a dos conmutadores de red Extreme divididos en cuatro segmentos. —Pruebas Macworld Lab supervisadas por Kevin Mitchell—
· En 1986 se presentó la primera versión de Mach para la familia de computadores DEC VAX, incluyendo las versiones multiprocesadores de VAX; POCO después aparecieron versiones para el IBM RT Pc y las estaciones de trabajo SUN.
· En 1987 surgieron las versiones Encore Multimax y Sequent, con apoyo total para multiprocesamiento, y las primeras versiones oficiales, Release 0 y Release 1. Hasta ese momento, todas las máquinas que ejecutaban Mach tenían un diseño de acceso uniforme a memoria (Uma, Uniform Memory Access); es decir, apoyaban los sistemas multiprocesadores con procesadores que tenían acceso uniforme a la memoria del sistema.
· La versión Release 2 fue más allá, y Mach se transportó a sistemas con acceso no uniforme a memoria (Numa, Non-Uniform Memory Access), donde los procesadores comparten la memoria, pero cada uno tiene acceso limitado, o no tiene acceso, a parte de la memoria en el sistema. Release 2 también comenzó la tarea de "nuclearizar" UNIX, aunque el esfuerzo no sería evidente hasta la Release 3, en 1990. La Release'2 ofrece compatibilidad con 4.3BSD incluyendo la mayor parte de éste en el núcleo; los niveles inferiores de BSD se sustituyen por los conceptos e implantaciones de Mach. Así, la Release 2.5 es en realidad más grande que el núcleo de BSD. A partir de Release 2.5, Mach está disponible en una amplia gama de máquinas, incluyendo algunas SUN, Intel, IBM y DEC de un solo procesador, y sistemas multiprocesadores DEC, Sequent y Encore.
· Introducción a GNU Mach
GNU Mach es el micronúcleo del sistema GNU. Un micronúcleo proporciona solamente una funcionalidad limitada: el mínimo nivel de abstracción que se precisa por encima del hardware para ejecutar el resto del sistema operativo en el espacio de usuario. Los servidores de GNU Hurd y la biblioteca de C de GNU implementan en los sistemas GNU la compatibilidad con POSIX sobre la arquitectura proporcionada por el micronúcleo Mach.
En la actualidad, GNU Mach se ejecuta en maquinas IA32. GNU Mach debería migrarse, y probablemente así se hará, a otras arquitecturas de hardware en el futuro. Mach ya se migró a otros sistemas operativos anteriormente.
Los desarrolladores del Hurd mantienen GNU Mach para el proyecto GNU.
2.19.4. INSTALACION
Microkernel
Un núcleo con 'arquitectura' micronúcleo es aquél que contiene únicamente el manejo de procesos y threads, el de manejo bajo de memoria, da soporte a las comunicaciones y maneja las interrupciones y operaciones de bajo nivel de entrada-salida. [Tan92]. En los sistemas operativos que cuentan con este tipo de núcleo se usan procesos 'servidores' que se encargan de ofrecer el resto de servicios (por ejemplo el de sistema de archivos) y que utilizan al núcleo a través del soporte de comunicaciones.
Este diseño permite que los servidores no estén atados a un fabricante en especial, incluso el usuario puede escoger o programar sus propios servidores. La mayoría de los sistemas operativos que usan este esquema manejan los recursos de la computadora como si fueran objetos: los servidores ofrecen una serie de 'llamadas' o 'métodos' utilizables con un comportamiento coherente y estructurado. Otra de las características importantes de los micronúcleos es el manejo de threads. Cuando un proceso está formado de un solo thread, éste es un proceso normal como en cualquier sistema operativo.
Los usos más comunes de los micronúcleos es en los sistemas operativos que intentan ser distribuidos, y en aquellos que sirven como base para instalar sobre ellos otros sistemas operativos. Por ejemplo, el sistema operativo AMOEBA intenta ser distribuido y el sistema operativo MACH sirve como base para instalar sobre él DOS, UNIX, etc.

Familia Mach.
• GNU / Hurd
• BSD lites
• Mac OS X
• NEXTSTEP
• YAMIT
• MKlinux
Detalles de implantación
En Mach se utilizan varias técnicas innovadoras para apoyar las llamadas al sistema disponibles para los servidores y programas de aplicación. En esta sección analizaremos los métodos más interesantes que se emplean internamente en Mach.
Ahora contamos con información suficiente respecto a los diversos aspectos de Mach para comprender cómo puede apoyar una de las operaciones clave de UNIX: la llamada al sistema fork (bifurcar). Un proceso utiliza esta llamada para crear otro nuevo que cuenta con un duplicado de la memoria de su padre. El hijo puede entonces continuar su ejecución (quizá modificando la memoria) o usar la llamada execve para reemplazar su memoria con un nuevo contenido de proceso. En Mach, fork crea una nueva tarea con un hilo; esta tarea tiene una copia a la escritura del espacio de direcciones del padre, y se asignan valores iníciales al hilo para que comience la ejecución en la instrucción que sigue a la llamada fork, lo mismo que en UNIX BSD. Por supuesto, fork es más eficiente que en UNIX estándar, ya que la memoria del padre en realidad no se copia.
Lo único que se requiere es una sencilla duplicación del mapa de direcciones del padre, con las páginas de datos fijadas para copia a la escritura (y un duplicado de la pila).
Mach está implantado usando técnicas de programación orientadas a objetos. La mayoría de las estructuras de datos se implantan como objetos, con una sección de datos y un conjunto de rutinas que leen o modifican los datos. Puesto que Mach se diseñó para ser fácilmente transportable, no se escribió en un lenguaje orientado a objetos, como C++, que quizá no se encuentre en todos los sistemas. En vez de esto, todo el núcleo se escribió en lenguaje C. Esta característica orientada a objetos se amplía en la versión 3.0 de Mach, donde se utiliza una herramienta que se encuentra en UNIX estándar, el preprocesador cpp de lenguaje C, en el servidor de emulación de BSD para permitir que los implantadores utilicen técnicas orientadas a objetos. Aunque no cuenta con las características más avanzadas que se encuentran en los lenguajes de programación orientados a objetos, tiene el poder suficiente para poyar los recursos básicos.
Cada vez que se crea un objeto interno, se le asigna un recuento de referencia para controlar el número de veces que se hace referencia a él. A este recuento se le asigna un valor inicial 1, el cual se incremento cada vez que otro objeto o rutina lo utiliza, y se reduce cuando dejan de usarlo. Cuando el recuento llega a cero, Mach puede eliminar ese objeto sin problemas. El empleo de recuentos de referencia permite crear y destruir objetos dinámicamente asignación más estáticas empleadas en, lo que evita las técnicas de otras implantaciones de sistemas operativos.
Por ejemplo, UNIX BSD Cuenta con varios arreglos, incluyendo algunos para almacenar información de proceso y los buffers de red que se definen durante la compilación y permanecen fijos durante la ejecución. Si se agotan los procesos de un sistema, hay que volver a compilar el núcleo, detener el sistema y volver a iniciarlo. El mecanismo dinámico de Mach permite que el número de recursos importantes crezca y se reduzca según sea necesario. Sin embargo, actualmente Mach no cuenta con un mecanismo para recuperarse si se llena todo su espacio de memoria.
Mach aplica cerraduras a todos los objetos durante la escritura. Compare esto con las construcciones normales de los sistemas operativos, donde las secciones de código que modifican datos (secciones críticas) se protegen entre sí de una ejecución concurrente múltiple. Las secciones críticas no son los métodos de control apropiados en los sistemas operativos multiprocesadores. Considere, por ejemplo, las rutinas que cambian los mapas de memoria virtual. Éstas son comunes en Mach, y en los sistema multiprocesadores podrían invocarse al mismo tiempo en varios procesadores. Con las secciones críticas, el código aseguraría que sólo un procesador ejecute el código a la vez; no obstante, esto provocaría que los demás procesadores tengan que esperar mientras un procesador individual ejecuta en su sección crítica. Con el modelo de cerraduras para datos que emplea Mach, las rutinas de cada objeto de datos aplican una cerradura cuando lo modifican. Es mucho menos probable que un objeto de datos (por ejemplo, el mapa de direcciones virtuales del proceso n) tenga que ser modificado por varios procesadores, que se ejecute concurrentemente el código del mapa de direcciones virtuales.
Por consiguiente, Mach utiliza cerraduras de exclusión mutua para las estructuras de datos. Al aplicar cerraduras sobre objetos individuales, se permite que continúen los demás cálculos, incluyendo modificaciones a otros ejemplos de los datos. Esto permite mayor concurrencia en el sistema operativo y, por tanto, mayor eficiencia. Puesto que los objetos aplican automáticamente las cerraduras, el código del núcleo está libre de que las rutinas de cerradura lo saturen, lo que hace más sencillo el código y reduce la posibilidad de corrupción de datos debida a una sección de código que no se protege de manera adecuada.
Todo hilo que se ejecuta en modo del núcleo no es desplazable. Esto incluye a los hilos que se ejecutan permanentemente en modo de núcleo, o incluso los que lo hacen de manera temporal (por ejemplo, una aplicación de usuario que emite una llamada al sistema). A primera vista, parecería que estos hilos del núcleo podrían interrumpirse, de la misma manera que los hilos de usuario, ya que todos los objetos cuentan con una cerradura durante la modificación. No obstante, recuerde que la emulación de 4.3BSD se lleva a cabo a través de la inclusión de la mayor parte de BSD COMO tarea a nivel del núcleo. Puesto que BSD es complicado, su mecanismo nativo de cerradura no se modificó para las secciones críticas, por lo que no usa el método de cerraduras para datos. Por esto, Mach no puede permitir que se interrumpan los hilos que pueden estar ejecutando código del núcleo BSD. Las cerraduras no son suficientes para asegurar que las estructuras de datos no serán corrompidas si se presenta una planificación de hilos normal de Mach.
En cambio, Mach permite que cada hilo del núcleo se ejecute hasta que declare que no se encuentra en una sección crítica y, por tanto, puede ser desplazado. Entonces, el planificador puede permitir que el hilo continúe su ejecución (y que, posiblemente, se declare como no desplazable) si no hay nada esperando al procesador, o puede colocar al hilo en la cola de esperas y ejecutar otro. Por supuesto, los hilos del núcleo cooperan, por lo que no hay posibilidad de que se presente un bloqueo indefinido. Un hilo permite su desplazamiento sólo cuando se encuentra en un estado seguro: uno donde no tiene acceso a objetos de inicio del núcleo; así, no se requieren cerraduras. Como ya se mencionó, se está reescribiendo la emulación de 4.3BSD para permitir que una parte se ejecute corno biblioteca a nivel de usuario y otra como llamadas al sistema a nivel del núcleo. El servidor y la biblioteca utilizarán las cerraduras normales de Mach y serán rnultihilos.
Para muchos objetos de Mach se emplean puertos de nombre. Nunca reciben mensajes, pero se utilizan corno puntos de referencia de los hilos que poseen derechos de envío para ellos. Por ejemplo, puesto que podemos comparar puertos en una tarea, dos hilos que poseen derechos de envío para un puerto de nombre pueden comparar esos puertos para determinar si se refieren a puertos de nombre generalmente se emplean refieren al mismo objeto. Los puertos cuando un objeto no desea otorgar un derecho a una tarea, pero sí quiere que un hilo de esa tarea tenga la capacidad para referirse a él (digamos, en una llamada al sistema).
Por ejemplo, el núcleo proporciona un puerto de nombre para un objeto de memoria, de manera que las tareas pueden ejecutar una llamada vm-region para el objeto y así conocer la fuente de los datos en una región determinada.
Referencia guía de instalación MACH especificado por maquina en:
http://translate.google.com.co/translate?hl=es&sl=en&u=http://www.cs.cmu.edu/afs/cs.cmu.edu/project/mach/public/www/mach.html&sa=X&oi=translate&resnum=10&ct=result&prev=/search%3Fq%3DMACH%26hl%3Des%26sa%3DG


2.19.5. GESTION DE PROCESOS Y DEL PROCESADOR

ADMINISTRACIÓN DE LOS PROCESOS:

Administración de procesos
Una tarea puede considerarse como un proceso tradicional que no tiene un apuntador de instrucciones o un conjunto de registros Una tarea contiene un espacio de direcciones virtuales, un conjunto de derecho de puertos e información contable. Es posible crear o destruir una tarea, igual que en UNIX. Una tarea no hace nada si en ella no se ejecutan uno o más hilos.
  • Estructura básica
Una tarea que contiene un hilo es semejante a un proceso UNIX. De la misma manera que una llamada al sistema fork produce un nuevo proceso en UNIX, Mach crea una nueva tarea para emular este comportamiento. La memoria de la nueva tarea es un duplicado del espacio de direcciones del padre.
La nueva tarea contiene un hilo que inicia en el mismo punto que la llamada de bifurcación en el padre. Es posible suspender o reanudar hilos o tareas.
Los hilos son especialmente útiles en las aplicaciones servidoras, comunes en UNIX. También permiten un empleo eficiente de los recursos de computación en paralelo: en vez que se requiera un proceso en cada procesador (con el impacto correspondiente sobre rendimiento y el tiempo adicional de procesamiento del sistema operativo), una tarea puede distribuir sus hilos entre procesadores en paralelo. Los Hilos también añaden eficiencia a los programas a nivel de usuario; por ejemplo, en UNIX, todo el proceso tiene que esperara cuando ocurre una falla de página o ejecutar una llamada al sistema. En una tarea con varios hilos, solo se demora el hilo que causo la falla de pagina o ejecuto. Por supuesto, hay un costo asociado a los hilos, ya que deben contar con el apoyo de estructuras de datos en el núcleo y además deben existir algoritmos más complejos para la planificación del núcleo.
Así como los procesos cuentan con estados, también los hilos. Un hilo puede encontrarse en uno de los estados siguientes:
Ejecución. El hilo está en ejecución o en una cola, listo para ejecución, esperando que se le asigne un procesador. Se considera que un hilo está en ejecución incluso si está bloqueado dentro del núcleo (por ejemplo, en espera que se resuelva una falla de página).
Suspendido. El hilo no se está ejecutando en un procesador ni se encuentra en una cola de espera para ejecución; no continuará su ejecución hasta que regrese al estado de ejecución.
Puede considerarse que una tarea está en uno de estos estados. Una operación que se aplica sobre una tarea afecta a todos sus hilos, por lo que la suspensión de una tarea implica la suspensión de todos sus hilos. Sin embargo, la suspensión de tareas e hilos son mecanismos independientes, por lo que se puede reanudar un hilo de una tarea suspendida sin reanudar la tarea.
Mach proporciona primitivas a partir de las cuales se pueden construir herramientas de sincronización. Esto va de acuerdo con la filosofía de Mach de proporcionar una funcionalidad mínima, aunque suficiente, en el núcleo. Para la sincronización puede usarse el recurso ipc de Mach, con procesos que intercambian mensajes en puntos de encuentro.
La sincronización a nivel de hilos utiliza las primitivas reanudar hilo y suspender-hilo para iniciar y detener los hilos cuando sea apropiado. Para cada hilo se conserva un recuento de suspensiones que permite aplicar varias suspensiones a un hilo; sólo cuando ocurra igual número de llamadas de reanudación se reactivará el hilo.
Por desgracia, esta característica presenta su propia limitante: cómo es posible un error si se ejecuta reanudar-hilo antes de suspender-hilo (por que el número de suspensión sería negativo), no pueden usarse estas rutinas para sincronizar el acceso a datos compartidos.
  • El paquete de hilos C
Un aspecto común de Mach es que proporciona rutinas de bajo nivel, aunque flexibles, en vez de funciones más grandes y elaboradas, pero más restrictivas. En vez de obligar a los programadores a trabajar en este bajo nivel, Mach ofrece interfaces de mayor nivel para la programación en C y otros lenguajes. Por ejemplo, el paquete de hilos C proporciona al programador varios hilos de control, variables compartidas, exclusión mutua para la sección crítica y variables de condición para la sincronización. Las rutinas de control de hilos 'incluyen las siguientes:
La rutina cthread-fork crea un nuevo hilo en una tarea; recibe como entrada una función que debe ejecutar y un parámetro (o apuntador a parámetros), Luego, el hilo ejecuta concurrentemente con el hilo creador, el cual recibe un identificador de hilo al devolver la llamada.
  • La rutina cthread-exit destruye el hilo que la llama y, si no está separada, envía un valor al hilo creador.
  • La rutina cthread-join espera a que termine un hilo y luego continúa (de manera similar a las llamadas wait de UNIX).
  • La rutina cthread-detach indica que nunca se aplicará a un hilo la rutina cthread-join.
  • La rutina cthread-yield indica al planificador que en ese momento puede ejecutarse otro hilo. Esta rutina también es útil si existe un planificador desplazante, ya que puede usarse para liberar voluntariamente la ucp antes de que expire el cuanto de tiempo, si el hilo ya no la necesita.
La exclusión mutua se logra con el uso de cerraduras giratorias. Las rutinas asociadas con la exclusión mutua son las siguientes:
  • La rutina mutex-qlloc crea dinámicamente una variable mutex.
  • La rutina mutex-free libera una variable mutex creada dinámicamente.
  • La rutina mutex lock aplica una cerradura a una variable mutex. El hilo en ejecución entra en cerraduras giratorias hasta que se logra la cerradura. Se presenta un bloqueo mutuo si un hilo con cerradura trata de aplicar una cerradura a la misma variable mutex; el paquete de hilos C no garantiza la espera limitada, sino depende de las instrucciones de hardware que se usan para implantar las rutinas mutex.
  • La rutina mutex unlock quita la cerradura a una variable mutex, en forma muy parecida a la operación señal típica de un semáforo.
La sincronización general puede lograrse usando variables de condición, para así implantar una región crítica condicional o un monitor, como se vio en el capítulo 5. Una variable de condición está relacionada con una variable mutex y refleja un estado booleano para dicha variable. Las rutinas asociadas con la sincronización general son las siguientes:
  • La rutina condition -alloc asigna dinámicamente una variable de condición. Esta rutina se expande a una macroinstrucción para ejecutar una versión de la función malloc de UNIX, modificada para apoyar hilos múltiples.
  • La rutina condition-free elimina una variable de condición creada dinámicamente, asignada como resultado de la rutina condition-alloc. Esta rutina se expande a una macroinstrucción para ejecutar una versión de la función free de UNIX, modificada para apoyar hilos múltiples.
  • La rutina condition-wait quita la cerradura de la variable mutex asociada y bloquea el hilo hasta que se ejecute condition-signal para la variable de condición, indicando que puede haber ocurrido el suceso que se espera. Luego se aplica una cerradura a la variable mutex y prosigue el hilo. Una rutina condition-signal no garantiza que la condición persista cuando el hilo desbloqueado finalmente regresa de su llamada de espera, por lo que hilo que despierta debe entrar en un ciclo, ejecutando la rutina condition-wait hasta que se quita el bloqueo y persiste la condición.
Utilizamos una variable mutex para proteger el buffer mientras se actualiza. Una vez que logramos el acceso exclusivo al buffer, empleamos variables de condición para bloquear el hilo productor si el buffer está lleno y para bloquear al consumidor si está vacío. Aunque este programa normalmente se escribiría en el lenguaje C en un sistema Mach, por cuestiones de claridad usaremos la sintaxis tipo Pascal. Suponemos que el buffer consta de n ranuras, cada una capaz de contener un elemento.
El semáforo mutex proporciona la exclusión mutua para los accesos al depósito de buffers y tiene un valor inicial.
Los semáforos vacío y lleno cuentan el número de buffers vacíos y llenos, respectivamente; el semáforo vacío tiene un valor inicial n, y el semáforo lleno, 0. La variable de condición no - vacío es verdadera mientras el buffer tenga elementos, y no lleno es verdadera si el buffer tiene una ranura vacía.
El primer paso incluye la asignación de las variables mutex y de condición:
mutex-alloc(mutex);
condition alloc(no vacío, no_lleno);
Al terminar el programa, hay que liberar las variables mutex y de condición:
mutex-free(mutex);
condition-free(no-vacío, no-lleno);
  • El planificador de la ucp
El planificador de la ucp para un sistema operativo multiprocesador basado en hilos es más complejo que sus parientes basados en procesos. Por lo general se encuentran más hilos en un sistema multihilos que procesos en un sistema de múltiples tareas.
repeat
Producir un elemento para p siguiente
mutéx lock(mutex);
while(lleno)
condition_wait(no_lleno, mutex);
añadir p siguiente al buffer
condition_signal(no-vacío);
mutex_unlock (mutex);
Untilfalso;
Así mismo, es difícil controlar varios procesadores y se trata de una área de investigación bastante reciente. Mach utiliza una política sencilla para que el planificador sea manejable. Sólo se planifican los hilos, por lo que el planificador no requiere conocimiento de las tareas. Todos los hilos compiten de igual manera por los recursos, incluyendo los cuantos de tiempo.
A cada hilo se le asocia una prioridad de 0 a 127, basada en el promedio exponencial de su utilización de la ucp. En otras palabras, un hilo que ha usado recientemente la ucp durante largo tiempo, tiene la menor prioridad.
repeat
mutex-lock(mutex);
while(vacío)
Condition-wait (no-vacío, mutex);
Quitar un elemento del buffer para csiguiente
Condition-signal(no-lleno);
mutex-unlock(mutex);
consumir el elemento en csiguiente
untilfalso;
Mach emplea la prioridad para colocar el hilo en una de las 32 colas de ejecución globales, las cuales se rastrean en orden prioritario para localizar los hilos en espera cuando un procesador está inactivo. Mach también cuenta con colas de ejecución para cada procesadora, o locales, que debe administrar junto con las colas globales. Una cola de ejecución local se usa para aquellos hilos enlazados a un procesador específico; por ejemplo, el manejador de un dispositivo conectado a una ucp sólo debe ejecutarse en esa ucp.
En vez de que haya un despachador central que asigne los hilos a los procesadores, cada procesador consulta las colas de ejecución locales y globales para seleccionar el hilo adecuado para la ejecución. Los hilos en la cola de ejecución local tienen prioridad absoluta sobre aquellas en las colas globales, ya que se supone que están realizando alguna tarea para el núcleo. Las colas de ejecución (como casi todos los demás objetos de Mach) están sujetas a una cerradura mientras se modifican, para evitar cambios simultáneos efectuados por varios procesadores. Para acelerar el despacho de hilos en la cola de ejecución global, Mach mantiene una lista de procesadores inactivos.
Por la naturaleza multiprocesador de Mach, surgen otros problemas de planificación. Por ejemplo, no resulta apropiado un cuanto de tiempo fijo porque puede haber menos hilos listos para ejecución que procesadores disponibles, y sería un desperdicio interrumpir un hilo con un cambio de contexto al núcleo al terminar su cuanto de tiempo, sólo para que se coloque de inmediato otra vez en estado de ejecución. En vez de usar un cuanto de longitud fija, Mach varía el tamaño del cuanto inversamente con el total de hilos en el sistema; sin embargo, el cuanto de tiempo permanece constante para todo el sistema. Por ejemplo, en un sistema con 10 procesadores, 11 hilos y un cuanto de 10 milisegundos, sólo tiene que ocurrir un cambio de contexto cada segundo para cada procesador a fin de mantener el cuanto deseado.
Por supuesto, aún existen muchas más complicaciones que se deben tomar en cuenta. Incluso, es más difícil liberar la ucp al esperar un recurso que en los sistemas operativos tradicionales. En primer lugar, un hilo tiene que emitir una llamada assert-wait para avisar al núcleo que el hilo está a punto de bloquearse; esto evita los bloqueos mutuos y las condiciones de competencia, que pueden ocurrir durante la ejecución en un entorno multiprocesador.
La llamada al sistema thread-block hace que el hilo salga de la cola de ejecución hasta que ocurra el suceso indicado. Existen varios otros estados internos de los hilos que utiliza el planificador para controlar la ejecución de hilos.
  • Manejo de excepciones
Mach implanta el paquete de señales estándar de UNIX (analizado en la sección 15.3.3). Recuerde que las señales proporcionan excepciones e interrupciones generadas por software. Las interrupciones son alteraciones de un hilo o tarea generadas externamente, mientras que las excepciones son causadas por la ocurrencia de condiciones poco usuales durante la ejecución de un hilo. Por desgracia, las señales tienen una funcionalidad limitada en los sistemas operativos rnultihilos. El primer problema es que, en UNIX, el manejador de una señal debe ser una rutina en el proceso que recibe la señal.
Si la señal es causada por un problema en el proceso (por ejemplo, una división entre cero), no puede remediarse el problema, pues el proceso sólo tiene acceso limitado a su propio contexto. Un segundo aspecto de las señales, aún más complicado, es que se diseñaron para aplicaciones de un solo hilo, lo que representa una seria limitante para ser utilizadas en Mach. Puesto que en Mach el sistema de señales debe operar correctamente con aplicaciones multihilos, para la ejecución de programas 4.3BSD, no es posible abandonar dichas señales. Sin embargo, la producción de un paquete de señales funcionalmente correcto requirió reescribir varias veces el código.
Otro problema con las señales es que pueden perderse, algo que ocurre cuando se presenta otra señal del mismo tipo antes de manejar la primera. Las excepciones en Mach se colocan en una., cola, como resultado de su implantación de RPC (llamadas a procedimientos remotos), lo que se verá más adelante.
El paquete de señales UNIX se usa para interrupciones generadas en forma, 1-interna (excepciones) y externa. Las excepciones no sólo se usan para detectar errores en un programa, sino también para apoyar la depuración. Obviamente, el recurso de señales no es suficiente para que Mach pueda apoyar depurador de aplicaciones multihilos; por esta razón Mach incluye un recurso de manejo de excepciones de propósito general.
Este recurso también es útil para otro fines, como registrar todo el estado de una tarea al presentarse un error fatal (un vaciado del núcleo en BSD ), permitir que las tareas manejen sus propios errores, (sobre todo aritméticos) y emular instrucciones que no están implantadas en el hardware. Las dos categorías a las que corresponden estos usos de excepciones; (manejo de errores y depuración) fueron incorporadas en el recurso de manejo de excepciones de Mach.
El recurso Mach se diseñó para ofrecer un sistema de manejo de excepciones individual, simple y consistente, con apoyo para excepciones estándar, así como las definidas por el usuario.
Para evitar redundancia en el núcleo, Mach utiliza primitivas de núcleo cada vez que sea posible. Por ejemplo, un manejador es sólo otro hilo en la tarea en la cual ocurre la excepción. Los mensajes de Rpc, sirven para sincronizar la ejecución del hilo que causa la excepción (la "víctima") y el manejador, y para comunicar información sobre la excepción entre la víctima y el manejador.
Las dos clases de excepciones se comportan en forma ligeramente distinta: el manejo de errores se lleva a cabo por hilos, mientras que la depuración hace que todas las excepciones de la tarea se dirijan al n-mismo manejador. No tiene sentido tratar de depurar un solo hilo, o que las excepciones de varios hilos invoquen a distintos depuradores. Además de esta distinción, la única otra diferencia entre los dos tipos de excepciones es su herencia de un proceso padre.
Los recursos de manejo de excepciones que abarcan toda la tarea pasan de padres a hijos, de forma que los depuradores pueden manejar todo un árbol de tareas. Los manejadores de errores no se heredan y, a menos que se especifique al crear tareas o hilos, no se dirigen a ningún manejador. Por último, si ocurren excepciones simultáneas, los manejadores de errores tienen precedencia sobre los depuradores. La razón de este enfoque es que los manejadores de errores normalmente forman parte de la tarea, por lo que deben ejecutarse en forma normal incluso en presencia de un depurador.
El manejo de excepciones se lleva a cabo de la siguiente manera:
  • El hilo víctima notifica la ocurrencia de una excepción por medio de un mensaje Rpc, que levanta la excepción que se envía al manejador.
  • La víctima espera a que se maneje la excepción.
  • El manejador recibe la notificación de la excepción, que generalmente incluye información sobre la excepción, el hilo y la tarea.
  • El manejador realiza su función de acuerdo con el tipo de excepción; esto implica aclarar la excepción, con lo que se reanuda la víctima, o terminar el hilo víctima.
Para que Mach pueda apoyar la ejecución de programas BSD, necesita apoyar las señales de tipos BSD. Las señales generadas externamente, incluyendo aquellas que se envían de un proceso BSD a otro, se procesan en la sección BSD del núcleo Mach, por lo que su comportamiento es idéntico al que se presenta en BSD. Las excepciones de hardware son un caso aparte, ya que los programas BSD esperan recibir las excepciones de hardware como señales; por consiguiente, una excepción de hardware provocada por un hilo debe llegar a él en forma de señal. Para producir este resultado, las excepciones de hardware se convierten a excepciones Rpc. Para las tareas y los hilos que no utilizan explícitamente el recurso de manejo de excepciones de Mach, el destino de esta RPC es una tarea en el núcleo que sólo tiene un propósito: su hilo ejecuta en un ciclo continuo recibiendo estas Rpc de excepciones. Para cada Rpc, convierte la excepción a la señal apropiada, la cual se envía al hilo que causó la excepción de hardware; luego completa la RPC y aclara ¡a condición de excepción original. Al concluir la Rpc, el hilo que la inició reingresa el estado de ejecución, de inmediato ve la señal y ejecuta su código de manejo de señales. De esta manera, todas las excepciones de hardware inician de manera uniforme, como excepciones RPC, pero los hilos que no están diseñados para manejar ese tipo de excepciones las reciben como lo harían en un sistema BSD normal: como señales.
w Proceso: espacio de direcciones y colección de hilos que se ejecutan en ese espacio de direcciones.
  • Además poseen puertos para la comunicación:

    • Puerto de proceso: Comunicación con el núcleo.
    • Puerto de arranque: Para inicializar los parámetros del proceso.
    • Puerto de excepción: Lo usa el SO para informar de las excepciones.
    • Puertos registrados: Para comunicación con los servidores estándar del sistema.
    • Un hilo pertenece a un solo proceso.
    • Los hilos poseen prioridades de 0 a 31 o de 0 a 127 y el 0 indica que el hilo tiene mayor prioridad.
    • Se planifican mediante un array global con colas de hilos cada cola de una prioridad.
    • También existe un array local para cada procesador con los hilos que solo se ejecutan en ese procesador.
    • Todas las colas del array local poseen más prioridad que las colas del array global.

2.19.6. GESTION DE MEMORIA
Administración de memoria
Dada la naturaleza orientada a objetos de Mach, no es ninguna sorpresa encontrar que su abstracción principal es el objeto de memoria. Estos objetos de memoria se utilizarán (en la Versión 3) para administrar el almacenamiento secundario y generalmente representan archivos, canales y otros datos con correspondencia de lectura y escritura en memoria virtual (Fig. 16.6). Los objetos de memoria pueden estar en almacenamientos auxiliares por administradores de memoria a nivel de usuario que ocupan el lugar del paginador de memoria virtual tradicional, incorporado en el núcleo, que se encuentra en otros sistemas operativos. En contraste con el enfoque tradicional, donde el núcleo proporciona la administración del almacenamiento secundario, Mach tratará a los objetos del almacenamiento secundario (usualmente archivos) de la misma manera que todos los demás objetos del sistema. A cada objeto se le asociará un puerto, y podrá ser manipulado por medio de mensajes que se envían al puerto. Las ventajas de un enfoque tan flexible son, entre otras, una reducción en la complejidad del núcleo y una mayor conveniencia para experimentos e implantaciones.
Estructura básica
El espacio virtual de direcciones de una tarea generalmente está disperso, formado por varios huecos de espacio no asignado. Por ejemplo, un archivo con correspondencia en memoria se coloca en un conjunto de direcciones. Los mensajes de gran tamaño también se transfieren como segmentos de memoria compartida, y para cada uno de estos segmentos se utiliza una sección de la dirección en memoria virtual para proporcionar a los hilos el acceso a mensaje. Al entrar o salir elementos del espacio de direcciones a carecen por huecos de memoria no asignada. Mach no intenta comprimir el espacio de direcciones, incluso si una tarea puede fallar al no tener espacio suficiente para satisfacer la solicitud de una región de su espacio de direcciones. Puesto que los espacios de direcciones actuales son de cuatro gigabytes por día esta limitante no representa un problema. Si se emplean algoritmos normales de la tabla de páginas para mantener un espacio de direcciones cuatro gigabytes para cada tarea, sobre todo si tiene huecos, se utilizaran cantidades de memoria excesivas. La clave para los espacios de dispersos es que el espacio de la tabla de páginas se usa sólo para las asignadas en ese momento. Al ocurrir una falla de página, el núcleo revisa si la página se encuentra en una región válida, en vez de utilizar un índice para consultar la tabla de páginas y verificar el registro. Aunque esta_ forma de consulta es más compleja, al parecer los beneficios de una reducción en los requisitos de almacenamiento en memoria y el mantenimiento simplificado del espacio de direcciones hacen que este enfoque sea rentable.
Mach también apoya la funcionalidad estándar de la memoria virtual incluyendo la asignación, revocación y copia de memoria virtual. Para asignar una nueva región de memoria virtual, un hilo puede efectuar una llamado vm-allocate (asignar memoria virtual). Puede proporcionarse la dirección, o la puede determinar el núcleo.
La memoria física no se asigna hasta que se efectúa el acceso a las páginas de esta región. El núcleo asigna un nuevo objeto de memoria al ejecutarse la llamada vm-locate y utiliza el paginador por omisión para administrar este objeto. Las regiones de memoria virtual también se asignan automáticamente cuando una tarea recibe un mensaje que contiene datos fuera de línea. La llamada vm-deallocate elimina una región del espacio de direcciones de una tarea; destruye la región sólo si ningún otro hilo tiene acceso a ella. Las llamadas al sistema vm-read (lectura de memoria virtual), vm-write (escritura en memoria virtual) y vm-copy (copia de memoria virtual) permiten la transferencia de datos entre tareas (a través del mecanismo de puertos). La llamada vm-region devuelve información acerca de una región en el espacio de direcciones de una tarea determinada. La llamada vm-protect cambia la protección de acceso de una región de memoria, mientras que vm_inherit se utiliza para especificar cómo se trasferirá una región de memoria a las tareas hijo al momento de su creación (compartida, copia a la escritura o no presente).
Memoria compartida
Mach emplea memoria compartida para reducir la complejidad de varios de los recursos del sistema, así como para ofrecer estas características de manera eficiente. Por lo general, la memoria compartida permite una comunicación entre procesos muy rápida, reduce el tiempo de procesamiento adicional en la administración de archivos y ayuda a apoyar la administración de bases de datos y el multiprocesamiento. Sin embargo, Mach no utiliza la memoria compartida para todas estas funciones tradicionales. Por ejemplo, todos los hilos de una tarea comparten la memoria de la tarea, por lo que no se requiere un recurso formal para compartir memoria dentro de una tarea. No obstante, 'Mach tiene que ofrecer la memoria compartida tradicional para apoyar otras construcciones del sistema operativo, como la llamada al sistema fork de UNIX.
Obviamente, es muy difícil que las tareas en varias máquinas compartan memoria y mantengan la consistencia de los datos. Mach no trata de resolver este problema en forma directa; en cambio, proporciona recursos que permiten resolverlo. Mach brinda apoyo para la memoria compartida consistente sólo cuando la memoria es compartida por tareas que se ejecutan en procesadores que comparten memoria. Una tarea padre puede declarar cuáles serán las regiones de memoria que heredarán sus hijos, y cuáles serán de lectura y escritura. Esto difiere de la herencia de copia a la escritura, donde cada tarea mantiene su propia copia de las páginas cambiadas.
Un objeto con capacidad de escritura se direcciona a partir del mapa de direcciones de cada tarea y todos los cambios se realizan sobre la misma copia. Los hilos en una tarea son responsables de coordinar los cambios a la memoria de manera que no interfieran entre sí (escribiendo al mismo tiempo en la misma localidad). Esto puede lograrse a través de los métodos de sincronización normales, ya sea con secciones críticas o con cerraduras de exclusión mutua para los datos.
Para la situación donde la memoria se comparte entre máquinas diferentes, Mach permite el uso de administradores de memoria externos. Si un conjunto de tareas no relacionadas quiere compartir una sección de la memoria, pueden utilizar el mismo administrador de memoria externo y a través de él lograr el acceso a las mismas áreas de almacenamiento secundario.
El implantador de este sistema tendría que escribir las tareas y el paginador externo, el cual sería tan sencillo o complicado como se requiera. Una implantación sencilla no permitiría lecturas mientras se escribe en una página; cualquier intento de escritura ocasionaría que el paginador invalidara la página en todas las tareas que tienen acceso en ese momento. Después, el paginador permitiría la escritura y volvería a validar los lectores con la nueva versión de la página. Los lectores esperarían durante una falla de página hasta que la página estuviera de nuevo disponible. Mach ofrece un administrador de memoria de este tipo: NetMemServer (servidor de memoria en red).
ADMINISTRACIÓN DE LA MEMORIA:

  • Separa las partes que dependen de la máquina de las que no dependen de ella.
  • Aumenta la portabilidad.
  • El código se divide en 3 partes:

    • La primera: es dependiente de la máquina y se ejecuta en el núcleo. Captura todos los fallos de página.
    • La segunda: es la parte independiente del núcleo. Procesa fallos de página, mapas de direcciones y reemplazo de páginas.
    • La tercera: pertenece al espacio del usuario. Controla la parte lógica, principalmente la memoria virtual.

2.19.7. GESTIÓN DE MEMORIA AUXILIAR (SECUNDARIA Y TERCIARÍA) Y SISTEMA DE ARCHIVOS
Administradores de memoria a nivel de usuario
Un objeto de almacenamiento secundario generalmente tiene una correspondencia con el espacio de direcciones virtuales de una tarea. Mach mantiene una memoria caché con las páginas residentes en memoria de todos los objetos con correspondencia, al igual que en otras-implantaciones de memoria virtual. No obstante, una falla de página que ocurre cuando un hilo tiene acceso a una página no residente, se ejecuta como un mensaje al puerto del objeto. El concepto de un objeto de memoria creado y atendido por tareas ajenas al núcleo (a diferencia de los hilos, por ejemplo, que son creados y mantenidos únicamente por el núcleo) es muy importante. El resultado final es que, en el sentido tradicional, la memoria puede ser paginada por administradores de memoria a nivel de usuario. Cuando se destruye el objeto, depende del administrador de memoria la escritura en almacenamiento secundario de las páginas modificadas. Mach no establece ningún supuesto respecto al contenido o la importancia de los objetos de memoria, por lo que son independientes del núcleo.
Existen varias circunstancias en las cuales son insuficientes los administradores de memoria a nivel de usuario. Por ejemplo, una tarea que asigna una nueva región de memoria virtual puede carecer de un administrador de memoria asignado a esa región, puesto que no representa un objeto de almacenamiento secundario (pero tiene que ser paginado), o un administrador de memoria puede fallar.
Mach necesita un administrador de memoria que se haga cargo de sus necesidades. Para estos casos, Mach proporciona un administrador de memoria por omisión, el cual utiliza el sistema de archivos estándar para almacenar los datos que deben escribirse en disco, en vez de requerir un espacio de intercambios aparte, como sucede en 4.3BSD. El administrador de memoria por omisión tiene una interfaz idéntica a los de nivel de usuario. Un hilo interno del núcleo de Mach, el proceso demonio pageout (salida de páginas), utiliza un algoritmo primitivo para la paginación FIFO con el fin de seleccionar las víctimas para el reemplazo; luego, el
Administrador de memoria por omisión efectúa la decisión de política del proceso demonio de salida de páginas. Un administrador de memoria a nivel de usuario puede ser más inteligente, e implantar cualquier algoritmo para la paginación adecuado para el objeto que pasa al almacenamiento auxiliar.
Si el administrador no logra reducir el número de páginas residentes cuando el núcleo se lo solicita, se invoca al administrador por omisión, el cual saca las páginas, enviándolas al administrador de nivel de usuario para que éste reduzca el tamaño de su conjunto residente. Si en un momento el administrador de nivel de usuario logra recuperarse del problema que le impidió satisfacer la solicitud del núcleo, tocará estas páginas (con lo que el núcleo las volverá a incorporar) y las sacará cuando sea conveniente.
Si un hilo requiere acceso a los datos en un objeto de memoria (por ejemplo, un archivo), invoca la llamada vm-map (correspondencia en memoria virtual) en vez de vm-allocate. En esta llamada al sistema se incluye un puerto, asociado a un administrador de memoria, el cual es responsable de la región. El núcleo ejecuta las llamadas a este puerto cuando hay que leer o escribir datos de esa región. Una complejidad adicional es que el núcleo emite estas llamadas en forma asíncrona, ya que no sería razonable que el núcleo esperara a un hilo a nivel de usuario. A diferencia de la salida de páginas, el núcleo no tiene ninguna alternativa si el administrador de memoria externo no satisface su solicitud. El núcleo no conoce el contenido de un objeto ni cómo hay que manipular éste; si existe una correspondencia entre un objeto de memoria y varias tareas en distintas máquinas, el administrador de memoria es responsable de los requisitos de consistencia y funcionalidad de estas tareas. Por ejemplo, dos tareas en máquinas distintas pueden tratar de modificar un objeto al mismo tiempo; si el administrador de memoria permitiera esta situación, cada uno de los computadores tendría una versión diferente del objeto, lo cual, en la mayoría de los casos, es indeseable. Las tareas múltiples en un mismo computador no ocasionan este problema, ya que la llamada vm-map coloca el objeto en los mapas de memoria de cada una de las tareas.
Cuando se realiza la primera llamada vm-nwp para un objeto de memoria, el núcleo crea dos puertos y los transfiere al administrador de memoria asociado por medio de una llamada memory-manager-inít (asignar valores iníciales al administrador de memoria). Para ser más precisos, el núcleo envía un mensaje al puerto que se transfiere en la llamada vm_map, invocando la rutina memory-Manager-init, que debe proporcionar el administrador de memoria como parte de su apoyo para un objeto de memoria. Los dos puertos que se transfieren al administrador de memoria son un puerto de control y un puerto de nombre. El administrador de memoria utiliza el primero para proporcionar datos al núcleo (por ejemplo, las páginas que deben ser residentes). Los puertos de nombre se usan extensamente en Mach; no reciben mensajes, sólo que se emplean como puntos de referencia y comparación.
El objeto de memoria debe responder a una llamada memory-manager-init con una llamada memory-object-set - attributes (asignar atributos de objeto de memoria) para indicar que está listo para recibir solicitudes. Cuando todas las tareas con derechos de envío para un objeto de memoria renuncian a esos derechos, el núcleo cancela la asignación de los puertos del objeto, liberando así al administrador y al objeto de memoria para que sean destruidos.
Se requieren varias llamadas del núcleo para apoyar a los administradores de memoria externos; de éstas, la llamada vm_map ya ha sido analizada, Existen además mandatos para obtener y asignar atributos y para proporcionar cerraduras a nivel de página cuando sea necesario (por ejemplo, después de ocurrir una falla de página pero antes de que el administrador de memoria haya devuelto los datos apropiados). El administrador de memoria utiliza la llamada memory-object-data-provided (datos del objeto de memoria proporcionados) para pasar una página (o varias, sí se emplea la lectura por adelantado) al núcleo corno respuesta a una falla de página. Esta llamada es necesaria, ya que el núcleo invoca al administrador de memoria en forma asíncrona. También hay varias llamadas que permiten que el administrador de memoria reporte errores al núcleo.
El administrador de memoria debe permitir varias llamadas para apoyar un objeto. Ya hemos analizado la llamada memory-object-init y otras. Cuando un hilo ocasiona una falla de página en una página de un objeto de- memoria, el núcleo envía una llamada memory-object-data-request (solicitud de datos de objeto de memoria) al puerto del objeto en nombre del hilo que ocasionó la falla. El hilo se coloca en estado de espera hasta que el, administrador de memoria envié de vuelta la página en una llamada, memory object—data-provided, o envié al núcleo un error al respecto.
Las páginas modificadas que el núcleo necesita sacar de la memoria residente (por ejemplo, debido al envejecimiento de la página) se envían al objeto de memoria por medio de la llamada memory-object-data- write (escritor de objeto de memoria). Una vez más, existen varias llamadas p cerraduras, información de protección y modificación, y todos aspectos con los que deben tratar los sistemas de memoria virtual.
En su versión actual (2.5), Mach no permite que los administradores de memoria externos afecten directamente los algoritmos para el reemplazo, de páginas. Mach no exporta la información de acceso a memoria necesaria para que una tarea externa seleccione, por ejemplo, la página menos recientemente utilizada. Actualmente se investigan métodos para proporcionar esta información. No obstante, los administradores de memoria externos siguen, siendo útiles por varias razones:
  • Pueden rechazar la víctima de reemplazo del núcleo si saben de un candidato mejor (por ejemplo, reemplazo de páginas MRU).
  • Pueden supervisar el objeto de memoria que pasan al almacenamiento auxiliar y solicitar que las páginas salgan antes de que la utilización de memoria invoque al proceso demonio de Mach.
  • Son especialmente importantes para mantener la consistencia del almacenamiento secundario con hilos en procesadores múltiples, como veremos en la próxima sección.
  • Pueden controlar el orden de las operaciones sobre el almacenamiento secundario para ejercer las restricciones de consistencia que exigen los sistemas de administración de bases de datos. Por ejemplo, en las bitácoras de transacciones, éstas deben escribirse en el archivo de bitácora en disco antes de la modificar la base de datos.
  • Pueden controlar el acceso a archivos por correspondencia.
2.19.8. GESTION DE ENTRADA Y SALIDA
Interfaz con el programador
Existen varios niveles donde un programador puede trabajar en Mach. Se cuenta, por supuesto, con el nivel de llamadas al sistema, equivalente a la interfaz de llamadas al sistema de 4.3BSD. La versión actual de Mach incluye la mayor parte de 4.3BSD como un hilo dentro del núcleo. Cualquier llamada al sistema BSD es atrapada, dirigida al núcleo y atendida, en nombre del emisor, de manera muy similar a como lo manejaría BSD estándar. Como la emulación actual no es multihilos tiene una eficiencia limitada. Sin embargo, la siguiente versión de Mach (3.0) incluirá una versión completamente nueva para emular BSD, que contiene menos código original. Esta versión será multihilos y no formará parte del núcleo, sino que se hallará en la parte de usuario del sistema operativo.
Parte del código se encontrará en una biblioteca incluida en cada una de las tareas que emplea la funcionalidad BSD, mientras que la restante estará en una tarea aparte, el servidor BSD. Así, las llamadas al sistema pasarán por el núcleo antes de ser redirigidas, de ser necesario, a la biblioteca del espacio de direcciones de la tarea o al servidor BSD. Aunque esta transferencia de control adicional reducirá la eficiencia de Mach, debe compensarse en cierta medida por la capacidad para que varios hilos ejecuten de manera concurrente el código tipo BSD.
En el siguiente nivel superior de programación se encuentra el paquete de hilos C (C Threads). Se trata de una biblioteca de tiempo de ejecución que ofrece una interfaz entre el lenguaje C y las primitivas básicas de hilos de Mach. Proporciona un acceso conveniente a estas primitivas, incluyendo rutinas para bifurcar y unir hilos, la exclusión mutua a través de variables mutex y la sincronización por medio de variables de condición. Por desgracia, no resulta apropiado usar el paquete de hilos C entre sistemas que no comparten memoria (sistemas NORMA), ya que para implantar sus construcciones depende de la memoria compartida. Actualmente no hay un equivalente del paquete de hilos C para los sistemas NORMA. Es posible escribir, y se han escrito, otras bibliotecas de tiempo de' ejecución para Mach, que apoyan el uso de hilos para otros lenguajes.
Aunque el uso de primitivas hace flexible a Mach, también ocasiona que muchas tareas de programación sean repetitivas. Por ejemplo, para el envío y recepción de mensajes cada tarea que utiliza mensajes (en Mach, la mayor parte) contiene una gran cantidad de código asociado. Por esto, los diseñadores de Mach ofrecen un generador de interfaces llamado MIG, que es, en esencia, un compilador que toma como entrada una definición de la interfaz que se utilizará (declaraciones de variables, tipos y procedimientos) y genera el código de la interfaz Rpc necesario para enviar y recibir mensajes de acuerdo con esta definición y para conectar los mensajes para los hilos de envío y recepción.
La salida de MIG incluye tres archivos en lenguaje C: un archivo incide con las definiciones que serán compartidas por los componentes del programa y dos archivos proceder, uno para la tarea del lado del usuario y otro para la parte del servidor del canal de comunicaciones. El código de la parte del usuario es capaz de crear y enviar mensajes a la parte del servidor, y esperar la recepción de una respuesta. Un programador que desee emplear el servidor sólo necesita enlazarse con las rutinas de la parte del usuario y hacer que el programa las invoque (con el contenido del mensaje). La parte del servidor es capaz de recibir mensajes, desempacarlos y enviarlos a la rutina apropiada, y luego responder cuando la rutina termina de procesar los datos. Por supuesto, el implantador del servidor aún debe escribir las rutinas principales y de procesamiento de mensajes, pero la interfaz de mensajes ya está completa.
La rutina principal también tiene que asignar puertos y registrarlos con el servicio de nomenclatura para que otras tareas puedan encontrarlos en la red (véase la sección 16.8). Una vez que el servidor recibe un mensaje, puede llamar a una rutina (míg-server) que desempacará el mensaje, llamará a la rutina del lado del servidor, dará forma y empacará un mensaje de respuesta. Un servidor completo puede implantarse usando estos recursos con menos de 100 líneas de código C.

ALGUNAS APROXIMACIONES HIBRIDAS

Dos de los micronúcleos originales, Mach y Chorus, comenzaron su evolución ejecutando los servidores únicamente como procesos de usuario, lo que aseguraba modularidad por el hardware mediante los espacios de direcciones. Cuando los servidores necesiten acceso directo al hardware se proporcionan llamadas especiales al sistema para esos procesos privilegiados, las cuales vincularán registros de dispositivos y bufferes sobre sus espacios de direcciones. El núcleo convierte las interrupciones en mensajes que permiten el manejo de interrupciones a los servidores de nivel usuario. Debido a problemas en las prestaciones, Mach y Chorus cambiaron permitiendo a los servidores cargarse dinámicamente sobre el espacio de direcciones del núcleo o sobre el espacio de direcciones de nivel usuario. Los clientes interactúan con los servidores utilizando las mismas llamadas de comunicación entre procesos. Un problema es que la depuración por parte de un programador de un servidor a nivel de usuario, permitiéndole ejecutarse dentro del espacio de direcciones del núcleo, amenaza la integridad del sistema por cualquier error de programación.

2.19.9. GESTION DE COMUNICACIONES Y SEGURIDAD
Comunicación entre procesos
Recuerde que, en 4.3BSD, la comunicación puede presentarse como conductos, señales y conectores. Por lo general, la comunicación por red tiene lugar entre anfitriones con nombres globales fijos (direcciones de la red). No existe ninguna independencia de la ubicación de los recursos, ya que cualquier sistema remoto que necesite un recurso debe conocer el nombre del sistema que lo provee. Los datos en los mensajes son flujos de bytes no tipificados. Mach simplifica esta perspectiva enviando los mensajes entre puertos, independientes de la ubicación; los mensajes contienen datos tipificados para facilitar su interpretación. Con este sistema simplificado pueden implantarse todos los métodos de comunicación BSD.
Los dos componentes de la ipc Mach son puertos y mensajes. Casi todo lo que existe en Mach es un objeto, y las referencias a objetos se realizan por sus puertos de comunicaciones. Se envían mensajes a estos puertos para que las rutinas que implantan esos objetos efectúen operaciones sobre ellos. Al depender únicamente de puertos y mensajes para toda comunicación, Mach ofrece independencia de la ubicación de los objetos y seguridad en la comunicación. La independencia de los datos es proporcionada por la tarea NetMsgServer, que se analiza más adelante; la seguridad se garantiza al requerir que los emisores y receptores de mensajes tengan derechos. Un derecho consta de un nombre de puerto y una capacidad (enviar o recibir) para ese puerto, y es muy semejante a una capacidad en los sistemas orientados a objetos.
Sólo puede haber una-tarea con derechos de recepción para un puerto, pero varias tareas pueden tener derechos de envío. Al crear un objeto, su creador asigna un puerto para representarlo y obtiene los derechos de acceso al puerto. El creador del objeto (incluyendo el núcleo) puede distribuir los derechos por medio de mensajes. Si el poseedor de un derecho de recepción envía ese derecho en un mensaje, el receptor del mensaje obtiene el derecho y el emisor lo pierde. Una tarea puede asignar puertos para permitir el acceso a cualquier objeto que le pertenezca o para comunicación. La destrucción de un puerto o el poseedor de un derecho de recepción ocasionan la cancelación de todos los derechos para ese puerto y, si se desea, pueden notificarse las tareas que poseen derechos de envío.
Puertos
Un puerto se implanta como una cola limitada y protegida dentro del núcleo del sistema donde reside el objeto. Si una cola está llena, un emisor puede abortar el envío, esperar que esté disponible una ranura en la cola o pedir al núcleo que entregue el mensaje. En este último caso, el núcleo actúa como una cola de un solo mensaje y no aceptará más hasta que entregue el mensaje del emisor.
La llamada al sistema port-allocate asigna un nuevo puerto en una tarea especificada, y otorga a esa tarea todos los derechos de acceso al nuevo puerto; el nombre del puerto se devuelve al generador de la llamada.
La llamada port-deallocate elimina los derechos de acceso a un puerto de una tarea. Si la tarea posee el derecho de recepción, se destruye el puerto y se notifica a todas las tareas con derecho de envío. Finalmente, la llamada al sistema port-status presenta el estado actual del puerto de una tarea. Además, es posible declarar un puerto de almacenamiento auxiliar con la llamada al sistema port-Set-backup, al cual se le otorga el derecho de recepción del puerto si la tarea que posee ese derecho solicita su liberación (o termina).
Al crear una tarea, el núcleo también crea varios puertos para ella. La función task-self devuelve el nombre del puerto que representa a la tarea en las llamadas al núcleo. Por ejemplo, para que una tarea asigne un nuevo puerto, emitirá la llamada port - allocate con task-Self como el nombre de la tarea que será dueña del puerto. La creación de un hilo da como resultado un puerto de hilo thread- self similar en el núcleo. Esto se parece al concepto estándar de identificador de procesos que se presenta en UNIX. Se crea otro puerto para una tarea, que se obtiene con task-notify, que es el puerto al cual el núcleo puede enviar mensajes de notificación de sucesos.
Es posible agrupar puertos en conjuntos de puertos. Este recurso resulta útil si un hilo atenderá solicitudes que llegan por varios puertos (por ejemplo, para objetos múltiples). Un puerto puede pertenecer a sólo un conjunto de puertos a la vez y, si el puerto está en un conjunto, no puede usarse directamente para recibir mensajes. En este caso, el mensaje se dirigirá a la cola del conjunto de puertos.
A un conjunto de puertos no se le puede pasar mensajes, a diferencia de un puerto. La llamada port set llocate crea un nuevo conjunto de puertos, port-set - add añade un puerto a un conjunto, port-set_remove cancela esta operación, port-set-deallocate destruye un conjunto de puertos y port set status presenta el estado de un conjunto. Los conjuntos de puertos son objetos con una finalidad semejante a la de la llamada al sistema select de 4.3BSD, pero más eficientes.
Mensajes
Un mensaje consiste en un encabezado de longitud fija y un número variable de objetos de datos tipificados. El encabezado contiene el nombre del puerto destino, el nombre del puerto de respuesta a donde deberán devolverse mensajes y la longitud del mensaje. Los datos en el mensaje (datos en línea) actualmente están limitados a menos de 8K, y los datos que excedan ese límite deberán enviarse en varios mensajes o, lo que es más probable, por referencia N Con un apuntador en el mensaje (datos fuera de línea, que se describirán más adelante). Cada sección de datos puede ser un tipo sencillo (numérico o caracteres), derechos de puertos o apuntadores a datos fuera de línea. A cada sección se asocia un tipo, de manera que el receptor pueda desempacar los datos correctamente.
El uso de apuntadores en un mensaje permite transferir todo el espacio de direcciones de una tarea en un solo mensaje. El núcleo también inspecciona el mensaje en busca ciertos tipos de datos. El núcleo debe procesar la información de puertos que existe en un mensaje, ya sea traduciendo el nombre del puerto una dirección de una estructura interna de datos de puerto o dirigiéndola a NetMsgServer para su procesamiento.
El núcleo también debe procesar los apuntadores del proceso a datos fuera de línea, ya que un apuntador a datos en el espacio de direcciones del emisor sería inválido en el espacio del receptor, ¡especialmente si el receptor y el emisor residen en sistemas diferentes. Por lo general, los sistemas envían mensajes copiando los datos del emisor al receptor como esta técnica puede ser ineficiente, sobre todo con mensajes de gran tamaño, Mach perfecciona este procedimiento. En un mensaje que se envía a un puerto del mismo sistema no se copian los datos a los que hace referencia un apuntador del emisor al receptor. En vez de esto, se modifica la tabla de páginas de la tarea receptora para incluir una copia a la escritura de las páginas del mensaje. Esta operación es mucho más rápida que el copiado de datos, y hace muy eficiente la transferencia de mensajes. En esencia, la transferencia de mensajes se implanta con la administración de memoria virtual.
La operación se lleva a cabo en dos fases. Un apuntador a una región de la memoria ocasiona que el núcleo efectúe una correspondencia temporal entre esa región y su propio espacio, colocando el mapa de memoria del emisor en modo de copia a la escritura para asegurar que las modificaciones no afecten la versión original de los datos. Al recibir, un mensaje, el núcleo mueve su correspondencia al espacio de direcciones del receptor utilizando una región de memoria virtual recién asignada para la tarea. Por esto se dice que la memoria virtual de Mach está dispersa, pues consiste en regiones de datos, separadas por direcciones no asignadas. Este esquema se presenta en la fig. 16.4. Los mensajes se envían por medio de la llamada al sistema msg-sena y se reciben con msg-receive. Se implanta un mecanismo RPC con MSG_RPC, que envía un mensaje y espera una respuesta.
Los mensajes entre sistemas con datos fuera de línea son un poco más complicados. Mach está diseñado para permitir que se traten como locales, en los que no es necesario transferir los datos, pero sí esta correspondencia en modo de copia por referencia en el espacio de direcciones, del receptor. Los accesos de los hilos de la tarea receptora causarían fallas de páginas, como es usual; sin embargo, lo que no es común es que el núcleo, pase las fallas de página a un administrador de memoria que puede existir en el sistema de la tarea emisora o incluso en un sistema aparte.
Esta flexibilidad se obtiene gracias a la generalidad de la administración de memoria se obtiene gracias al sistema y la funcionalidad independiente de la posición.
Actualmente, Mach no emplea este método para la comunicación entre sistemas porque existen dificultades que aún no se contemplan, por lo que no se ha implantado la copia a la escritura entre sistemas. Estos problemas incluyen las fallas de la red o del administrador de memoria, lo que ocasiona que partes del mensaje no estén disponibles cuando se presenta la falla de página de la tarea receptora.

2.19.9._Transferencia_de_Mensajes_en_MACH.JPG
Transferencias de mensajes en Mach


El servidor de mensajes en red (NetMsgServer)
Para enviar un mensaje entre computadores debe existir una manera para que el software de la red localice el puerto destino para el mensaje. UNIX tradicionalmente deja que los protocolos de bajo nivel de la red se hagan cargo de este mecanismo, lo que requiere que los computadores tengan direcciones fijas conocidas para los demás sistemas. Uno de los principios de Mach es que todos los objetos en el sistema sean independientes de la ubicación y que ésta sea transparente para el usuario. Esto requiere que Mach proporcione un sistema de nomenclatura de mayor nivel para todo el sistema, el servidor de mensajes en red o NetMsgServer (Netwoork Message Server), un proceso demonio de red, a nivel de usuario, basado en capacidades, que limite a las tareas registrar puertos de red; éstos son puertos que pueden ir mensajes de otros computadores.
El NetMsgServer de un computador e los puertos de red del sistema, y puede ponerse en contacto con los servidores de otros computadores y así mantener una base de datos distribuida de puertos de red, la cual se puede consultar por tareas o núcleos.
Ahora que NetMsgServer conoce todos los puertos de la red, puede desempeñar el papel decisivo de un distribuidor de mensajes. El núcleo utiliza el servidor cuando hay que enviar un mensaje a un puerto que no se encuentra en el computador donde se ejecuta el núcleo. Por lo general, NetMsgServer ofrece las mismas funciones para puertos de red, como protección y modificación, que proporciona el núcleo de Mach para los puertos en un sistema. Un usuario puede obtener derechos de envío a un puerto de red solicitando a NetMsgServer que busque un nombre en su base de datos o recibiendo un derecho de puerto en un mensaje. Las tareas heredan automáticamente derechos de envío a NetMsgServer para que puedan efectuar consultas directas.
Puesto que Mach está diseñado para trabajar con sistemas heterogéneos en red, debe ser capaz de enviar datos entre sistemas con un formato que puedan comprender tanto el emisor como el receptor. Por desgracia, los computadores varían en cuanto al formato en que almacenan los tipos de datos. Por ejemplo, en un sistema, el almacenamiento de un entero puede ocupar dos bytes, y el más significativo puede almacenarse antes del menos significativo; otro sistema puede invertir este ordenamiento. Por consiguiente, NetMsgServer tiene otra faceta en su operación: utiliza la información de tipo almacenada en un mensaje para traducir los datos del formato del emisor al formato del receptor. De esta manera, todos los datos están representados correctamente cuando llegan a su destino.
Como el ejemplo de la operación de NetMsgServer considere un hilo en el nodo A que envía un mensaje a un puerto que corresponde a una tarea en el nodo B. El programa envía un mensaje al puerto para el cual tiene derecho de envío.
El mensaje pasa primero por el núcleo, el cual determina que el puerto no es local y dirige el mensaje al servidor en el nodo A. NetMsgServer se pone en contacto (usando la información de su base de datos) con su homólogo en el nodo B y le envía el mensaje. El servidor del nodo B presenta el mensaje al núcleo, después de traducir el puerto de red al puerto local equivalente en el nodo B. Por último, el núcleo entrega el mensaje a la tarea receptora cuando ésta ejecuta una llamada msg-receive.
clip_image004.jpg
2.19.9.B_Transferencia_de_Mensajes_en_MACH.JPG

Comunicación entre procesos en Red
El servidor de mensajes en red de un computador acepta las llamadas a procedimientos remotos netnam-check-in, netname-look-up y netnamo-check-out que se utilizan para añadir, consultar o eliminar puertos de red de la base de datos de NetMsgServer, respectivamente. Como precaución de seguridad, el valor de puerto de una llamada al procedimiento remoto netname-check-in debe ser igual a la llamada netnam-check - out para que un hilo pueda eliminar un nombre de puerto de la base de datos.
Sincronización por medio de IPC
El mecanismo ipc es muy flexible y se utiliza extensamente en Mach. Por ejemplo, puede emplearse para la sincronización de hilos. Es posible usar un puerto como variable de sincronización, al cual se puede enviar n mensajes para n recursos. Cualquier hilo que desee utilizar un recurso ejecuta la llamada msg-receive para ese puerto. Si el recurso está disponible, el hilo recibirá un mensaje; de lo contrario, esperará en el puerto hasta que esté disponible un mensaje. Para devolver un recurso después de utilizarlo, el hilo puede ejecutar una llamada al sistema msg-send. En este aspecto, msg_receive es equivalente a la operación espera y msg-send equivale a la operación señal en un semáforo.

Este método puede emplearse para sincronizar operaciones de semáforos entre hilos de una misma tarea, pero no para la sincronización entre tareas, ya que sólo una tarea puede tener derechos de recepción para un puerto. En el caso de semáforos de propósito más general, puede escribirse un proceso demonio sencillo que implanta el mismo método.

2.19.10.SOPORTE A TIEMPO REAL

· Stefan Savage, Hideyuki Tokuda. Mach en Tiempo Real: Ha llegado la hora de exportar el usuario. Este documento está previsto que aparecen en las Actas del Tercer Simposio Usenix Mach (Machnix), 19-21 de abril de 1993
El actual CMU micronúcleo Mach 3,0 exportaciones de simple retraso de hora y abstracciones a través de acogida \ _GET \ _time () y un tiempo de parámetro a mach \ _msg ().Si bien esto es suficiente para muchos propósitos, no ofrece la precisión o generalidad necesaria para una variedad de aplicaciones de tiempo real. En el presente trabajo se describen las extensiones del CMU a Mach 3,0 que ofrecen a los usuarios con horario flexible basada en la sincronización de hora y servicios. Además, vamos a describir cómo el calendario y la programación de servicios se integran para permitir aplicaciones de tiempo real para manejar el calendario de fallas.

· Hideyuki Tokuda, Tatsuo Nakajima, Prithvi Rao. Real-Time Mach: Hacia predecibles Sistemas de Tiempo Real Proceedings of the USENIX 1990 Mach Workshop, October 1990. Actas de la USENIX Mach Workshop 1990, octubre de 1990.
Los Sistemas Distribuidos en tiempo real desempeñan un papel muy importante en nuestra sociedad moderna. Se utilizan en los aviones de control, sistemas de comunicaciones, mando militar y los sistemas de control, automatización de fábricas y la robótica. Sin embargo, la satisfacción de los rígidos plazos de varios requisitos en tiempo real de actividades distribuidas en tiempo real a menudo requiere métodos ad hoc para afinar el comportamiento de sistemas en tiempo de ejecución.
El objeto de Real-Time Mach es desarrollar un tiempo real de la versión del kernel Mach que proporciona a los usuarios con un previsible y confiable distribuido en tiempo real entorno informático. En el presente trabajo se describe un modelo de hilo en tiempo real, en tiempo real la sincronización, y el ITDS planificador en Tiempo-Real Mach. En él también se debaten las cuestiones de aplicación, en tiempo real el conjunto de herramientas, y la situación actual del sistema.

· Hideyuki Tokuda y Tatsuo Nakajima. Evaluación de Real-Time Sincronización en Tiempo Real Mach. Este documento aparece en el procedimiento para la USENIX Mach Workshop 1991, octubre de 1991.
Real-Time Mach proporciona en tiempo real de hilo y en tiempo real de sincronización de instalaciones. Un tiempo real de hilo se pueden crear para una actividad periódico o aperiódico con un calendario de limitación. Los hilos pueden ser sincronizados entre ellos utilizando un tiempo real y la versión de supervisar la base de sincronización con un mecanismo adecuado y un protocolo de bloqueo. En Real-Time Mach, hemos puesto en práctica varias políticas de bloqueo, como kernelized monitor, prioridad básica, la prioridad la herencia de protocolo, protocolo prioridad techo, y relanzable con sección crítica, para aplicaciones de tiempo real.
En el presente trabajo se describe el tiempo real de sincronización en las instalaciones de Real-Time Mach, su aplicación y la evaluación del desempeño. Nuestros resultados de la evaluación demuestran que la adecuada elección de la política de bloqueo puede evitar la prioridad sin limitar las inversiones y mejorar la planificación del procesador para aplicaciones de tiempo real.

2.19.11.ANALISIS COMPARATIVO CON LINUX Y WINDOWS XP

RELACIONES CON OTROS SISTEMAS OPERATIVOS:

Los sistemas operativos basados en este concepto del Mach fueron OSF/1, NeXTSTEP, e IBM OS/2 para las máquinas basadas en RS/6000 – ninguno de los cuales es ya usado ampliamente -. Otros sistemas operativos querían migrar a esta clase de sistema también, como Pink de Apple, Workplace OS de IBM y varios más.

Apple seleccionó OPENSTEP para ser la base para el sucesor de su clásico Mac OS. Se convirtió en API Cocoa Mac OS X. OPENSTEP es de hecho una versión actualizada de NeXTSTEP, que utilizó el Mach 2.5. Como tal, la amalgama de Mach/BSD de OPENSTEP es la base para el sistema operativo Mac OS X de Apple.

El desarrollador líder en el proyecto Mach, Richard F. Rashid, ha estado trabajando en Microsoft desde 1991 en las varias posiciones a nivel superior en la división de la investigación de Microsoft, Microsoft Research. El Windows NT de Microsoft, precursor del Windows XP actual, comenzó con un modelo basado en un micronúcleo similar al de Mach. Otro de los desarrolladores originales de Mach, Avie Tevanian, fue antes jefe de software en NeXT y hasta Mayo del 2006 fue Director de la Oficina de Tecnología de Software en Apple.

Aun cuando se diseñan, construyen o utilizan muchos sistemas operativos experimentales, Mach es capaz de satisfacer las necesidades de las masas mejor que los demás, pues es completamente compatible con UNIX 4.3BsD, de manera que proporciona una oportunidad única para comparar dos sistemas operativos funcionalmente semejantes, pero internamente diferentes. El orden y el contenido de la presentación de Mach varían respecto a la de UNIX, para reflejar las diferencias en el énfasis de cada sistema. No hay una sección acerca de la interfaz con el usuario, puesto que es similar al de 4.3BSD.