La Evolución del Sistema de tiempo de cómputo compartido UNIX ///////////////////////////////////////////////////////////// Por Dennis M. Ritchie ABSTRACT Este paper presenta una breve historia del desarrollo primigenio del sistema operativo Unix. Se concentra en la evolución del sistema de ficheros, el mecanismo de control de procesos, y la idea de comandos entubados. Cierta atención se presta a las condiciones sociales durante el desarrollo del sistema. ---- Durante los pocos años pasados, el sistema operativo UNIX ha llegado al uso difundido, tan amplio ha sido que su propio nombre se ha convertido en una marca registrada de los Laboratorios Bell. Sus importantes características se han vuelto conocidas a muchas personas. Desde la primer publicación que lo describía en 1974 ha sufrido mucha reescritura y reordenamiento, pero recibió pocos cambios fundamentales. Sin embargo, UNIX nació en 1969, no en 1974, y el desalle de su desarrollo conforma una historia poco conocida y tal vez instructiva. Este paper representa la historia técnica y social de la evolución del sistema. ORIGENES Para la ciencia del cómputo en los Laboratorios Bell, el período 1968-1969 era algo relativamente incómodo. El motivo principal para esto era el repliegue lento, aunque claramente inevitable, de los Laboratorios del proyecto Multics. Para la comunidad de cómputo de los Laboraotiors como un todo, el problema era la cada vez mayor obviedad del gracaso de Multics para ofrecer rápidamente cualquier tipo de sistema utilizable, mucho menos la panacea computacional que de el se había envisionado. Por mucho de este tiempo, el Centro de Cómputo de Murray Hill (Nueva Jersey) también operaba una costosa máquina General Electric GE 645 que simulaba inadecuadamente una GE-635. Otro inconvenciencia ocurrida durante este período fue la saparación organizativa de los servicios de cómputo y la investigación del cómputo. Desde el punto de vista del grupo que se encontraba mayormente involucrado en los comienzos de UNIX (K. Thomson, Ritchie, M. D. McIlroy, J. Ossana) el declive y caída de Multics había hecho sentir su efecto firecto. Estabamos entre los últimos reductos de los Laboratorios Bell que realmente trabajaban en Multics, de modo que aún teníamos algún interés en su éxito. Más importante, el conveniente servicio interactivo de computación que Multics había proetido a una comunidad entera de hecho estaba disponible para nuestro grupo limitado, en un comienzo bajo la éjida del sistema CTSS usado para desarrollar Multics, y luego bajo el Multics en sí. Incluso aunque Multics no era capaz de soportar muchos usuarios, podía soportarnos a nosotros, a pesar de hacerlo a un costo exhorbitante. No queríamos perder el agradable nicho que ocupábamos, porque no existían otros similares disponibles, incluso el servicio de tiempo de cómputo compartido que luego se ofrecería bajo el sistema operativo de General E lectric, aún no existía por entonces. Lo que nosotros queríamos era preservar no sólo un buen ambiente en el cual programar, sino uno alrededor del cual también pudiese formarse una comunidad. Sabíamos de la experiencia que la escencia del cómputo comunal - tal como lo proveen el acceso remoto a máquinas de tiempo de cómputo compartido - no equivale a mecanografiar programas en un terminal teletipo en lugar de introducirlos a través de conmutadores, sino promover la comunicación cercana. Por lo tanto, durante 1969, comenzamos a intentar buscar una alternativa a Multics. La investigación tomó varios rumbos. A lo largo de 1969 nosotrs (principalmente Ossanna, Thompson, Ritchie) presionamos intensamente para la compra de una máquina de escala media para la cual prometimos escribir un sistema operativo; la máquina que sugerimos era la DEC PDP-10 y la SDS (luego Xerox) Sigma 7. El esfuerzo fue frustrante, porque nuestras propuestas nunca fueron claramente rechazadas, pero aún así nunca fueron aceptadas. Varias veces parecimos estar próximos al éxito. El golpe final a este esfuerzo llegó cuando presentamos una propuesta exquisitammente complicada, diseñada para minimizar el gasto financiero, que involucraba alguna compra directa, algún leasing a terceros, y un plan para convertir un procesaodr DEC KA-10 en el próximo a anunciarse y más capacitado KI-10 [N.d.T. distintas versiones de CPU de la DEC PDP-10]. La propuesta fue rechazada, y los rumores que llegaron pronto eran que W.O. Bak er (por entonces vicepresidente de Investigaciones) había reaccionado con el comentario "los Laboratorios Bell no hacen negocios de esta manera!". Realmente es perfectamente obvio en retrospectiva (y debería haberlo sido entonces) que estabamos a los Laboratorios gastar mucho dinero en muy pocas personas y con un plan muy vago. Además, estoy bastante seguro que en ese momento los sistemas Operativos no eran un área atractiva para que la Administración apoyara nuestra labor. Se encontraban en el proceso de extraerse a sí mismos no sólo de los esfuerzos de desarrolllos de sistemas operativos que había fracasado, sino incluso de gestionar un Centro de Cómputo Local. Por lo tanto, puede haber parecido que comprar una máquina como la que habíamos suferido podía llevar a la concreción de otro Multics más, o de otra manera, que si producíamos algo útil, deberían montar otro centro de cómputo más de los cuales deberían hacerse responsables. Además, los agitaciones financieros que tuvieron lugar en 1969, también hubo rispideces técncias. Thompson, R, H Cadanady y Ritchie desarrollaron (en pizarras y blocks de notas) el dsieño básico de un sistema de archivo que luego se convertiría en el corazón de UNIX. La mayoría del diseño era de Thompson, como también lo fue el impuso de pensar en sistemas de archivaje en sí, pero creo que yo contribuí con la idea de los ficheros de dispositivos. El impulso de Thompson para la creaciuón de un sistema operativo tuvo varias formas durante este período; también escribió (en Multics) una simulación bastante detallada de la performace del diseño propuesto para el sistema de archivos, y el comportamiento de los programas de paginado. Además, comenzó a trabajar en un sistema operativo nuevo para la GE645, llegando tan lejos como escribir un ensablado para dicha máquina, así como un núcleo para un sistema operativo rudemanetario, cuyo mayor logro, según creo recordar, era escribir un mensaje de bienvenida. La complejidad de la máquina era tal que un simple mensaje era ya un logro bastante notable, pero cuando se volvió claro que la vida útil de la GE645 en los Laboratorios Bell se mediría en meses, el trabajo fue abandonado. También durante 1969, Thompson desarrolló el juego del "Viaje Espacial", primero escrito en Multics, luego transliterado a FOTRAN para GECOS (el sistema operativo para la General Electric, luego Honneywell 635), que no era menos que la simulación del movimiento de los cuerpos mayores del Sistema sSolar, con un jugador que guiaba una nave de aquí a allá. observando el escenario, e intentando aterrizar en varios planetas y lunas. La versión GECOS resultó insatisfactoria en dos aspectos importantes: primero, la presentación del estado del juego era atolondrada y difícil de controlar porque uno tenía que mecanografiar comandos para hacerlo funcinoar, y segundo, un juego costaba unos 75 dólares de tiempo de CPU en un gran computadora. No tardó mucho tiempo, por lo tanto, hasta que Thompson encontrara un procesador poco utilizado; el sistema al completo se utilizaba como un terminal Graphic-II. Él y yo reescribimos Space Travel para que corriera en esta máquina. La labor fue más ambiciosa de lo que podría parecer; debido a que despreciamnos todo software existente, tuvimos que reescribir un paquete de aritmética de coma flotante, la especificación de puntos para los caracteres gráficos del presentador, y un subsistema de depuración que mostrara de manera continua los contenidos de las localizaciones tipeadas en un costado de la pantalla. todo esto fue escrito en lenguaje ensamblador para un ensamblador cruzado que corría bajo GECOS y producía cintas de papel perforado que podían ser llevadas a la PDP-7. Space Travel, aunque era un juego muy atractivo, principalmente servía como una introducción a la torpe tecnología de preparar programas para la PDP-7. Pronto Thompson comenzó a implementar el sistema de archivaje en papel (tal vez "sistema de archivaje de tiza" sea una descripción más precisa). que había sido diseñado anteriormente. Un siistema de archivos sin una manera de ejercitar es una proposición estéril, de modo que procedió a concretarlo con los otros requerimientos necesarios para un sistema operativo funcional, en particular la noción de procesos. Luego vino un pequeño conjkunto de utilidades de nivel usuario: esto implica una manera de copiar, imprimir, borrar y editar ficheros, y por supuesto un intérprete de comandos (shell) simple. Hasta este momento todos los programas estaban escritos empleando GECOS y los archivos se transferían a la PDP-7 en cinta de papel; pero una vez que completamos un ensamblador, el sistema fue capaz de auto-soportarse. Aunque no fue hasta bien entrado 1970 que Brian Kerningham sugirió el nombre "UNIX", como una broma algo traicionera sobre "Multics", el sistema operativo como lo conocemos hoy nació. El sistema de archivos del PDP-7 UNIX Estructuralmente, el sistema de archivos del UNIX para la PDP-7 era casi idéntico al de hoy. Tenía: 1. Una i-list: un arreglo lineal de i-nodos cada uno describiendo un fichero. Un i-nodo contenía menos de lo que tiene ahora, pero la información escencial era la misma: el modo de protección del fichero, su tipo y tamaño, y un listado de bloques físicos que daban sorpote a sus contenidos. 2. Directorios. Un tipo de fichero especial, que contenía una secuencia de nombres y el número-i asociado. 3. Ficheros especiales que describían dispositivos. No se contenía explícitamente una descripción de dispositivo en el i-nodo, pero en su lugar se codificaba en el número, los números-i específicos correspondían a ficheros específicos. Las llamadas de sistema importantes también se encontraban presentes desde el comento. Leer, Escribir, Abrir, Creat (sic), Cerrar: con una excepción muy importante tratada abajo, eran las mismas que encontramos hoy día. Una diferencia menor era que la unidad de E/S era el Word, no el Byte, porque la PDP-7 era una máquina de direccionamiento de Word. En práctica esto sifnificaba simplemente que todos los programas que hacían cargo de cadenas de caracteres ignoraban los caracteres nulos, ya que estos se usaban para redondear un fichero a un numero par de caracteres. Otra diferencia menor y ocasionalmente molesta era la falta de borrado y matado de procesos para las terminales. Las terminales, en efecto, siempre estaban en modo bruto. Sólo unos pocos programas (notablemente la shell y el editor) se molestaban en implementar el procesado de borrado y matado. A pesar de sus considerables similitudes con el sistema de ficheros actual, el sistema de archivos de la PDP-7 era de una manera destacablemente diferente: no tenía nombres de ruta, y cada argumento de nombre de fichero en el sistema era un nombre simple (sin "/") tomada en relación al directorio actual. Los enlaces, en el sentido UNIX usual, existían. Junto con un conjunto elaborado de convenciones, eran los medios principales por los cuales la falta de nombres de ruta se volvían aceptables. La llamada link tomaba la forma: link(dir, file, new3name) donde dir era un fichero de directorio en el directorio actual, file era una entrada existente en dicho directorio, y newname el nombre del enlace, el cual estaba agregado al directorio actual. Debido a que dir necesitaba estar en el directorio actual, es evidente que la prohibición actual contra los enlaces a directorios no se forzaba entonces, el sistema de archivos del PDP-7 UNIX guerdaba la forma de un gráfico general dirigido. De modo que todo usuario no necesitaba mantener un enlace a todos los directorios de interes, existía un directorio llamado dd que contenía entradas para el directorio de cada usuario. por lo tanto, para hacer un enlace a un fichero x en el directorio ken, podría hacer ln dd ken ken ln ken x x rm ken Este esquema volvía a los directorios lo suficientemente difíciles de usar como para hacer que en la práctica no se los utilizara. Otra barrera importante era que no había manera de crear un directorio mientras el sistema estaba corriendo; todos se gabricaban durante la recreación del sistema de archivos desde la cinta de papel perforado, de modo que los directorios eran en efecto un recurso no renobable. La convención dd hacía al comando chdir relativamente conveniente. Aceptaba múltiples argumentos, y conmutaba al directorio actual a cada directorio nombrado. Por tanto, chdir dd ken movería al directorio ken (incidentemente, chdir se escribia ch; porqué expandimos esto cuando pasamos a la PDP-11, no lo recuerdo). La inconveniencia más seria de la implementación del sistema de archivos, además de la falta de nombres de ruta, era la dificultad en cambiar su configuración; como se ha mencionado, los directorios y los ficheros especiales se hacían tán solo cuando se recreaba el disco. La instalación de un nuevo dispositivo se volvía muy dolorosa, porque el código para el dispositivo se repartía ampliamente a través de todo el sistema; por ejemplo, había varias bucles que visitaban cada dispositivo por vez. No es sorprendente que no hubiese noción de montar un pack de disco duro removible, porque la máquina sólo tenía un disco de cabezal fijo. El código del sistema operativo que implementaba este sistema de archivo era una versión drásticamente simplificada del esquema actual. Una de las simplificaciones importantes seguidas del hecho de que el sistema no era multiprogramado; sólo un programa se encontraba en memoria por vez, y el control se pasaba entre los procesos únicamente cuando había un intercambio explíficto. Por ejemplo, había una rutina iget que volvía disponible un i-nodo nombrado, pero dejaba el i-nodo en una constante, una locación estática en lugar de devolver un puntero a una gran tabla de i-nodos activos. Un percusor del mecanismo de búfer actual estaba presente (con algo así como 4 bufers) pero esencialmente no había sobrepaso a la E/S del disco con conmputación. Esto se evitaba no meramente por simplicidad. El disco asociado a la PDP-7 era rápido para su tiempo, transfería una palabra de 18 bits cada 2 microsegundos. Por otro lado, la PDP-7 en sí tenía un ciclo de memoria de 1 microsegundo, y la mayoría de las instrucciones ocupaban dos ciclos (uno para la instrucción en si, y otro para su operando). Sin embargo, las instrucciones indirectamente direccionada requerían tres ciclos, y la indireccińo era bastante común, porque la máquina no tenía registros índice. Finalmente, el controlador DMA era incapaz de acceder a la memoria durante una instrucción. El problema era que el disco incurriría en errores de sobrepasaje si cualquiera de las instrucciones indirectamente direccionadas se ejecutaban mientras estaba transfiriendo. Por lo tanto el control no podía ser devuelto al usuario, ni de hecho podía el código general del sistema ser ejecutado con el disco en funcinoamiento. Las rutinas de interrupción para el reloj y las terminales, que necesitaban estar corriendo todo el tiempo, tenían que ser codificados en una manera muy extraña para evitar la indirección. Control de procesos Por "control de procesos" quiero significar el mecanismo por el cual los procesos son creados y utilizados; hoy las llamadas de sismemas fork, exec, awit y exit implkementan tales mecanismos. A diferencia del sisetma de archivos, que existe en casi su manera presente en los primeros días, el esquema de control de procesos se sometió a una motación considerable luego de que el PDP-7 UNIX ya se encontraba en uso. (La introducción de nombres de ruta en los sistemas PDP-11 fue ciertamente un avance notacional considerable, pero no un cambio en la estructura fundamental). Hoy, la manera en la cual los comandos son ejecutados por la shell pueden resumirse como sigue: 1. La shell lee una línea de comandos del terminal. 2. crea un proceso hijo a través de fork. 3. El proceso hijo usa exec para llamar al comando desde un fichero. 4. Mientrastanto, la shell padre usa wait para esperar que el proceso del (comando) hijo termine llamando a exit. 5. El shell padre vuelve al paso 1. Los procesos (entidades de ejecución independientemente)) existían muy al comienzo del UNIX de PDP-7. De hecho había precisamente dos de ellos, uno para cada uno de las dos terminales conectadas a la máquina. No había fork, wait o exec. Había un exit, pero su sifnificado era bastante diferente, como se verá. El bucle principal para la shell se producía de la siguiente manera: 1. La shell cerraba todos sus ficheros abiertos, luego abría el fichero especial de terminal para la entrada y salida estándar (descriptores de fichero 0 y 1). 2. Leía una línea de comandos de la terminal. 3. Enlazaba al fichero especificando el comando, abría el fichero, y remobía el enlace. Luego copiaba un programa de inicialización pequeño a la parte superior de memoria y saltaba a él; este programa inicializador leía el fichero sobre el código de la shell, luego saltaba a la primer localización del comando (en efecto, un exec). 4. El comando hacía su trabajo, luego, terminaba llamando exit. La llamada exit causaba que el sistema leyera una copia fresca de la shell sobre el comando terminado, luego para saltar a su iniciio (y por lo tanto, en efecto iba al paso 1). La cosa más interesante sobre esta implementación primitiva es el grado en el cual anticipaba los temas que se desarrollarían más adelante. Ciertamente, no podía dar soporte a procesos en segundo plano ni a ficheros de comandos de shell (mucho menos caños y filtros), pero la redirección de E/S (a través de "<" y ">") pronto estuvo incorporada, y se discute a continuación. La implementación de redirección fue bastante sencilla; en el paso tres indicado arriba, la shell simplemente reemplazaba su entrada estándar o salida con el fichero apropiado. Crucial para el desarrollo subsiguiente fue la implementación de la shell como un programa de nivel de usuario almacenado en un fichero, en lugar de ser parte del sistema operativo. La estructura de este esquema de control de procesos, con un proceso por terminal, es similar a la de muchos sistemas interactivos, por ejemplo CTSS, Multics, Honeywell TSS, y los TSS y TSO de IBM. En general tales sistemas requieren mecanismos especiales para implementar facilidades útiles tales como computaciones desconectadas y ficheros de comando; UNIX en ficha etapa no se molestó en suplir tales mecanismos especiales. También exibía algunos problemas idiosincráticos irritantes. Por ejemplo, una shell recientemente recreada debía cerrar todos sus ficheros abiertos tanto para deshacerse de cualquier fichero abierto dejado por el comando que acababa de ejecutar, y para rescindir previas redirecciones de E/S. Luego debía reabrir el fichero especial correspondiente a su terminal, de forma de poder leer una nueva línea de comandos. No había directorio /dev (porque no había nombres de ruta); además, la shell no podía retener memoria a lo largo de distintos comandos, porque se re-ejecutaba nuevamen te después de cada comando. Por lo tanto, se requería una convención de sistema de archivaje adicional: cada dirección debía contener una entrada tty para un fichero especial que refería a la terminal del proceso que la había abierto. Si por accidente uno cambiaba a algún directorio que carecía de esta entrada, la shell podría quedar en un bucle insalvable; casi siempre el único remedio era reiniciar. (Algunas veces el enlace faltante podía ser concretado a partir de la otra terminal). El proceso de control en su forma moderna fue diseñado e implementado en un par de días. Es sorprendente cuán facilmente se incorporó al sistema existente; al mismo tiempo, es fácil ver cómo algunos de las funcionalidades ligeramente inusuales de diseño están presentes precisamente porque representaron cambios pequeños, fácilmente programados a lo que ya existía. Un buen ejemplo es la separación de las funciones de fork y exec. El modelo más común para la creación de nuevos procesos involucra especificar un programa para el proceso a ejecutar; en UNIX, un proceso bifurcado continúa ejecutando el mismo programa que su padre hasta que desarrolla un exec explícito. La separación de las funciones ciertamente no es única a UNIX, y de hecho estaba presente en el sistema de cómputo de tiempo compartido de Berkeley, que era bien conocido por Thompson. Aún así, parece razonable suponer que existe en UNIX principalmente por la facilidad con la cual fork pudo ser implementado sin cambiar muchas o tras cosas más. El sistema ya manejaba múltiples (por ejemplo, dos) procesos; había una tabla de procesos, y los procesos se intercambiaban entre la memoria principal y el disco. La implementación inicial de fork sólo requirió: 1. Expandir la tabla de procesos 2. Agregar una llamada fork que copiara el proceso actual al área de intercambio de disco, usando las primitivas de intercambio de E/S ya existentes; y hacer algunos ajustes a la tabla de procesos. De hecho, la llamada fork de la PDP-7 requería precisamente 27 líneas de código ensamblador. Por supuesto, otros cambios en el sistema operativo y los programas de usuarios fueron requeridos, y algunos de ellos fueron bastante interesantes e inesperados. Pero un fork-exec combinado podría haber sido considerablemente más complicado, si sólo porque exec como tal no existía; su función ya era realizada -usando E/S explícita- por la shell. La llamada de sistema exit, la cual previamente leía una nueva copia de la shell (realmente una especie de exec automático pero sin argumentos) simplificada considerablemente; en la nueva versión, un proceso sólo tenía que limpiar su entrada de tabla de procesos, y ceder el control. Curiosamente, las primitivas que se convirtieron en wait eran considerablemente más generales que en el esquema actual. un par de primitivas envíaban mensajes de una word entre procesos declarados: smes (pid, mensaje) (pid, mensaje)=rmes() El proceso destino de smes no necesitaba tener ninguna relación ancestral con el receptor, aunque el sistema no proveía un mecanimos explífico para comunicar IDs de procesos, ecepto que fork devolvía a vada uno de los padres e hijos la ID de su pariente. Los mensajes no eran enviados a cola; un remitente se retrasaba hasta que el receptor leía el mensaje. La facilidad de mensajes fue utilizada de la siguiente manera: la shell padre -luego de crear un proceso para ejecutar un comando- envía un mensaje a los nuevos procesos por smes; cuando el comando terminaba (asumiento que no intentaba leer ningún mensaje) el smes bloqueado de la shell se volvía -en efecto- el equivalente de wait. Un protocolo diferente, que sacaba ventaja de máws de la generalidad ofrecida por el mensaje, se usaba entre el programa de inicialización y las shells para cada terminal. El profceso de inicialización, cuya ID era entendida como 1, creaba una shell apra cada una de las terminales, y luego enviaba rmses; cada shell, cuando leían el fincal de su fichero de entrada, usaba smes para enviar un mensaje convencional "estoy finalizados" al proceso de inicialización, el cual recreaba un nuevo proceso de shell para dicho terminal. No pUedo recordar otro uso de mensajes. Esto explica porqué la facilidad fue reemplazada con la llamada wait en el sistema actual, la cual es menos general, pero más directamente aplicable al propósito deseado. Posiblemente relevante también sea el bug evidente el el mecanismo: si un proceso de coamdno intentaba usar mensajes para comunicarse con otros procesos, interrumpiría la sincronización de la shell. La shell dependía de enviar un mensaje que nunca fue recibido; su un comando ejecutaba rms, recibiría el mensaje falso de la shell, y cusaría que la shell leyera otra línea de entrada de la misma manera que si el comando hubiese finalizado. Si se hubiera manifestado por si misma una neecesidad para mensajes generales, el bug probablemente hubiese sido reparado. En cualquier csao, el esquema de control de procesos nuevos instantaneamente volvió algunas funcionalidades muy valiosas en triviales de implementar; por ejemplo, los procesos abandonados (con "&") y el uso recursivo de la shell como un comando. La mayoría de los sistemas deben suplir algún tipo de "envío de trabajo por lotoes" y un intérprete de comandos especial para los ficheros distintos a los que se usan interactivamente. A pesar de que la idea de múltiples procesos se introdujo muy fácilmente, hubieron algunos efectos posteriores que no fueron anticipados. El más memorable de todos estos se hizo evidente pronto tras que se puso en funcinoamiento el nuevo sistema y aparentemente funcionaba. En el medio de nuestro júbiulo, se descubrió que el comando chdir (cambiar directorio actual) había dejado de funcionar. Hubo mucha lectura de código fuente e introspección ansiosa sobre cómo el agregado de fork podría haber roto la llamada chdir. Finalmente apareció la verdad: en el viejo sistema chdir era un comando ordinario; ajustaba el directorio actual del (único) proceso asociado a terminal. Bajo el nuevo sistema, el comando chdir correctamente cmabiaba el direcotio actual del proceso creado para ejecutarlo, pero este proceso rápidamente terminaba y no tenía efecto alguno sobre la shell padre! Fue necesario hacer de chdir un comando especial, ejecutado internamiente dentro de la shell. Resultó que varias funciones s imilares a comandos tenían la misma propiedad, por ejemplo login. Otro desencuentro entre el sistema como había sido y el nuevo esquema de control de procesos llevaron más tiempo en volverse evidentes. Originalmente, el puntero read/write asociado con cada fichero abierto se almacenaba dentro del proceso que abría le fichero (este puntero indica dónde en el archivo la siguiente lectura o escritura tendrá lugar). El problema con esta organización se volvió evidente s+polo cuando intentamos usar ficheros de comando. Supongamos un fichero de comando simple que contiene ls who y se ejecuta como sigue: sh comfile>output La secuencia de eventos era: 1. La shell principal crea un proceso nuevo, que abrie outfile para recibir la salida estándar y ejecuta la shell recursivamente. 2. La nueva shell crea otro proceso para ejecutar ls, el cual correctamente escribe en el fichero output y luego finaliza. 3. Otro proceso es creado para ejecutar el sisguiente comando. Sin embargo, el puntero de E/S para la salida es copiado desde aquella a la shell, y aúin es 9, porque la shell nunha ha escrito sobre su salida, y los punteros E/S están asociados con procesos. El efecto es que la salida de who sobreescribe y destruye la salidad del comando ls precedente. La solución a este problema requirió la creación de una nueva tabla de sistema para contener los punteros dee E/S para abrir ficheros independientemente del proceso en el cual fueron abiertos. Redirección de E/S La muy conveniente notación para redirección de E/S, usando los caracteres ">" y "<", no estava presente desde el comienzo del sistema PDP-7 UNIX, pero apareció bastante al principio. Como mucho más en UNIX, estuvo inspirada por una idea de Multics. Multics tenía un mecanismo de E/S bastante general que involucraba cadenas de E/S designadas que podían ser redireccionadas dinámicamente a varios dispositivos, ficheros e incluso a través de módulos de procesamientos de cadenas especiales. Incluso en la versión de Multics. Incluso en la versión de Multics que conocíamos hace una década, existía un comando para redirigir la salida posterior, normalmente destinada a la terminal, a un archivo, y otro para volver a enviarla a la terminal. Mientras que en UNIX se podría usar: Is>xx para obtener una lista de los nombres de los archivos en xx, en Multics la notación era: iocall i 0ca I I attach user_output f i I e x x lis t a t t a c h use r _0 u t put syn user-i/o Aunque esta secuencia tan engorrosa se usaba con frecuencia en la época de Multics y habría sido muy fácil integrarla en la shell de Multics, la idea no se nos ocurrió ni a nosotros ni a nadie más en aquel momento. Supongo que la razón fue la enorme envergadura del proyecto Multics: los desarrolladores del sistema de entrada/salida estaban en Bell Labs en Murray Hill, mientras que la shell se desarrolló en el MIT. No nos planteamos modificar el intérprete de comandos (era su programa); por consiguiente, es posible que los responsables del intérprete ni siquiera conocieran la utilidad, aunque algo torpe, de `ioeal!`. (El manual de Multics de 1969 cataloga `ioeal!` como un comando «mantenido por el autor», es decir, no estándar). Dado que tanto el sistema de E/S de UNIX como su intérprete de comandos estaban bajo el control exclusivo de Thompson, cuando finalmente surgió la idea adecuada, su implementación solo llevó una hora aproximadamente. La llegada del POP-11 A principios de 1970, UNIX para PDP-7 ya estaba en funcionamiento. Si bien era primitivo para los estándares actuales, aún ofrecía un entorno de programación más agradable que sus alternativas. Sin embargo, era evidente que el PDP-7, una máquina que ni siquiera poseíamos, ya estaba obsoleto, y sus sucesores de la misma línea ofrecían poco interés. A principios de 1970 propusimos la adquisición de una PDP-11, que Digital acababa de lanzar. En cierto modo, esta propuesta era simplemente la última de una serie de intentos realizados durante el año anterior. Se diferenciaba en dos aspectos importantes. Primero, la cantidad de dinero (unos 65.000 dólares) era mucho menor que la que habíamos solicitado anteriormente; segundo, el objetivo no era simplemente desarrollar un sistema operativo (sin especificar), sino crear un sistema diseñado específicamente para editar y formatear texto, lo que hoy se denominaría un procesador de textos. La iniciativa surgió principalmente de J. F. Ossanna, quien, desde entonces y hasta el final de su vida, se interesó por el procesamiento de textos. Si nuestras primeras propuestas eran demasiado vagas, esta quizás era demasiado específica; al principio tamb ién fue recibida con recelo. Sin embargo, poco después se consiguieron los fondos gracias a la gestión de L. E. McMahon, y en mayo se realizó un pedido de una PDP-11. El procesador llegó a finales del verano, pero el PDP-II era un producto tan nuevo que no hubo disco disponible hasta diciembre. Mientras tanto, se escribió una versión rudimentaria de UNIX, solo para el núcleo, utilizando un ensamblador cruzado en el PDP-7. La mayor parte del tiempo, la máquina permanecía en un rincón, enumerando todos los recorridos cerrados del caballo en un tablero de ajedrez de 6x8, una tarea que duró tres meses. El primer sistema PDP-11 Una vez que llegó el disco, el sistema se completó rápidamente. En su estructura interna, la primera versión de UNIX para el PDP-II representó un avance relativamente menor con respecto al sistema PDP-7; su escritura fue en gran medida una cuestión de transliteración. Por ejemplo, no había multiprogramación; solo un programa de usuario estaba presente en el núcleo en cada momento. Por otro lado, se introdujeron cambios importantes en la interfaz de usuario: se implementó la estructura de directorios actual, con rutas completas, junto con la forma moderna de `exec` y `wait`, y funciones prácticas como el borrado de caracteres y el bloqueo de líneas para terminales. Quizás lo más interesante del sistema era su reducido tamaño: contaba con 24 KB de memoria principal (16 KB para el sistema y 8 KB para programas de usuario) y un disco con bloques de 1 KB (512 KB). Los archivos estaban limitados a 63 KB. Al realizar el pedido del PDP-II, parecía lógico, o quizás conveniente, prometer un sistema dedicado al procesamiento de textos. Durante la prolongada espera del hardware, la creciente utilidad de UNIX para PDP-7 justificó la creación de UNIX para PDP-11 como herramienta de desarrollo, que se utilizaría para escribir el sistema más específico. Para la primavera de 1971, existía un consenso general de que nadie tenía el menor interés en abandonar UNIX. Por lo tanto, transcribimos el formateador de texto roff al lenguaje ensamblador PDP-11, partiendo de la versión PDP-7 que había sido transcribida de la versión BCPL de McIlroy en Multics, que a su vez se había inspirado en el programa runoff de J. Saltzer en CTSS. A principios del verano, con el editor y el formateador en mano, nos sentimos preparados para cumplir con nuestro cometido al ofrecer un servicio de procesamiento de texto al departamento de Patentes para la preparación de solicitudes de patentes. En ese momento, estaban evaluando un sistema comercial para este propósito; las principales ventajas que ofrecíamos (además de la dudosa de participar en un experimento interno) eran dos: primero, admitíamos Teletypos modelo 37, que, con una caja de tipos ampliada, podían imprimir la mayoría de los símbolos matemáticos necesarios. En segundo lugar, rápidamente dotamos a Roff de la capacidad de generar páginas numeradas por línea, requisito indispensable para el responsable de patentes y que el otro sistema no podía gestionar. Durante la segunda mitad de 1971, apoyamos a tres mecanógrafas del departamento de patentes, quienes dedicaban el día a escribir, editar y formatear solicitudes de patentes, mientras intentábamos continuar con nuestro propio trabajo. UNIX tiene fama de ofrecer servicios interesantes en hardware modesto, y este periodo podría marcar un punto álgido en la relación beneficio/equipo; en una máquina sin protección de memoria y con un único disquete de 0,5 MB, cada prueba de un nuevo programa requería cuidado y audacia, ya que podía provocar fácilmente un fallo del sistema, y ​​cada pocas horas de trabajo de las mecanógrafas implicaban transferir más información a DECtape, debido al reducido tamaño del disquete. El experimento fue agotador, pero exitoso. El departamento de patentes no solo adoptó UNIX, convirtiéndose así en el primero de muchos grupos en los Laboratorios en ratificar nuestro trabajo, sino que logramos la credibilidad suficiente para convencer a nuestra propia dirección de adquirir uno de los primeros sistemas PDP-II/45 fabricados. Desde entonces, hemos acumulado mucho hardware y trabajado continuamente en el software, pero dado que la mayor parte del trabajo interesante ya se ha publicado (por ejemplo, sobre el propio sistema 1,5,6 y las aplicaciones de procesamiento de texto), parece innecesario repetirlo aquí. Tuberías Una de las contribuciones más admiradas de UNIX a la cultura de los sistemas operativos y los lenguajes de comandos es la tubería, utilizada en una secuencia de comandos. Por supuesto, la idea fundamental no era nueva; la tubería es simplemente una forma específica de corrutina. Incluso la implementación no carecía de precedentes, aunque no lo sabíamos en aquel momento; los "archivos de comunicación" del Sistema de Tiempo Compartido de Dartmouth 10 hacían prácticamente lo mismo que las tuberías de UNIX, aunque parece que no se explotaron al máximo. Las tuberías aparecieron en UNIX en 1972, mucho después de que la versión del sistema para PDP-11 ya estuviera en funcionamiento, por sugerencia (o quizás insistencia) de M. D. McIlroy, un defensor desde hace mucho tiempo del flujo de control no jerárquico que caracteriza a las corrutinas. Algunos años antes de que se implementaran las tuberías, sugirió que los comandos se concibieran como operadores binarios, cuyos operandos izquierdo y derecho especificaban los archivos de entrada y salida. Así, una utilidad de "copia" se comandaría mediante: entrada archivo copiar salida archivo Para crear una tubería, se podían apilar operadores de comandos. De este modo, para ordenar la entrada, paginarla correctamente e imprimir el resultado sin conexión, se escribiría: entrada ordenar paginar imprimir En el sistema actual, esto correspondería a: ordenar La idea, explicada una tarde en una pizarra, nos intrigó, pero no desencadenó ninguna acción inmediata. Hubo varias objeciones a la idea tal como se planteó: la notación infija parecía demasiado radical (estábamos demasiado acostumbrados a escribir 'cp x y' para copiar x a y); y no veíamos cómo distinguir los parámetros de comando de los archivos de entrada o salida. Además, el modelo de ejecución de comandos de una entrada y una salida parecía demasiado restrictivo. ¡Qué falta de imaginación! Tiempo después, gracias a la persistencia de McIlroy, finalmente se instalaron las tuberías en el sistema operativo (una tarea relativamente sencilla) y se introdujo una nueva notación. Utilizaba los mismos caracteres que para la redirección de E/S. Por ejemplo, la tubería anterior podría haberse escrito así: sort La idea es que después de '>' puede ir un archivo, para especificar la redirección de la salida a ese archivo, o un comando al que se dirige la salida del comando anterior como entrada. El '>' final era necesario en el ejemplo para especificar que la salida (inexistente) de opr debía dirigirse a la consola; de lo contrario, el comando opr no se habría ejecutado en absoluto. En su lugar, se habría creado un archivo `opr`. La nueva funcionalidad fue recibida con entusiasmo, y pronto se acuñó el término «filtro». Muchos comandos se modificaron para que pudieran utilizarse en tuberías. Por ejemplo, nadie había imaginado que alguien querría que la utilidad `sort` o `pr` ordenara o imprimiera su entrada estándar sin argumentos explícitos. Pronto se hicieron evidentes algunos problemas con la notación. El más molesto era un problema léxico trivial: la cadena después de `>` estaba delimitada por espacios en blanco, por lo que, para pasar un parámetro a `pr` en el ejemplo, había que citar: En segundo lugar, en un intento por lograr generalidad, la notación de tubería aceptaba `<` como una redirección de entrada de forma equivalente a `>`; esto significaba que la notación no era única. También se podría escribir, por ejemplo: opropr> La notación de tubería con '<' y '>' solo duró un par de meses; fue reemplazada por la actual, que utiliza un operador único para separar los componentes de una tubería. Si bien la notación antigua tenía cierto encanto y coherencia interna, la nueva es sin duda superior. Claro que también tiene limitaciones. Es claramente lineal, aunque existen ciertas excepciones. Situaciones en las que se requieren múltiples entradas y salidas redirigidas. Por ejemplo, ¿cuál es la mejor manera de comparar las salidas de dos programas? ¿Cuál es la notación apropiada para invocar un programa con dos flujos de salida paralelos? En la sección sobre redirección de E/S, mencioné que Multics proporcionaba un mecanismo para dirigir los flujos de E/S a través de módulos de procesamiento hacia (o desde) el dispositivo o archivo que actuaba como origen o destino. Por lo tanto, podría parecer que la segmentación de flujos en Multics fue el precursor directo de las tuberías de UNIX, al igual que la redirección de E/S de Multics lo fue para su versión de UNIX. De hecho, no creo que esto sea cierto, o lo es solo en un sentido limitado. Las corrutinas no solo eran bien conocidas, sino que su implementación como módulos de E/S segmentables de Multics requería que estos módulos se codificaran de forma especial para que no pudieran utilizarse para ningún otro propósito. La genialidad de la tubería de UNIX reside precisamente en que se construye a partir de los mismos comandos que se utilizan constantemente de forma simplex. El salto mental necesario para vislumbrar esta posibilidad e inventar la notación fue considerable. Lenguajes de alto nivel Cada programa para el sistema UNIX original del PDP-7 se escribía en lenguaje ensamblador, y era lenguaje ensamblador puro; por ejemplo, no había macros. Además, no existía un cargador ni un editor de enlaces, por lo que cada programa debía ser completo en sí mismo. El primer lenguaje interesante que apareció fue una versión de TMG11 de McClure, implementada por McIlroy. Poco después de que TMG estuviera disponible, Thompson decidió que no podíamos pretender ofrecer un servicio informático real sin Fortran, así que se puso a escribir una versión de Fortran en TMG. Si mal no recuerdo, la intención de trabajar con Fortran duró aproximadamente una semana. En cambio, produjo una definición y un compilador para el nuevo lenguaje B. B estuvo muy influenciado por el lenguaje BCPL; otras influencias fueron el gusto de Thompson por la sintaxis espartana y el reducido espacio en el que debía caber el compilador. El compilador producía código interpretado sencillo; Aunque tanto el programa como los que generaba eran bastante lentos, hicieron la vida mucho más agradable. Una vez que se dispuso de interfaces para las llamadas al sistema habituales, volvimos a disfrutar de las ventajas de usar un lenguaje razonable para escribir lo que normalmente se denomina «programas de sistema»: compiladores, ensambladores y similares. (Si bien algunos podrían considerar que el PL/I que usábamos con Multics era poco razonable, era mucho mejor que el lenguaje ensamblador). Entre otros programas, el compilador cruzado B para PDP-7 para el PDP-11 se escribió en B, y con el tiempo, el compilador B para el propio PDP-7 se transcribió de TMG a B. Cuando llegó el PDP-11, B se trasladó a él casi de inmediato. De hecho, una versión del programa de calculadora de escritorio de precisión múltiple fue uno de los primeros programas en ejecutarse en el PDP-11, mucho antes de la llegada del disquete. Sin embargo, B no se impuso de inmediato. Solo se consideró superficialmente la posibilidad de reescribir el sistema operativo en B en lugar de ensamblador, y lo mismo ocurrió con la mayoría de las utilidades. Incluso el ensamblador se reescribió en ensamblador. Este enfoque se adoptó principalmente debido a la lentitud del código interpretado. De menor importancia, pero no por ello menos relevante, fue la incompatibilidad entre el lenguaje B, orientado a palabras, y el PDP-11, que utilizaba direcciones de byte. Así pues, en 1971, se comenzó a trabajar en lo que se convertiría en el lenguaje C. La historia del desarrollo de lenguajes, desde BCPL hasta C, pasando por B, se narra en otro lugar y no es necesario repetirla aquí. Quizás el punto de inflexión más importante se produjo en 1973, cuando el núcleo del sistema operativo se reescribió en C. Fue entonces cuando el sistema adquirió su forma moderna; el cambio de mayor alcance fue la introducción de la multiprogramación. Hubo pocos cambios visibles externamente, pero la estructura interna del sistema se volvió mucho más racional y general. El éxito de este esfuerzo nos convenció de que C era útil como una herramienta casi universal para la programación de sistemas, en lugar de ser simplemente un juguete para aplicaciones sencillas. Hoy en día, el único programa importante de UNIX que aún se escribe en ensamblador es el propio ensamblador; prácticamente todos los programas de utilidad están en C, al igual que la mayoría de las aplicaciones, aunque también existen sitios con muchos programas en Fortran, Pascal y Algol 68. Parece indudable que gran parte del éxito de UNIX se debe a la legibilidad, la modificabilidad y la portabilidad de su software, lo cual, a su vez, se deriva de su expresión en lenguajes de alto nivel. Conclusión Una de las cosas reconfortantes de los viejos recuerdos es su tendencia a idealizarlos. El entorno de programación que ofrecían las primeras versiones de UNIX, al describirlo aquí, parece extremadamente duro y primitivo. Estoy seguro de que si me viera obligado a volver al PDP-7, lo encontraría intolerablemente limitado y carente de comodidades. Sin embargo, en aquel momento no lo parecía; la memoria se centra en lo bueno y lo que perduró, y en la alegría de contribuir a crear las mejoras que hicieron la vida más fácil. Dentro de 10 años, espero que podamos recordar con nostalgia. La misma impresión mixta de progreso y continuidad. Agradecimientos Agradezco a S. P. Morgan, K. Thompson y M. D. McIlroy por proporcionar documentos iniciales y rescatar recuerdos. Dado que mi principal interés es describir la evolución de las ideas, este artículo atribuye ideas y trabajo a individuos solo cuando parece más relevante. En general, el lector no se equivocará si interpreta cada aparición de «nosotros» con antecedente poco claro como «Thompson, con cierta ayuda mía». Dennis Ritchie, Centro de Investigación en Ciencias de la Computación, Laboratorios Bell de AT&T, 600 Mountain Ave., Murray Hill, NJ 07974. Ritchie y Thompson fueron los principales desarrolladores del Sistema UNIX y coautores del artículo original que lo describía, publicado en 1974 en Comm. Assoc. Compo Mach. ----- Even in the version of Multics we were familiar with a decade ago, there existed a command that switched subsequent output normally destined for the terminal to a file, and another command to reattach output to the terminal. Where under UNIX one might say Is>xx to get a listing of the names of one's files in xx, on Multics the notation was iocall i 0ca I I attach user_output f i I e x x lis t a t t a c h use r _0 u t put syn user-i/o Even though this very clumsy sequence was used often during the Multics days, and would have been utterly straightforward to integrate into the Multics shell, the idea did not occur to us or anyone else at the time. I speculate that the reason it did not was the sheer size of the Multics project: the implementors of the I/O system were at Bell Labs in Murray Hill, while the shell was done at MIT. We didn't consider making changes to the shell (it was their program); correspondingly, the keepers of the shell may not even have known of the usefulness, albeit clumsiness, of ioeal!. (The 1969 Multics manual lists ioeal! as an 'author-maintained,' that is, non-standard, command.) Because both the UNIX I/O system and its shell were under the exclusive control of Thompson, when the right idea finally surfaced, it was a matter of an hour or so to implement it. The advent of the POP-11 By the beginning of 1970, PDP-7 UNIX was a going concern. Primitive by today's standards, it was still capable of providing a more congenial programming environment than its alternatives. Nevertheless, it was clear that the PDP-7, a machine we didn't even own, was already obsolete, and its successors in the same line offered little of interest. In early 1970 we proposed acquisition of a PDP-11, which had just been introduced by Digital. In some sense, this proposal was merely the latest in the series of attempts that had been made throughout the preceding year. It differed in two important ways. First, the amount of money (about $65,000) was an order of magnitude less than what we had previously asked; second, the charter sought was not merely to write some (unspecified) operating system, but instead to create a system specifically designed for editing and formatting text, what might today be called a 'word-processing system.' The impetus for the proposal came mainly from J. F. Ossanna, who was then and until the end of his life interested in text processing. If our early proposals were too vague, this one was perhaps too specific; at first it too met with disfavor. Before long, however, fund s were obtained through the efforts of L. E. McMahon, and an order for a PDP-11 was placed in May. The processor arrived at the end of the summer, but the PDP-II was so new a product that no disk was available until December. In the meantime, a rudimentary, core-only version of UNIX was written using a cross-assembler on the PDP-7. Most of the time, the machine sat in a corner, enumerating all the closed Knight's tours on a 6x8 chess board-a three-month job. The first PDP-11 svstem Once the disk arrived, the system was quickly completed. In internal structure, the first version of UNIX for the PDP-II represented a relatively minor advance over the PDP-7 system; writing it was largely a matter of transliteration. For example, there was no multiprogramming; only one user program was present in core at any moment. On the other hand, there were important changes in the interface to the user: the present directory structure, with full path names, was in place, along with the modern form of exec and wait, and conveniences like character-erase and line-kill processing for terminals. Perhaps the most interesting thing about the enterprise was its small size: there were 24K of core memory (16K for the system, 8K for user programs), and a disk with 1K blocks (512K). Files were limited to 63K. At the time of the placement of the order for the PDP-II, it had seemed natural, or perhaps expedient, to promise a system dedicated to word processing. During the protracted arrival of the hardware, the increasing usefulness of PDP-7 UNIX made it appropriate to justify creating PDP-11 UNIX as a development tool, to be used in writing the more special-purpose system. By the spring of 1971, it was generally agreed that no one had the slightest interest in scrapping UNIX. Therefore, we transliterated the roff text formatter into PDP-11 assembler language, starting from the PDP-7 version that had been transliterated from McIlroy's BCPL version on Multics, which had in turn been inspired by J. Saltzer's runoff program on CTSS. In early summer, editor and formatter in hand, we felt prepared to fulfill our charter by offering to supply a text-processing service to the Patent department for preparing patent applications. At the time, they were evaluating a commercial system for this purpose; the main advantages we offered (besides the dubious one of taking part in an in-house experiment) were two in number: first, we supported Teletype's model 37 terminals, which, with an extended type-box, could print most of the math symbols they required; second, we quickly endowed roff with the ability to produce line-numbered pages, which the Patent Officer required and which the other system could not handle. During the last half of 1971, we supported three typists from the Patent department, who spent the day busily typing, editing, and formatting patent applications, and meanwhile tried to carry on our own work. UNIX has a reputation for supplying interesting services on modest hardware, and this period may mark a high point in the benefit/equipment ratio; on a machine with no memory protection and a single 0.5 MB disk, every test of a new program required care and boldness, because it could easily crash the system, and every few hours' work by the typists meant pushing out more information onto DECtape, because of the very small disk. The experiment was tyring but successful. Not only did the Patent department adopt UNIX, and thus become the first of many groups at the Laboratories to ratify our work, but we achieved sufficient credibility to convince our own management to acquire one of the first PDP-Il/45 systems made. We have accumlated much hardware since then, and labored continuously on the software, but because most of the interesting work has already been published, (e.g. on the system itself 1,5,6 and the text processing applications) it seems unnecessary to repeat it here. Pipes One of the most widely admired contributions of UNIX to the culture of operating systems and command languages is the pipe, as used in a pipeline of commands. Of course, the fundamental idea was by no means new; the pipeline is merely a specific form of co-routine. Even the implementation was not unprecedented, although we didn't know it at the time; the 'communication files' of the Dartmouth Time-Sharing System 10 did very nearly what UNIX pipes do, though they seem not to have been exploited so fully. Pipes appeared in UNIX in 1972, well after the PDP-11 version of the system was in operation, at the suggestion (or perhaps insistence) of M. D. McIlroy, a long-time advocate of the non-hierarchical control flow that characterizes coroutines. Some years before pipes were implemented, he suggested that commands should be thought of as binary operators, whose left and right operand specified the input and output files. Thus a 'copy' utility would be commanded by input file copy output file To make a pipeline, command operators could be stacked up. Thus, to sort input, paginate it neatly, and print the result offline, one would write input sort paginate offprint In today's system, this would correspond to sort The idea, explained one afternoon on a blackboard, intrigued us but failed to ignite any immediate action. There were several objections to the idea as put: the infix notation seemed too radical (we were too accustomed to typing 'cp x y' to copy x to y); and we were unable to see how to distinguish command parameters from the input or output files. Also, the one-input one-output model of command execution seemed too confining. What a failure of imagination! Some time later, thanks to McIlroy's persistence, pipes were finally installed in the operating system (a relatively simple job), and a new notation was introduced. It used the same characters as for I/O redirection. For example, the pipeline above might have been written sort The idea is that following a '> ' may be either a file, to specify redirection of output to that file, or a command into which the output of the preceding command is directed as input. The trailing '>' was needed in the example to specify that the (nonexistent) output of opr should be directed to the console; otherwise the command opr would not have been executed at all; instead a file opr would have been created. The new facility was enthusiastically received, and the term 'filter' was soon coined. Many commands were changed to make them usable in pipelines. For example, no one had imagined that anyone would want the sort or pr utility to sort or print its standard input if given no explicit arguments. Soon some problems with the notation became evident. Most annoying was a silly lexical problem: the string after '> ' was delimited by blanks, so, to give a parameter to pr in the example, one had to quote: Second, in attempt to give generality, the pipe notation accepted '< ' as an input redirection in a way corresponding to '>'; this meant that the notation was not unique. One could also write, for example, opropr> The pipe notation using '<' and '>' survived only a couple of months; it was replaced by the present one that uses a unique operator to separate components of a pipeline. Although the old notation had a certain charm and inner consistency, the new one is certainly superior. Of course, it too has limitations. It is unabashedly linear, though there are situations in which multiple redirected inputs and outputs are called for. For example, what is the best way to compare the outputs of two programs? What is the appropriate notation for invoking a program with two parallel output streams? I mentioned above in the section on I/O redirection that Multics provided a mechanism by which I/O streams could be directed through processing modules on the way to (or from) the device or file serving as source or sink. Thus it might seem that stream-splicing in Multics was the direct precursor of UNIX pipes, as Multics I/O redirection certainly was for its UNIX version. In fact I do not think this is true, or is true only in a weak sense. Not only were coroutines well-known already, but their embodiment as Multics spliceable I/O modules required that the modules be specially coded in such a way that they could be used for no other purpose. The genius of the UNIX pipeline is precisely that it is constructed from the very same commands used constantly in simplex fashion. The mental leap needed to see this possibility and to invent the notation is large indeed. High-level languages Every program for the original PDP-7 UNIX system was written in assembly language, and bare assembly language it was-for example, there were no macros. Moreover, there was no loader or link-editor, so every program had to be complete in itself. The first interesting language to appear was a version of McClure'S TMG11 that was implemented by McIlroy. Soon after TMG became available, Thompson decided that we could not pretend to offer a real computing service without Fortran, so he sat down to write a Fortran in TMG. As I recall, the intent to handle Fortran lasted about a week. What he produced instead was a definition of and a compiler for the new language B. B was much influenced by the BCPL language; other influences were Thompson's taste for spartan syntax, and the very small space into which the compiler had to fit. The compiler produced simple interpretive code; although it and the programs it produced were rather slow, it made life much more pleasant. Once interfaces to the regular system calls were ma de available, we began once again to enjoy the benefits of using a reasonable language to write what are usually called 'systems programs': compilers, assemblers, and the like. (Although some might consider the PL/I we used under Multics unreasonable, it was much better than as- sembly language.) Among other programs, the PDP-7 B cross-compiler for the PDP-11 was written in B, and in the course of time, the B compiler for the PDP-7 itself was transliterated from TMG into B. When the PDP-11 arrived, B was moved to it almost immediately. In fact, a version of the multiprecision 'desk calculator' program de was one of the earliest programs to run on the PDP-11, well before the disk arrived. However, B did not take over instantly. Only passing thought was given to rewriting the operating system in B rather than assembler, and the same was true of most of the utilities. Even the assembler was rewritten in assembler. This approach was taken mainly because of the slowness of the interpretive code. Of smaller but still real importance was the mismatch of the word-oriented B language with the byte-addressed PDP-11. Thus, in 1971, work began on what was to become the C language. The story of the language developments from BCPL through B to C is told elsewhere, and need not be repeated here. Perhaps the most important watershed occurred during 1973, when the operating system kernel was rewritten in C. It was at this point that the system assumed its modern form; the most far reaching change was the introduction of multiprogramming. There were few externally visible changes, but the internal structure of the system became much more rational and general. The success of this effort convinced us that C was useful as a nearly universal tool for systems programming, instead of just a toy for simple applications. Today, the only important UNIX program still written in assembler is the assembler itself; virtually all the utility programs are in C, and so are most of the applications programs, although there are sites with many in Fortran, Pascal, and Algol 68 as well. It seems certain that much of the success of UNIX follows from the readability, modifiability, and portability of its software that in turn follows from its expression in high-level languages. Conclusion One of the comforting things about old memories is their tendency to take on a rosy glow. The programming environment provided by the early versions of UNIX seems, when described here, to be extremely harsh and primitive. I am sure that if forced back to the PDP-7 I would find it intolerably limiting and lacking in conveniences. Nevertheless, it did not seem so at the time; the memory fixes on what was good and what lasted, and on the joy of helping to create the improvements that made life better. In 10 years, I hope we can look back with the same mixed impression of progress combined with continuity. Acknowledgements I am grateful to S. P. Morgan, K. Thompson, and M. D. McIlroy for providing early documents and digging up recollections. Because I am most interested in describing the evolution of ideas, this paper attributes ideas and work to individuals only were it seems most important. The reader will not, on the average, go far wrong if he reads each occurrence of 'we' with unclear antecedent as 'Thompson, with some assistance from me.' Dennis lrf. Ritchie, Computing Science Research Center, AT&T Bell Laboratories, 600 Mountain Ave., Murray Hill, NJ 07974. Ritchie and Thompson were the chief developers of the UNIX System, and co-authored the original paper describing UNIX which was published in 1974 in Comm. Assoc. Compo Mach. ---------------- Entrevista con Ritchie y Thompson ///////////////////////////////// Transcripción de una entrevista entre Microsystems (Mark y Chris) a Dennis Ritchie y Ken Thompson, realizada en AT&T Murray Hill, Nueva Jersey, el 1 de agosto de 1984. Mark: Nos gustaría conocer, desde su perspectiva, varios aspectos de UNIX que difieren de lo que hemos oído y leído. En particular, cuestiones generales, como cuál cree que será el impacto (en ambos sentidos) de la expansión de UNIX al mundo comercial, y aspectos internos más específicos, como la estructura de archivos y directorios. Por ejemplo, aún no entiendo del todo la diferencia entre UNIX Versión 7, UNIX System III y UNIX System V en cuanto a mejoras implementadas, como la protección de archivos para evitar que los i-nodos se bloqueen. Trabajé en un proyecto de desarrollo con la Versión 7, y cada dos por tres el sistema se colgaba. No podíamos simplemente abortar o apagar la máquina sin cerrarla de forma ordenada; el sistema simplemente se colgaba, y a menudo se llevaba consigo muchos i-nodos. Dennis: Bueno, allí intervienen dos cosas. Una es que pueden haber existido bugs, ya sea en el hardware o posiblemente en el software, que simplemente podrían causar fallos. Los cambios que se han realizado tienen que ver con el estado en el que se encuentran las cosas cuando se produce un fallo, y en realidad no se trata de un cambio estructural: los datos en el disco son idénticos; simplemente el sistema se ha tornado más cuidadoso en lo que respecta al orden en que realiza las operaciones. Ken: Los sistemas antiguos tenían una caché de búferes (un conjunto de búferes) y las operaciones de entrada/salida (E/S) se completaban en los búferes ante cualquier solicitud de los usuarios o del sistema para mantener su estructura interna, como directorios y demás de manera tan sólo lógica; los datos se almacenaban en los búferes (que se denominaban bloques o simplemente cachés en el disco); luego, en algún momento aleatorio -cuando se presentaba la oportunidad- se producía finalmente la E/S física... Mark: O cuando ocurría algo que provocaba algún tipo de volcado de bufer... Ken: Sí, normalmeente se producían ante cualquier cosa que provocara que se sobrescribieran. Por ejemplo, se usaban mucho los búferes, y al reutilizarlos, se borraba el contenido anterior antes de volver a etiquetarlos. Los cambios posteriores a los que creo que te refieres tenían como objetivo mantener la coherencia estructural del sistema, reasegurar los directorios, i-nodos y demás, ordenando explícitamente el 110 físico, en lugar de dejarlos a las riendas del azar y al tráfico de datos. Mark: ¿Cómo se hacía eso? Ken: Al crear o eliminar un archivo, simplemente se asegura de que el directorio se actualice antes que lo haga el archivo, porque se encuentra reasignando un archivo antiguo. Y al vaciar y liberar los bloques, se asegura de que la estructura de archivos esté escrita antes de liberar los bloques. Dennis: Cuando se crea un bloque indirecto, por ejemplo, hay un i-nodo que apunta a un bloque que apunta a otro bloque. Así que, asegurándose de no escribir el i-nodo a través de un puntero al bloque indirecto antes de que este se haya creado, se impide obtener un puntero defectuoso en caso de que exista una falla de sistema justo en ese momento. En cambio, si ya se ha escrito el bloque indirecto y se lo ha guardado en disco, podrá actualizar el i-nodo. De esta forma, incluso si el sistema falla, puede que se pierda parte del archivo, pero no se habrá creado una estructura defectuosa. Se trata simplemente de... de hacer un sistema que esté atento y... Ken: ...de tener cuidado (risas). Dennis: Bueno, en realidad, incluso se trata de considerar la mera posibilidad de que todo se cuelgue en este punto, e intentar —en la medida de lo posible— mitigar las cosas en un orden que, si el sistema se detuviera, mantuviera la coherencia del disco. Mark: Para preservar la integridad de los datos... Dennis: Sí, e incluso con las modificaciones realizadas, es imposible lograrlo por completo. UNIX no pretende ser un sistema transaccional, uno que confirma y revierte transacciones, etc. Con un cuidado razonable, sin embargo, se puede elevar considerablemente su fiabilidad. Aún así, en lo que respecta a fallos y pérdida de datos, también es posible que existan bugs en algún eslabón de la cadena: en el hardware de la CPU, en el disco duro o en el propio sistema operativo. Tradicionalmente, UNIX exige mucho de las máquinas, en el sentido de que realiza operaciones que otros sistemas no hacen... Ken: ...de forma muy asíncrona: produce muchos procesos y mucha conmutación entre los mismos. Antiguamente, DEC carecía de un sistema comparable, y quizás el 50 % de las CPU en las que se instalaba UNIX -que habían estado ejecutando algún sistema operativo de DEC- simplemente eran reacias a compatibilizar con UNIX. Quiero decir, habría grandes partes de la CPU que nunca habrían funcionado en toda su vida, como la gestión de memoria... Mark: ...¿se debía a que las CPUs jamás fueron depuradas correctamente? Ken: Sí. Y en los sistemas antiguos, el Unibus era mediocre... la E/S, las reflexiones, los ángulos, etc., desde el punto de vista de la ingeniería eléctrica, eran desastrosos. Mark: ¿Qué opinas de los portados a las nuevas CPU, como algunas de las microcomputadoras? De hecho, me he preguntado si alguna vez pensaron si nosotros, los inconformistas del mundo de las microcomputadoras, seríamos capaces de hacer funcionar UNIX en ellas. Dennis: Lo interesante, es que durante la mayor parte de su existencia, UNIX corría en minicomputadoras, considerablemente más pequeñas que los mainframes actuales, y fue precisamente ese minicomputadora la que se convirtió en la solución. Ken: Contaba con 8 KB de memoria de 12... no, de 18 bits. Dennis: El PDP-11, el primero, tenía 24 KB. Ken: Pero no sé. UNIX no funciona bien en las microcomputadoras tradicionales de 8 bits. Solo las máquinas de 16 bits pueden ejecutarlo correctamente. Mark: Ya ni siquiera consideramos las máquinas de 8 bits. Chris: Ni siquiera sabía que alguien hubiera intentado portar UNIX a una máquina de 8 bits. Dennis: Creo que no ha habido ningún portado propiamente dicho. Ken: Sí que ha habido algunas... IDRIS funciona en él, ¿no? Mark: ¿Has colaborado con Whitesmiths en el desarrollo de IDRIS? ¿Les has ayudado, te han contactado o algo así? Dennis: No. De hecho, fueron de los primeros desarrolladores independientes de compiladores de C y cosas por el estilo. Bueno, claro, también está Yourdon. Y precisamente por ser el primero, y por haber estado aquí [en Bell Labs], fueron extremadamente cuidadosos para evitar problemas de licenciamiento. Y creo que eso le perjudicó, ya que la biblioteca de su compilador de C no recurría a llamadas de E/S compatibles con el estándar C. Creo que pensaron que se meterían en problemas. No creo que los hubiesen tenido, puesto que el material publicado jamás ha sido un secreto comercial. Creo que ha cambiado, de hecho, y ahora usa software compatible. En realidad, la comunicación con nosotros fue mínima. De hecho, Brian [Kernighan] se quejó de que estaban desarrollando todas sus herramientas de software en Pascal y que no se comunicaban lo suficiente. Pero esa es otra historia. Mark: ¿Qué tan involucrado estaban con la gente de aquí, en los Bell Labs, que desarrollaban compiladores de C y otros sistemas UNIX? Dennis: La gente que se dedica al desarrollo relacionado con UNIX se mudó a unas instalaciones en Summit, a un par de kilómetros de aquí. Antes estaban todos aquí. Mark: Eso es un desarrollo nuevo... Ken: System V. Dennis: Sí, en efecto, elllos son los desarrolladores, con la gente que está haciendo cosas nuevas. Mark: ¿Qué relación tienen con ellos? Dennis: Organizacionalmente, prácticamente ninguna. Nosotros estamos en el área de investigación, ellos en el área de desarrollo informático. En cuanto a las relaciones, hay mucho intercambio, con quejas sobre el rendimiento por nuestra parte y demás. En cuanto a los detalles, revisamos alguna parte de un compilador y se los enviamos, o escribimos algún software nuevo y se lo damos. En cierta medida, eso ha sido así desde que empezaron. Más aún, dado que el jefe del departamento que se ocupa de los compiladores también era jefe aquí, decidió que quería... Ken: Quería conectar... Dennis: Sí, conectar cosas y llevarlas a cabo. En lo que respecta al desarrollo del sistema operativo, en general, hay menos intercambio de ideas. Parte de la razón es que nos hemos distanciado bastante en el desarrollo. De hecho, nosotros en Investigación tenemos nuestro propio sucesor del UNIX de 7ma. Edición, y continuamos esa rama. Ellos tienen System V. Mark: ¿Lo consideran una mejora de System V o como una versión diferente de System V? Dennis: Nuestro sistema jamás será un producto. Mark: Ya veo. Quieres decir que lo utilizan para la investigación. Dennis: Exacto. Ken: Ellos son de investigación, y nosotros somos oficiales. Dennis: Así que toman ideas. Quiero decir, también tienen el código, pero la cuestión es que no es un sistema completo. En cuanto a lo de distribuir un nuevo sistema por nuestra parte, existen dos buenas razones para no hacerlo: primero, no queremos; es una cantidad de trabajo increíble para compilar todo. Simplemente no es investigación. Y segundo, sería competir con System V. Así que -de mutuo acuerdo- no lo hacemos. Es posible que haya algunas licencias muy limitadas para personas con las que eventualmente nos gustaría trabajar, pero no estamos seguros de quiénes podrían ser y, de hecho, tendría que ser de forma privada. Mark: La actividad de poner UNIX en funcionamiento en el mundo de los usuarios es bastante diferente de lo que realmente te interesa, ¿no? Ken: Mmm. Nuestro trabajo es la investigación. No está orientado a sacar un producto; no tenemos dirección, ni administración propiamente dicha, nada de lo que se parezca a ello. Compartimos un entorno de pruebas. Ya sabes, lo que queramos hacer. Dennis: Y de vez en cuando salen cosas buenas del Laboratorio. UNIX es un caso un tanto inusual, porque, bueno, para empezar, no nos tomamos la molestia de crear una distribución que pudiera tener una amplia difusión. Además esto ocurrió en un momento en que la empresa no estaba en condiciones [legales] de comercializarlo como producto, así que cobraban licencias. Había gente que quería subir las tarifas de licenciamiento lo máximo posible, solo para ver si podíamos ganar el mayor dinero posible, pero en realidad no podía ser un negocio, en ninguno de los sentidos de la palabra. Y, por supuesto, tampoco tenía soporte como producto. Chris: ¿Dirías, entonces, que...? ¿UNIX se desarrolló más que nada como herramienta de investigación? Ken: Bueno, en realidad jamás hubo un propósito directo, sino más bien el intento de crear algo que pudiéramos usar por nosotros mismos. Dennis: Definitivamente no se diseñó como un producto. Mark: Pero, Dennis, ¿no comentaste por teléfono la semana pasada que también se diseñó para el desarrollo de un programa de ajedrez? (Risas). Ken: Para ser honesto, se desarrolló mucho antes del trabajo con el software ajedrecístico. UNIX se diseñó para programar, y para cualquier otra cosa que se nos ocurriera hacer. En aquél entonces, me interesaban más los lenguajes de programación que los sistemas de cómputo. El hecho de crearlo alteró eso un poco. Mark: ¿Qué opinas del debate actual sobre UNIX, es decir, sobre los dos puntos: el bloqueo de archivos/registros y las operaciones en tiempo real? Hemos escuchado muchas quejas del mundo "comercial" que aducen que UNIX no es un sistema operativo en tiempo real. Pero mucha gente parece no entender qué significa eso, ni cómo no podría serlo, considerando que AT&T debe ser la principal corporación en uso de cómputo de tiempo real, quizás del mundo. Ken: Pero UNIX no conmuta teléfonos (risas). [N.d.T. El chiste parece venir del hecho que para 1984, UNIX corría el principal programas de conmutación telefónica en las conmutadoras digitales ESS-5 de la AT&T] Dennis: La razón por la que no hay funciones en tiempo real —o mejor dicho, pseudo-tiempo real— en UNIX es, básicamente, que nunca se nos ocurrió ninguna aplicación donde quisiéramos implementarlas. Lo que se incluyó fue lo que... Ken: ...necesitábamos. No se desarrolló como un producto. Desde el principio, hubo grupos de personas que decían que necesitaban discos ocultos, procesamiento transaccional y otras cosas. Pero esas cosas nunca nos interesaron, así que nunca las metimos. Mark: Ya veo. Bueno, hay un aspecto interesante en la discusión, debido a la diversidad de personas involucradas. Actualmente, existe una estructura jerárquica en los grupos de personas involucradas con UNIX: primero, están los investigadores —ustedes— que concibieron y crearon UNIX; luego, un núcleo de personas —principalmente estudiantes universitarios y recién graduados— que aprendieron UNIX simplemente porque era el sistema operativo que tenían en la universidad. Son los "gurús" y los "hackers", personas con una conexión emocional con el sistema porque es lo que conocen; y, por debajo de estos, hay otro nivel: los administradores de sistemas, personas que han trabajado con otros sistemas operativos y ahora están aprendiendo UNIX. Finalmente, está el sector comercial, que está adoptando UNIX por su portabilidad y otras ventajas. Ahora bien, existe una gran controversia entre el sector comercial y el segundo nivel, que argumenta: "Pero el bloqueo de registros y el procesamiento en tiempo real no tienen cabida aquí, ya que destruirían la integridad del núcleo y la filosofía de UNIX". Dennis: Bueno, existen razones técnicas... Ken: Creo que System V tiene bloqueo de registros. Tienen algún tipo de controlador, ¿no? Dennis: Tienen mecanismos para ello. Hay semáforos, con los que, por acuerdo, se puede lograr el bloqueo de registros; y Berkeley tiene bloqueo de archivos. En realidad, hay dos cosas aquí. El tiempo real es bastante difícil de implementar de forma generalizada, simplemente porque es prácticamente incompatible con los requisitos de un sistema de tiempo compartido. Chris: Lo siento, pero ¿acaso un sistema de tiempo compartido no es inherentemente un sistema de tiempo real? ¿Qué quieres decir entonces con un sistema de tiempo real? Este término resulta confuso para mucha gente. Dennis: Lo que quiero decir con un sistema de tiempo real es aquel en el que el sistema se compromete a ofrecer algún tipo de garantía sobre el rendimiento para tareas específicas. Obviamente, el sistema tiene que mostrar los caracteres a medida que se escriben, y si no lo hace con suficiente rapidez, se producen quejas. Así que, en ese sentido, es tiempo real. Pero esto no garantiza que una tarea reciba 3/5 del poder de cómputo de la CPU. Tampoco UNIX promete que, si una tarea requiere servicio, lo recibirá en un determinado número de milisegundos. No es imposible diseñar e implementar una función así, pero en realidad es básicamente incompatible con UNIX, sobre todo si se intenta hacerlo de forma general. Obviamente, si se tiene un dispositivo específico que requiera o transmite datos a una velocidad determinada, se puede crear un controlador y lograr que funcione de dicha manera. No obstante, hacerlo de forma general es mucho más difícil. Mark: El tema de hacerlo de forma general plantea un problema. Supongamos que se desea escribir un programa que muestre información en una videoterminal con direccionamiento por cursor, y que se quieran actualizar algunos campos de información mientras el programa está en ejecución. El control del cursor permite formatear la pantalla para actualizar solo los campos sin volver presentar las cadenas de texto que los rodean y ya están escritos. Ahora bien, cuando tienes acceso directo a los controladores de E/S, tanto en CP/M como en MS-DOS... Dennis: Ese es el problema. Es decir, el sistema se diseñó para que ambos tipos de E/S fueran iguales; esa era la idea. El problema surge cuando tienes acceso directo a los controladores de E/S, porque entonces te quedas atascado con ellos. Ken: Y también existen todo tipo de números y cosas raras integradas. Dennis: Tamaños de bloque, por ejemplo. Mark: ¿Qué hicieron con respecto a la degradación? ¿Qué opinan del rendimiento del sistema cuando empezaron a trabajar en ello? Porque, al generalizar, el rendimiento del sistema se ve afectado. Ken: Creo que, en general, las cosas han mejorado en lugar de empeorar. Existe una forma correcta y una incorrecta de hacer las cosas, y esta última es incorrecta. Si lo haces de forma genérica y surge un problema —si no es lo suficientemente rápido—, entonces buscas la manera de que lo sea, porque tener el control total de los controladores es erróneo. Dennis: En realidad, las cosas están mejorando. Tengo la impresión de que la gente está empezando a generalizar y a retroceder en esa dirección. Mark: Empiezan. Pero aún tenemos tres, cuatro, incluso cinco tipos de opciones abiertas, dependiendo del compilador, para adaptarnos a diferentes requisitos específicos; es decir, incluso en los compiladores de C, las cosas no funcionan bien si solo usas la forma generalista que se proporciona por defecto. Simplemente no siempre puedes hacer que haga lo que quieres. Es posible que el compilador realice conversiones automáticas de CR/LFs a LFs, o viceversa, cuando la aplicación necesita recibir cada bit completo. Cosas así. Ken: Normalmente, esos son síntomas de intentar seguir una retrocompatibilidad con elementos anteriores, algo que nunca sentimos la necesidad. Lo diseñamos nosotros. No necesitámos ser compatibles con aspectos previos. No teníamos limitaciones. Mark: ¿Qué hay del desarrollo futuro a partir de lo que han escirto? Ken: Bueno, ahora existe una enorme inercia en el software detrás de UNIX. El sistema en sí es solo una pequeña parte. Todos los subsistemas (los lenguajes, programas, etc.) representan probablemente entre 10 y 100 veces más esfuerzo, trabajo e inercia que el propio sistema UNIX. Mark: ¿Qué tamaño tenía el sistema inicialmente? Entiendo que ocupa unos 256 KB de memoria principal y un promedio de 7 MB de primitivas de disco; ese es el tamaño general que se considera para UNIX. Ken: Como se describe en el artículo de CACM —esa es la primera descripción pública— tenía 10.000... Dennis: ...líneas de código y unos 20.000 bytes de memoria. El primer PDP-11 que usamos durante un par de años tenía 24.000 bytes de memoria y un disco de medio megabyte. Por otro lado, el primer PDP-11 que conseguimos costaba unos 50.000 dólares, lo cual, para una minicomputadora, no era mucho en aquella época. Es decir, esto fue entre 1969 y 1970. Chris: En aquel entonces, lo único que se podía conseguir por menos era un PDP-8, que no era comparable, que era una minicomputadora realmente pequeña. Pero, entonces, ¿qué ocupaba la mayor parte? Ken: Una vez dentro, se ajusta el número de discos necesarios para el búfer del sistema. Hay un grupo de búferes que, si es mayor, es más eficiente. De hecho, se realizan menos operaciones de entrada/salida de disco; La E/S se realiza dentro de la caché del búfer. Hay sistemas que tienen literalmente megabytes de búfer. El número de búferes es un parámetro que se especifica. Se pueden tener tantos como se quiera; con dos es suficiente, pero... Dennis: Creo que el sistema estándar que estamos usando asigna búferes en función de la cantidad de memoria principal disponible. Es aproximadamente un 10 o 12 por ciento de la memoria principal. Ken: Y asigna búferes en función del número de usuarios. Es decir, del número de dispositivos de E/S. Dennis: Pero además hay dos cosas. El tamaño del texto (el tamaño del código fuente del programa) del sistema ha aumentado notablemente. System V añadió un montón de funciones que varias personas querían (y podían usar), pero que en realidad no estaban muy bien pensadas ni eran coherentes. Ya saben, diferentes funciones para hacer esto, aquello y lo otro; se añadieron porque había clientes que las reclamaban y gente que las quería... Mark: ¿Te refieres a soluciones comerciales? Dennis: No, no era algo comercial, era principalmente demandas internas. Ken: El System V surgió del System III; las adiciones fueron versiones internas, dentro del sistema, y ​​se mantuvieron dentro del sistema. Por eso es que faltó el System IV. Hubo una política de contar, básicamente, con tres sistemas de desarrollo. Está el sistema que mantienen internamente —llamémoslo System IV—. Hay uno en el que trabajan experimentalmente, en el grupo de desarrollo —ese es el System V—; y están los Releases públicos, lanzados comercialmente con posterirdad al System III. Algo así como "mientras usamos el IV, distribuimos el III..." Mark: ...y experimentamos con el V... Ken: Exacto. Y luego, cuando se decidieron a lanzar UNIX como producto, lo actualizaron, de modo que el externo y el interno coincidieran, y el System IV desapareció. La versión System IV era interna, como producto, y luego, cuando salió la versión System V, se decidió omitir la versión IV como producto externo y quedarse solo con la System V. Mark: Uno de los rumores que circulan es que el System III surgió de la 7ma Edición, con una mejora importante para solucionar el problema de la fragilidad de la estructura de directorios de archivos, y que, cuando AT&T decidió lanzarlo como producto, decidieron lanzar una nueva versión, la System V, y que las personas que trabajaban en la versión System III no tuvieron tiempo para trabajar en la System V, así que un nuevo grupo de desarrollo comenzó con la 7ma. Edición de forma independiente. Dennis: No, la división entre nosotros y el área de desarrollo... El hecho de que dejaran de seguirnos y de tomar nota de todo lo que hacíamos ocurrió antes de UNIX 7ma. Edición. Así que, la rama principal del sistema no solo era anterior a la System III, sino también a la 7ma. Edición de UNIX. No es que hayamos dejado de comunicarnos; simplemente, la colaboración, que era muy activa, cesó. El System III cuenta con una estructura de control de E/S para terminales muy diferente. El grupo de desarrollo decidió rehacerla, y nosotros decidimos no hacerlo. Por lo tanto, UNIX System V es su sistema sucesor. Mark: ¿Cuáles son las diferencias, específicamente? Ken: La E/S para terminal se llama de forma diferente, con parámetros distintos. Dennis: El suyo es lógicamente mucho más limpio. También es más complejo: tiene muchos más bits y mucho más "estados". Han intentado separar la entrada y la salida, de modo que los estados de lectura y escritura del terminal se vean algo compartimentados. Lo han desunido, por así decirlo. Al comparar UNIX 7ma. Edición con UNIX System V, una diferencia radica en el modo sin procesar frente al modo procesado. El modo procesado ofrece funciones como retorno de carro/salto de línea, borrado y eliminación de caracteres, agrupación de líneas, etc. En UNIX System V, existen otras opciones. Por ejemplo, se puede decidir de forma independiente si se desea el procesamiento de borrado y eliminación de caracteres y las secuencias de retorno de carro/salto de línea, así como si se desea recuperar el texto línea por línea o carácter por carácter. En cierto modo, hay detalles que no me convencen: no me gusta que sea más complejo, pero, lógicamente, supone una mejora respecto al nuestro. En la práctica, sin embargo, ha resultado ser un inconveniente. En realidad, solo existen dos áreas con diferencias significativas entre las versiones de UNIX, y esta es una de ellas. Para decirlo de manera simple, al realizar alguna acción para controlar la terminal, hay que hacerlo de forma diferente en System V que en las versiones derivadas del UNIX de 7ma. Edición, incluida el UNIX de Berkeley [N.d.T. se refiere al BSD]. Esa es una de las diferencias. El otro tema tiene que ver con las declaraciones externas en C. El lío del estándar de C... bueno, déjenme explicarles: se trata de si se puede declarar la misma variable externa en dos rutinas diferentes sin tener que usar "extern" en una de ellas. Ken: Una clara distinción entre referencia y definición. Dennis: Todo el asunto es muy, muy complicado, porque el manual —el "Libro Blanco"— dice que lo que decidió UNIX System III es correcto, y nunca lo cambiamos. Mantuvimos la versión extendida, y la gente siguió dependiendo de ella, aunque el manual diga que no se debe hacer. UNIX System III dijo: "Vamos a imponer esto". En la práctica, eso se ha revertido. En UNIX System V, Release 2 —que es la versión actual— las reglas vuelven a ser las mismas que teníamos. Esos son los dos puntos principales. Mark: ¿Sabes por qué se tomó esa decisión? Ken: Tiene que ver, principalmente, con los mainframes de IBM y el acceso a sus cargadores. La forma de declarar variables externas para los cargadores de IBM es mediante un bloque común (como en los cargadores Fortran estándar), lo que implica un número arbitrariamente pequeño. El lenguaje C se modificó para permitir implementaciones en entornos que no fueran UNIX. En nuestro grupo, simplemente no insistimos en que así debía ser. El grupo de desarrollo, sobre todo al realizar adaptaciones a otras máquinas, ... Dennis: ...y, también por razones intelectuales, decidió seguir el estándar. Lo consideraron mejor por dos motivos: primero, porque era un mejor estilo de programación seguir las instrucciones del manual -el "libro blanco"- ya que era la norma. Esto causó bastantes problemas, en varios sentidos (programas que tuvieron que modificarse), pero no por falta de motivación. En cualquier caso, ese tema ya está prácticamente zanjado, puesto que la norma actual ha vuelto a la original. Chris: Parece que existe un movimiento, al menos entre los grupos de usuarios, para desarrollar "estándares" para UNIX. No sé si esto tiene que ver con estilos de programación o con formas específicas de hacer las cosas. ¿Qué opinas sobre el desarrollo de estos estándares? Ken: Bueno, el grupo que impulsa los estándares es /usr/group, y sus preocupaciones son comerciales. Quieren poder escribir software que se ejecute en UNIX y poder decir: "Si seguimos el estándar, y quienes implementan UNIX también lo siguen, entonces todo será compatible". Es algo impulsado por el mercado. Ese es su objetivo, y en ese sentido tienen razón. Para un mercado comercial, necesitan estándares a los que adherirse. Entiendo que quienes producen disquetes para CP/M tienen que producir 10 o 15 versiones diferentes, y la gente de UNIX no quiere que eso suceda. Quieren un estándar para poder vender una sola versión de su software que funcione en todas partes. [N.d.T. el estandar POSIX aparecería en 1988] Dennis: Por otro lado, tienen que ser bastante conservadores. En realidad no están tratando de resolver los problemas de hardware, porque hay demasiados grupos de interés. Básicamente, hay dos grupos de personas. Una es la gente del System V, y la otra es la gente de UNIX de Berkeley 4.1 y 4.2. Esta última no es numéricamente gigantesca, pero son intelectualmente es muy, muy importantes, puesto que incluyen a todas las Universidades y sus facultades. El /usr/group no puede simplemente llegar y decir: "Tiene que ser así", porque hay demasiada gente que lo querría de otra manera. Por eso, están intentando anticiparse lo máximo posible y registrar principios que indiquen "Así son las cosas" en la mayor área posible. En otras palabras, están intentando descubrir estándares, no crearlos. Ken: Están intentando encontrar reglas que permitan convivir con los sistemas existentes. Dennis: Y, en la medida en que lo están haciendo, AT&T parece estar bastante de acuerdo. Lo mismo ocurre, por cierto, con el estándar C. La semana que viene se reúnen y están procediendo con mucha cautela. La mayoría de los cambios que han hecho en el manual son básicamente aclaraciones. Mark: Todavía tengo muchas preguntas, pero parece que ya están todo listo para las fotos.