Está en la página 1de 33

Servidores II

TAREA Sistemas Operativos 2004 1.- Cuales son las dos funciones principales de un Sistema Operativo? La primera funcin es la gestin de las operaciones bsicas de hardware. El control de entrada y salida, espacio de almacenamiento, equipos de deteccin de error, y la gestin de almacenamiento son slo algunas de las responsabilidades de la O / S o el sistema operativo. La segunda funcin es la gestin y la interaccin con el software de aplicaciones. Se hace cargo de las tareas de impresin y almacenamiento de datos. 2. Que es la multiprogramacin? Es cuando muchos programas que no estn relacionados unos con otros pueden residir en la memoria de una computadora y tomar turnos usando la unidad central de procesamiento, cuando usamos Windows, Unix o Linux hemos experimentado un entorno de multiprogramacin porque estos sistemas pueden ejecutar un largo numero de programas de usuario aparentemente de manera simultanea en una sola unidad central de procesamiento. La seccin que permite la multiprogramacin en un sistema operativo se denomina Kernel (software que se en carga de las tareas, decidir cual tarea correr en un momento dado) 3. Una de las razones por las que las Interfaces Graficas de Usuario (GUI) fueron adoptadas lentamente, fue por el costo del hardware necesario para soportarlas. Cuanta RAM de video se necesita para una terminal modo texto de 80x25 (columnas, lneas)? 4000 bytes de RAM de vdeo.

Cuanta para una pantalla grafica de 1024x768 con 24 bits de profundidad de color? 2MB de RAM nicamente para contener la imagen. En 1980 el costo de la memoria , Cuanto cuesta en la actualidad? memorias RAM DDR2 4200 la de 512MB $500 memorias RAM DDR2 4200 la de 1GB $800 G.skill Ripjaws X 8gb Ddr3 2133mhz Pc3 17000 $1990

Pgina

Servidores II

4. Cuales de las siguientes instrucciones deberan permitirse en modo kernel? Deshabilitar todas las interrupciones Leer el Reloj de Tiempo Real (RTC) Escribir el RTC Cambiar el mapa de memoria. 5. Un microprocesador tiene un pipeline de 4 etapas. Todas las etapas demoran 1nseg en procesar. Cuantas instrucciones por segundo (IPS, KIPS, MIPS) puede ejecutar este micro?

6. La MMU normalmente compara la direccin virtual entrante con el Registro Limite, provocando una excepcin cuando la primera se excede. Un diseo alternativo consiste en primero sumar la direccin virtual al Registro Base y despus comparar el resultado con la direccin fsica del Registro Limite. Son equivalentes estos mtodos? No , porque el Kernel debe coordinarse con el hardware = traduccin direcciones virtuales a fsicas. 7. Cuando un programa de usuario efectua un SysCall para leer o escribir un archivo en disco, este provee el archivo necesita, un puntero a un buffer de datos y la cantidad de datos. Entonces, el control pasa al SO, el que llama al driver apropiado. Supongamos que el driver le da la orden al disco y termina cuando llega una interrupcion. En caso de una lectura, obviamente el programa que llamo tiene que permanecer bloqueado (pues no hay datos). ?Es lo mismo para una escritura a disco?, es decir, ?Necesita bloquear el programa que pidio la escritura hasta que se complete la transferencia?

Pgina

Servidores II

8. De condiciones de falla para cada uno de los SysCall que siguen: fork(), exec() y unlink().

Exec()= Retornan -1 si hay error. Si se ejecuta con xito no devuelve ningn valor dado que el cdigo de programa se sustituye por el del nuevo programa y se eliminan todas las variables del programa. fork()= fork causa la creacin de un nuevo proceso copia (casi exacta) del proceso padre. RETORNO si la llamada tiene xito retorna: al proceso hijo pid del hijo al proceso padre si fracasa devuelve -1 unlink()= Borra una entrada en la tabla de un directorio. pathname representa un fichero ya existente cuya entrada se quiere borrar. Si se elimina la ltima entrada existente en algn directorio que hace referencia a un inodo concreto el sistema elimina el fichero de ese i-nodo. RETORNO Retorna 0 si no hay error y -1 si hay algn error. 9. Puede la siguente llamada a sistema retornar en count un valor menor que nbytes? Explicar. count = write(fd, buffer, nbytes) La llamada write escribe un nmero de bytes dado por count en el fichero cuyo file descriptor viene dado por fd. Los bytes a escribir deben encontrarse a partir de la posicin de memoria indicada en buf. RETORNO Retorna el nmero de bytes escrito o -1 si hay un error. 10. Indique la diferencia esencial entre un dispositivo de caracteres y uno de bloques. Dispositivos de bloque tienen un bfer para las peticiones, por lo tanto pueden escoger en qu orden las van a responder. Esto es importante en el caso de los dispositivos de almacenamiento, donde es ms rpido leer o escribir sectores que estn cerca entre s, que aquellos que estn ms desperdigados. Otra diferencia es que los dispositivos de

Pgina

Servidores II

bloque slo pueden aceptar bloques de entrada y de salida (cuyo tamao puede variar segn el dispositivo). Dispositivos de carcter pueden usar muchos o unos pocos bytes como ellos quieran. La mayora de los dispositivos del mundo son de carcter, porque no necesitan este tipo de buffering, y no operan con un tamao de bloque fijo. Se puede saber cundo un fichero de dispositivo es para un dispositivo de carcter o de bloque mirando el primer carcter de la salida de ls -l. Si es `b' entonces es un dispositivo de bloque, y si es `c' es un dispositivo de carcter. 11. Laboratorio 2 12. Tome un *nix personal (Linux, OpenBSD, MINIX, Darwin, etc.) que pueda romper sin problemas. Escriba un shell script que intente crear un numero ilimitado de procesos hijos y observe lo que sucede. Nota: no intente esto en un laboratorio de acceso publico. shell acta como un intermediario entre el sistema operativo y el usuario. 13. El comando strace da un registro (traza) de todas las SysCalls que llama el comando que le sigue. Obtenga las trazas de los siguientes comandos, tratando de identificar todos los SysCalls que producen (el comando man puede ayudar). 1. strace cat /etc/hosts 2. strace cat (CTRL-D puede ayudar a terminar) 3. strace echo 1 4. strace mozilla (busquese una silla comoda) Intente identificar patrones comunes que correspondan a codigos de inicializacion y terminacion de procesos.

Procesos e Hilos 1. Por que un hilo dejaria voluntariamente la CPU con un thread_yield si sabe que despues de esto puede que se quede sin CPU para siempre? Otra llamada comn relacionada con los threads es thread_yield, que permite que un thread abandone Voluntariamente la CPU para permitir que se ejecute algn otro thread. Tal llamada es importante ya que no existe ninguna interrupcin de reloj que d soporte al tiempo compartido como en el caso de los procesos.

Pgina

Servidores II

Por tanto para los threads es importante ser corteses y ceder voluntariamente la CPU de cuando en cuando para dar la oportunidad de que se ejecuten otros threads. Hay otras llamadas que permiten a un thread esperar a que otro thread termine algn trabajo, o a que un thread anuncie que ha terminado algn trabajo, etc. 2. En un sistema con hilos, hay un solo stack por hilo o un stack por proceso cuando se usan hilos en espacio de usuario? Y si se usan hilos a nivel de kernel? El ncleo mantiene una tabla de threads que sigue la pista de todos los threads en el sistema. Cuando un thread desea crear un nuevo thread o destruir uno que ya existe, hace una llamada al ncleo, que es el que se encarga efectivamente de su creacin o destruccin actualizando la tabla de threads del sistema. 3. Para el siguiente programa decidir que valores se pueden imprimir.

Pensar en el mismo codigo, solo que en vez de procesos tenemos hilos. Se imprime a, *ptr_b. Condiciones de Carrera 4. Dado el siguiente par de procesos que insertan datos en el spooler de impresion, donde cola es un espacio de memoria compartida y libre es una variable local a cada proceso.

1. Dar una planificacin o escenario que produce la prdida de un trabajo.

Pgina

Servidores II

Situaciones en las que dos o ms procesos leen o escriben en un rea de memoria compartida y el resultado final depende de los instantes de ejecucin de cada uno. Esto se soluciona impidiendo que ms de un proceso acceda simultneamente a las variables compartidas. Se soluciona garantizando la exclusin mutua.

2. Dar una planificacion o escenario que funciona correctamente. Imaginemos que nuestro directorio de spool tiene un nmero muy grande de entradas, numeradas 0, 1, 2, ..., cada una de ellas capaz de contener un nombre de fichero. Imaginemos tambin que se tienen dos variables compartidas, out, que apunta al siguiente fichero a imprimir, e in, que apunta a la siguiente entrada libre en el directorio. Estas dos variables pueden caber perfectamente en un fichero de dos palabras disponible para todos los procesos. En un cierto momento, las entradas de la 0 a la 3 estn vacas (al haberse imprimido ya los ficheros correspondientes) y las entradas de la 4 a la 6 estn ocupadas (con los nombres de los ficheros encolados para su impresin). Ms o memos simultneamente, los procesos A y B deciden cada uno de ellos mandar a la cola de impresin un fichero. 3. Cuantas planificaciones existen para estas 3+3 lineas de codigo? Cuantas son correctas y cuantas producen problemas? (determine el %) 5. Se tienen 2 procesos P0 y P1, P0 con N acciones atomicas y P1 con M acciones atomicas. Calcular cuantos escenarios posibles de ejecucion se pueden dar en un entorno concurrente. 6. Considere los procesos P0 y P1, con un valor inicial de x=0. Cuales son los valores finales de x?

7. Si ahora consideramos que x:=x+1 no es atomico a nivel de ensamblador y se compila en una secuencia de accesos a memoria y operaciones de la ALU, equivalentes al siguiente multiprograma. Cuales son los valores finales de x?

Pgina

Servidores II

7. Mostrar que agregando un re-testeo de lock=0 luego del busy waiting en metodo de la variable candado, no soluciona nada.

variable entera turno, inicializada a 0, indica a quien le corresponde el turno de entrar en la regin crtica y examinar o actualizar la memoria compartida. En un primer momento, el proceso 0 inspecciona turno, observa que vale 0 y entra en su regin crtica. El proceso 1 tambin se encuentra con que turno vale 0 y por lo tanto espera en un bucle vaco comprobando continuamente turno para ver cuando pasa a valer 1. La comprobacin continua de una variable hasta que contenga algn valor determinado se denomina espera activa (busy waiting). Usualmente debe evitarse, ya que derrocha tiempo de CPU. La utilizacin de la espera activa slo es apropiada cuando existan unas expectativas razonables de que la espera va a ser muy corta. Un cerrojo que utiliza espera activa se denomina un spin lock. 8. Mostrar que en alternancia estricta el proceso P0 puede impedir al P1 entrar a la CS aunque P0 este fuera de ella. Solucin de Peterson La Instruccin TSL (Test and Set Lock) 9. Deshabilitar interrupciones no funciona para regiones criticas anidadas (una dentro de la otra). Reescribir Begin/EndRegion para arreglar este problema. 10. Generalizar la alternancia estricta a 3 procesos. Generalizarla a n. 11. Demostrar de manera rigurosa que el algoritmo de Peterson no adolece del problema de progreso de la alternancia estricta. 12.Demostrar de manera rigurosa que el algoritmo de Peterson cumple con la propiedad de seguridad de la Region Critica (#proc_in_cs1).

Pgina

Servidores II

13. Sigue cumpliendo con la propiedad de seguridad el algoritmo de Peterson si intercambiamos las 2 primeras asignaciones de su BeginRegion? Demostrar o dar contraejemplo.

14. [Fin88, 8.12] Implementar un spin lock con TestInc. atomic function TestInc(var lock: integer):integer; result:=lock; lock:=lock+1; return result;

15. [Wol04][Tan02, 2.22] Implementar un spin lock con Swap. atomic procedure Swap(var v,w: integer); tmp:=v; v:=w; w:=tmp; Primitivas de sincronizacion 16. [Wol04] Dados 3 procesos P0, P1 y P2 que realizan las acciones A0, A1 y A2, poner P's y V's de semaforos antes y despues de las acciones para sincrinizarlos de manera tal que se ejecuten en secuencia A0,A1,A2. Especificar el/los valor/es inicial/es de el/los semaforo/s. 17. [Wol04] Implementar utilizando semaforos la Region Critica N-1, es decir dentro de la region critica puede haber a lo mas N-1 procesos. 18. [Tan02, 2.24] {Dificil} Implemente semaforos generales (el semaforo almacena valores arbitrarios) usando semaforos binarios (solo pueden valer 0 o 1). 19. [Fin88, 8.22] Implementar semaforos utilizando monitores. 20. [Tan02, 2.28] {Dificil} La sincronizacion en monitores usa variables de condicion y dos operaciones especiales, wait y signal. Una forma mas general de sincronizacion son las esperas por condiciones con auto-sealizacion, donde escribimos await CondicionBooleana para bloquear el proceso hasta que la condicion se cumpla. Por ejemplo el BeginWrite del problema de lectores y escritores se resume a escribirawait nr=0nw=0 dentro del monitor Claramente este esquema es mas general y abstracto que los monitores de Hoare y Brinch-Hansen, pero no se usan. ?Por que? Ayuda: pensar en la implementacion.

Pgina

Servidores II

22. [Tan02, 2.33] {Mediano} El problema de lectores y escritores puede ser formulado de varias formas respecto a cuando cada categoria de procesos puede empezar. De manera cuidadosa describa 3 variaciones distintas del problema, cada una favoreciendo (o desfavoreciendo) alguna categoria de procesos. Para cada variacion, especifique que sucede cuando un lector o escritor esta listo para acceder a la base de datos y que sucede cuando un proceso ha terminado de usar la base de datos. 23. [Tan02, 2.50] Tenemos un Bao Unisex donde puede haber de manera excluyente varones y mujeres. Mediante semaforos sincronice la entrada y la salida del bao por parte de varones y mujeres (EntraVaron,SaleVaron, EntraMujer, SaleMujer) de manera que se cumpla con el invariante nv=0 nm=0, es decir que no se mezclen. Este problema clasico de sincronizacion tambien se conoce con el nombre de problema del Puente de Una Via, y modela el acceso a un recurso que puede ser compartido por muchos procesos de un tipo o (excluyente) de otro. Planificadores 24. [Tan02, 2.35] Los planificadores RR mantienen una lista de todos los procesos listos para correr, donde cada proceso aparece exactamente una vez. ?Que pasaria si hubiera 2 o mas apariciones de un proceso en la lista de procesos para correr? ?Para que serviria? 25. [Tan02, 2.36] ?Se podra "medir" si un proceso es IO-bound o CPU-bound analizando el codigo fuente? (analisis estatico) ?Como se podria determinar en tiempo de ejecucion? (analisis dinamico) 26. [Tan02, 2.38] Mediciones realizadas en un sistema muestran que en promedio un proceso corre por T tiempo antes de bloquearse en I/O. Un cambio de proceso requiere de un tiempo S, denominado overhead (sobrecarga). Para un planificador RR con un quanto Q, dar una formula que mida la eficiencia de la CPU (tiempo usado en CPU/tiempo total) para los siguientes casos. a. Q = infinito b. Q>T c. S<Q<T d. Q=S e. Q casi 0

27. El planificador SPN (shortest process next) necesita de una medida de estimacion del tiempo de computo. Con un "factor de memoria" =1/2, donde los ultimos tiempos de corrida fueron: 40, 20, 40 y 15 msec. ?Cual es la estimacion del tiempo siguiente? 28. [Wol04] Dar un conjunto de procesos con sus tiempos de arribo y sus tiempos de uso de CPU, que muestren que SJF!=SRTN (shortest job first, shortest remaining time next). 29. [Fin88, 3.6] Completar la tabla para las siguientes politicas de planificacion: FCFS, SJN, SRTN, RR (Q=1), RR (Q=5).

Pgina

Proc Arribo UsoCPU

Servidores II

B C D E F G

2 3 7 8 15 25

6 10 1 5 2 7

Procesos e Hilos

1. Estudiantes trabajando en sus computadoras personales de un laboratorio envian sus archivos para imprimir hacia un server que hace spooling en el disco duro. Bajo que condiciones puede ocurrir un deadlock si el espacio de disco para el print spool esta limitado? Como se puede evitar dicho deadlock? Se reduce la probabilidad de interbloqueos del spool: o o Proporcionando un espacio en disco considerablemente mayor que el necesario, preferentemente con asignacin dinmica. Limitando los spoolers de entrada para que no lean ms trabajos cuando los archivos de spool llegan a cierto nivel de saturacin.

2. En el deadlock tipico de 2 procesos y 2 recursos, ?Cambiaria la situacion si se devuelven los recursos en otro orden? 3. Las trayectorias de recursos o diagramas de procesos bidimensionales tienen trayectorias horizontales o verticales. ?Cuando puede suceder que las trayectorias sean diagonales? 4. Que es un deadlock de un solo proceso? ?Porque esta situacion no causa ninguna preocupacion dentro del Sistema Operativo? Pueden ser utilizados solo por un proceso a la vez. Se le conceden al proceso que lo solicita y cuando son liberados voluntariamente por ese proceso se asignan a otro proceso solicitante. Ej. Impresora,escaner.

Pgina

5. Se puede estar en estado de asignacion de recursos (EAR) que no este en deadlock y que no sea seguro? Ejemplo o demostracion de lo contrario.

10

Servidores II

6. [Sil92, 6.8] Un sistema tiene 4 recursos del mismo tipo compartidos por 3 procesos, donde cada uno de los procesos necesita a lo mas 2 recursos. Muestre que el sistema esta libre de deadlocks. 7. [Tan02, 3.18] Una computadora tiene 6 grabadoras de CDs, con n procesos compitiendo por ellas. Cada proceso necesita 2 grabadoras. ?Para que valores de n este sistema esta libre de deadlocks? 8. [Fin88, 4.6] Se tiene el siguente Estado de Asignacion de Recursos donde juegan 3 procesos y 2 tipos de recursos. Proceso P0 P1 P2 C 34 23 42 M 15 36 20 A 23

1. Dibujar el grafo de asignacion de recursos. 2. Decidir si algun subconjunto de procesos esta en deadlock. 9. [Sil92, 6.15] Se tiene el siguente Estado de Asignacion de Recursos: Proceso P0 P1 P2 P3 P3 C 0012 1000 1354 0632 0014 M 0000 0750 1002 0020 0642 A 152

3. Decidir si el estado es seguro. 4. ?Si llega un pedido del P1 por (0,4,2,0), se lo puede otorgar inmediatamente? 10. [Tan02, 3.20] Tenemos un EAR con 4 procesos y 5 clases de recursos. Los valores de los vectores y matrices son como siguen. Proceso C 1 0 P0 2 1 1 2 0 P1 1 1 0 1 P2 1 0 M A 0 0 x 1 1

01002

02100

10300

Pgina

11

Servidores II

P3

1 0 1 1 1 1 0

0111

11. Para que valores de x resulta seguro? 12. [Tan02, 3.22] Tenemos 2 procesos, P0 y P1, cada uno de ellos necesita 3 registros de una base de datos (R0, R1, R2). Si P0 pide los registros en ese orden y P1 tambien, no hay posibilidad de deadlock, en cambio si P0 pide en el orden (R0,R1,R2) y P1 en (R2, R1, R0), hay posibilidad de deadlock. Con 3 recursos hay 3! combinaciones para pedir estos 3 recursos por parte de cada proceso. ?Que fraccion de estas combinaciones estan libres de deadlock? 13. [Tan02, 3.26] Un estudiante de ciencias de la computacion que esta pensando en el tema de deadlocks piensa en la siguiente idea brillante para eliminar deadlocks. Cuando un proceso pide un recurso, especifica un limite de tiempo. Si el proceso se bloquea porque el recurso no esta disponible, se inicia un temporizador. Si se excede el limite de tiempo, se libera el proceso y se lo reinicia. Si usted fuera el profesor, ?que nota le pondria a la propuesta del alumno? ?Por que?

Pgina

12

Servidores II

Lab1: Observando el Comportamiento de Linux

Objetivos Iniciar los laboratorios con un proyecto sencillo, donde se muestre como a travs del sistema de archivos virtual /proc de Linux, podemos inspeccionar informacin interna del kernel. Se deber generar la utilidad ksamp que muestra de diversas formas algn subconjunto de la informacin disponible en /proc.

Introduccin Podemos pensar el kernel de Linux como una coleccin de funciones y estructuras de datos. Estas estructuras de datos (o variables de kernel) contienen la visin del kernel respecto al estado del sistema, donde cada interrupcin, cada llamada al sistema, cada fallo de proteccin hacen que este estado cambie. Inspeccionando las variables del kernel podemos obtener informacin relevante a los procesos, interrupciones, dispositivos, sistemas de archivos, capacidades del hardware, etc. Muchas variables conforman el estado del kernel y estas pueden estar alojadas de manera esttica o dinmica en un stack frame de la memoria del kernel. Dado que el kernel de Linux es un programa "C" de cdigo abierto, es posible inspeccionar el cdigo fuente y encontrar algunos ejemplos relevantes de estas variables como por ejemplo xtime definido en include/linux/sched.h que mantiene la hora del sistema, la estructura task_struct definida en include/linux/sched.h que contiene la descripcin completa de un proceso, o los valores nr_threads y nr_running definidos en kernel/fork.c los cuales indican cuantos procesos existen y cuantos de estos estn corriendo. El cdigo fuente de Linux lo podemos encontrar en el directorio /usr/src/linux de la mayora de las distribuciones, pero tambin existen pginas donde podemos navegar el cdigo de varias versiones de kernel, como por ejemplo Linux Cross Reference. Tambin existen utilidades para navegacin de cdigo local como Source Navigator. Tareas Parte A Buscar informacin acerca de la estructura del directorio /proc, y averiguar los siguientes datos

Pgina

Tipo y modelo de CPU. Versin del kernel. Tiempo en das, horas, minutos y segundos que han transurrido desde que se inici el sistema operativo. Cuanto tiempo de CPU ha sido empleado para procesos de usuario, de sistema y cuando tiempo no se us. Cuanta memoria tiene y cuanta est disponible.

13

Servidores II

Cuantos pedidos de lectura/escritura a disco se han realizado. Cuantos cambios de contexto han sucedido. Cuantos procesos se crearon desde que inici el sistema.

Pgina

14

Servidores II

Tipo y modelo de CPU. Versin de Kernel.

Pgina

15

Parte B Escriba una versin inicial del programa que inspeccione las variables del kernel a travs del /proc e informe por stdout:

Servidores II

Cantidad de tiempo transcurrido desde que se inici el sistema operativo, con el formato ddD hh:mm:ss.

Tambin se pide incluir una cabecera donde se indique el nombre de la mquina y la fecha y hora actuales. Parte C Escriba una segunda versin del programa que imprima la misma informacin que la versin por defecto, pero en caso de invocarse con la opcin -s, agrega la siguiente informacin:

Cantidad de tiempo de CPU utilizado para usuarios, sistema y proceso idle. Cantidad de cambios de contexto. Fecha y hora cuando el sistema fue iniciado. Nmero de procesos creados desde el inicio del sistema.

Parte D La tercera parte involucra imprimir todo lo de las versiones anteriores, pero cuando se invoca con la opcin -l interval duration imprime adems:

Nmero de peticiones a disco realizadas. Cantidad de memoria configurada en el hardware. Cantidad de memoria disponible. Lista de los promedios de carga de 1 minuto.

Asi por ejemplo ksamp -l 2 100 mostrar el promedio de carga de 1 minuto por 100 segundos tomando muestras en intervalos de 2 segundos. Aclaracin 29 Agosto: Hay mucha gente que pregunt por este ltimo punto, el enunciado no esta del todo claro. El comando ksamp -l a b, lee los datos indicados arriba (peticiones de disco, cantidades de memoria, promedios de carga) de /proc, y los imprime repetidamente cada a segundos; esto se repite hasta que hayan pasado b segundos. Por ejemplo: [so2004@hal so2004]$ ksamp -l 5 15 Peticiones a disco: 12345 Memoria disponible / total: 1000000 / 8000000 Promedio de carga en el ltimo minuto: 0.88 [Pausa de 5 segundos] Peticiones a disco: 12348 Memoria disponible / total: 2000000 / 8000000 Promedio de carga en el ltimo minuto: 0.82 [Pausa de 5 segundos] Peticiones a disco: 12645 Memoria disponible / total: 500000 / 8000000 Promedio de carga en el ltimo minuto: 0.98 [Pausa de 5 segundos] Peticiones a disco: 99995 Memoria disponible / total: 300000 / 8000000 Promedio de carga en el ltimo minuto: 1.07

Pgina

16

Servidores II

[so2004@hal so2004]$ En particular noten que el promedio de carga de un minuto es un valor que el sistema provee ya calculado, no es algo que ustedes tengan que calcular. Fin de aclaracin 29 Agosto. Notar que cada opcin incluye a la otra, por lo que ksamp -s -l 2 100 no debera ser aceptado y en tales casos resulta til imprimir por la salida standard un resumen de las opciones aceptadas. Cmo atacar los problemas La pgina del manual de Linux man 5 proc contiene suficiente informacin al respecto, tambin se pueden ver artculos de la revista Linux Magazine " An Overview of the Proc Filesystem" o The Official Red Hat Linux Reference Guide en su captulo "The /proc Filesystem". En general basta con realizar una bsqueda de "/proc filesystem" en cualquier buscador de la Web para encontrar informacin en cualquier idioma. Una vez encontrados los archivos de /proc donde est la informacin, es necesario abrirlos, leer la informacin y cerrarlos. Esto se puede lograr con las funciones de la biblioteca "C" fopen, fgets (ofscanf) y fclose. Un ejemplo de uso sera el siguiente.

#include<stdio.h> #define BUFFSIZE 256 int main(int argc, char *argv[]) {

FILE *fd; char buffer[BUFFSIZE+1]; fd = fopen("/proc/sys/kernel/hostname","r"); fgets(buffer, BUFFSIZE+1, fd); printf("Hostname: %s\n",buffer); fclose(fd); }

Pgina

Para facilitar el proceso de lectura y anlisis de los archivos, les facilitamos un TAD para hacer lexing (separacin de la entrada en tokens, es decir elementos como palabras, nmeros, simbolos, espacios en blanco). Pueden usarlo en su proyecto tal como est, y les aconsejamos hacerlo as no pierden tiempo en este aspecto del proyecto. El fuente del TAD lo pusimos en un paquete Lexer.tar.gz.

17

Servidores II

Para leer los argumentos de entrada e interpretarlos (proceso de parsing) hay que hacer uso de las variables int argc y char *argv[]. La primera indica cuantos argumentos se pasaron y argv es el arreglo de tamao argc con cada uno de las cadenas de los argumentos. Notar que como el propio comando se incluye en la lista de argumentos una llamada ksamp -l 10 100 implica que al inicio del main se cumple {argc=4 & argv[]={"ksamp", "-l", "10", "100"}}. Pueden utilizar la funcin getopt de la glibc para no volver a inventar la rueda. Pueden encontrar informacin en man 3 getopt o bien en las Infopages invocando pinfo libc y buscado este tema. Este ltimo comando muestra la GNU C Library reference manual. El ejemplo anterior resulta sencillo en cuanto a que no tenemos que "interpretar" la secuencia de caracteres, slo la tomamos y la imprimimos. Sin embargo, muchos de los parmetros que se necesitan imprimir requieren de cierto tratamiento. Este proceso de transformar una secuencia de caracteres en alguna representacin ms adecuada para su tratamiento se denomina parsing. Por ejemplo el tiempo transcurrido desde que el sistema inici se expresa en segundos, y se encuentra en cierta parte del archivo. Entonces tenemos que extraerlo y convertirlo a un entero sin signo. Cuando ya tenemos un entero sin signo, resulta sencillo operar matemticamente y generar una secuencia de caracteres (imprimir) con el formato adecuado. Esto ltimo se denomina pretty printing. Funciones como atoi y sus relacionadas pueden ser tiles. Tambin resulta til sscanf. Para obtener la fecha y hora que va en el encabezado del informe que brinda el programa, se pueden utilizar la funciones de la glibc gettimeofday y ctime, o bien leer el tiempo de inicio del sistema y sumarlo al transcurrido para luego convertirlo a fecha. Cuando se necesite realizar las muestra del promedio de carga de 1 minuto, puede ser til la funcinsleep que duerme un proceso por un intervalo determinado de tiempo. Qu se debe Entregar

Cdigo (funcionando bajo las especificaciones dadas y bajo cualquier caso de test de parametros de entrada) o Dividir en mdulos de manera juiciosa. o Estilo de cdigo. o Usar TADs, por ejemplo no estara mal un TAD que contenga toda la informacin que se quiere con mtodos para leer del kernel e imprimir en un filedescriptor los datos, o uno que contenga las opciones de la lnea de comandos y que acepte un mtodo para leerlas a partir de argc y argv. o Utilizar Makefile. Informe del desarrollo del proyecto

Pgina

18

Servidores II

Tips No intenten hacer todo de golpe, vayan de a partes, y sobre todo discutan, analicen y trabajen en ideas de forma grupal. Una hora pensando en papel libremente suele ahorrar muchos problemas en el momento de codificar. Utilicen debuggers de lnea de comandos como gdb o interfaces grficas para estos como ddd. Tambin pueden realizar compilacin condicional para hacer debugging de la siguente manera.

#define STDOUT 0 #define DEBUG . . #ifdef DEBUG fprintf(STDOUT,"DEBUG> argc: %d\n",argc); #endif . .

Deducir la entrada disk_io requiere un poco ms de trabajo que el resto de la informacin. Encuentren el manejo de /proc en kernels 2.4.x, analicen el cdigo fuente y deduzcan el significado de cada elemento. Pueden utilizar Linux Cross Reference. Tareas Adicionales Si les sobra tiempo pueden hacer las siguientes mejoras:

Pgina

19

Algunos de las datos que se muestran involucran cantidades de memoria, y el valor que se puede leer en /proc est siempre expesado en bytes. Como leer cantidades como 64MB en bytes suele ser dificultoso, muchos programas incluyen la opcin -h que significa "legible para humanos", que transforma las cantidades a una unidad correspondiente de manera que la cadena se mantenga acotada en tamao. Este programa puede ser muy til para monitorear la actividad de un servidor, pero resulta ms practico si se le agrega una opcin -d que bajo la opcin -l muestra el diferencial de los valores leidos para, por ejemplo, poder medir cuantos cambios de contexto se estn realizando por segundo. Este es un muy buen lugar para utilizar un TAD con los valores de muestra que acepte mtodos que calculen el diferencial entre muestras. Utilizar getopt de POSIX.2 para parsear la lnea de comandos. Comparar lo realizado con utilidades establecidas que realizan tareas similares, como por ejemploprocinfo.

Servidores II

Introduccin La interfaz ms tradicional de un sistema operativo UNIX-like (*NIX) es el intrprete de lnea de comandos. Este programa, que ejecuta en modo usuario, funciona en cualquier *NIX que soporte interface de caracteres y su funcin es aceptar comandos ingresados por entrada estandar (teclado), parsearlos, ejecutar la rden y mostrar el resultado en salida estandar (pantalla), para luego volver a repetir el proceso. Por defecto UNIX ejecuta un proceso shell cada vez que un usuario interactivo ingresa al sistema. Aunque esto puede ser configurado de otra manera (ver el ltimo campo de cada lnea del archivo/etc/passwd), en la mayora de los casos luego de ingresar nuestro nombre de usuario y contrasea, el proceso que maneja el ingreso de usuarios genera un proceso hijo que ejecuta un shell, con el uid/gid (identificador de usuario y grupo) correspondiente al usuario. En este momento la pantalla se suele presentar de la siguiente manera:

[juan@hal juan]$

Despus de este texto inicial llamado prompt, que contiene informacin de entorno como por ejemplo el nombre del usuario, el nombre del host y el ltimo tramo del directorio corriente, el shell espera datos a travs de la stdin que normalmente se asocia al dispositivo teclado. Podemos escribir el comando que deseamos que el shell ejecute, e iniciar la ejecucin ingresando el caracter NEWLINE '\n' generalmente asociado con la tecla Enter o Return.

[juan@hal juan]$ sleep 10

Har que el shell ejecute un proceso con el programa binario que se encuentra en /bin/sleep, pasndole el argumento "10". Operacin Bsica

comando argumento1 argumento2 ...

Pgina

20

La sintxis bsica del intrprete de comandos ms usual de *NIX, conocido como Bourne shell (Bourne again shell - bash, en Linux) es la siguiente,

Servidores II

donde el comando y los argumentos son secuencias de caracteres separados por uno o ms espacios. La semntica dice que al presionar Enter el shell buscar el comando dentro de los comandos internos y si no lo encuentra tratar de buscar un archivo ejecutable con ese nombre, siguiendo las reglas de camino de *NIX o componiendo el comando a la secuencia de la variable de entorno PATH, para luego crear unproceso hijo que cargar y ejecutar el contenido de ese archivo con los argumentos correspondientes. Los comandos internos son manejados directamente por el shell, sin requerir de ningn archivo externo. Un ejemplo es el comando de cambio de directorio cd, el cual no se encuentra como archivo ejecutable en ningn lugar del rbol de directorio (el comando find /bin /sbin /usr/bin /usr/sbin -perm +400 -type f -name cd no devuelve nada). Con man builtin obtenemos una lista de todos los comandos internos implementados en bash. Si el comando no es un builtin, el shell deber buscar un archivo dentro de su sistema de archivos, cargarlo y ejecutarlo pasndole los argumentos. El problema principal es dnde buscar este archivo. Existen tres formas:

Camino absoluto Camino relativo Bsqueda en secuencia PATH

Cuando el comando comienza con /, este se toma como un camino absoluto dentro del rbol del filesystem, el shell cargar en memoria y ejecutar el comando. En cambio si el comando comienza con el nombre de un directorio, . o .., se debe seguir las reglas usuales de camino relativo de *NIX, cargar y ejecutar el archivo comando, relativo al camino actual (ver comando pwd). Otro mecanismo entra en juego cuando el comando no comienza con un delimitador de camino absoluto o relativo. La variable de entorno PATH, que puede ser leida con el comando env o con echo $PATH, sirve de secuencia de caminos absolutos o relativos, separados por ':' que sern prefijados a commando hasta encontrar un archivo que pueda ser ledo y ejecutado. Usemos el archivo ejecutable /bin/date que nos proporciona la fecha y hora del sistema para ejemplificar los mecanismos de camino absoluto, relativo y secuencia PATH.

Pgina

[juan@hal juan]$ /bin/date Sun Aug 31 15:33:22 ART 2003 [juan@hal juan]$ cd /usr [juan@hal /usr]$ ../bin/date Sun Aug 31 15:33:57 ART 2003

21

Servidores II

[juan@hal /usr]$ cd / [juan@hal /]$ bin/date Sun Aug 31 15:34:24 ART 2003 [juan@hal /]$ cd ~ [juan@hal juan]$ date Sun Aug 31 15:35:02 ART 2003

Todos los comandos ejecutados por bash son el mismo /bin/date.

Ejercicios 1. Cmo ejecutamos un archivo que se llama exactamente como un builtin?

Aunque usamos builtin para implementarlo, en lugar builtin utilizar command para evitar que la funcin cd() se llame a si mismo ya que command es mas respectivo solo busca comandos internos.

2. Por qu las recomendaciones de seguridad indican que es peligroso tener. / en PATH al ms puro estilo DOS? En Unix la estructura de directorios es en forma de arbol similar a la de Msdos. Dado que la estructura de directorios se organiza como las ramas de un arbol para localizar un punto cualquiera hay que utilizar cada uno de los directorios que conducen a ese punto desde el directorio raiz. Nosotros lo llamaremos camino y en Unix se le suele llamar path. Se empieza en el directorio raz representado por '/' y se avanza por las ramas de ese arbol separando cada identificador por un nuevo caracter '/'. De esta forma '/usr/local/bin' indica un lugar concreto en el arbol de directorios. Quizs se pregunte porqu Unix usa '/' en lugar de '\' como en Msdos.

Pgina

22

Servidores II

3. Supongamos que existen 2 comandos posibles dentro de la secuencia que contien PATH, donde el primero en la secuencia no est marcado como ejecutable y el segundo si. Qu hace el intrprete bash, ejecuta el segundo o informa que el primero no tiene permiso de ejecucin? (incorporte esta semntica a baash)
4. disponemos del array $@, el cual contiene todos los parmetros pasados al guion y podemos iterar sobre estos de la siguiente manera: 5. 6. 7. 8. for param in "$@" do echo "$param" done

3. Indique qu sucede cuando se tiene un directorio en el pwd actual con el mismo nombre que un archivo ejecutable en el PATH. Dice que no puede ejecutar un directorio o ejecuta el comando que encontr? (siga esta forma en baash)
busca la variable de entorno BASH_ENV, si existe expande su valor, y lo utiliza como el nombre del archivo para leer y ejecutar. bash se comporta como si se ejecutase la siguiente orden: 4. if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

pero el valor de la variable PATH no se utiliza para buscar el archivo.

5. Obtenga la lgica ms sencilla que unifique los tres tipos de bsqueda.

6. Podemos poner directorios relativos en PATH? (haga lo propio con baash) Rutas relativas:
Las rutas relativas sealan la ubicacin de un archivo o directorio a partir de la posicin actual del sistema operativo en el sistema de archivos. Por ejemplo es una ruta relativa dir1/arc1.fil que seala al archivo arc1.fildentro del directorio dir1 en la ubicacin actual. En sistemas tipo UNIX, la ruta ~/ es una ruta relativa que lleva al directorio personal del usuario que ha insertado la ruta relativa; por ejemplo, si el usuario Juan tiene una imagen en su directorio personal, esta imagen podra tener dos rutas de acceso, una relativa y una absoluta: La absoluta:

/home/juan/imagen.jpg La relativa:

~/imagen.jpg

Pgina

En este caso, la ruta relativa slo puede ser verdaderamente valida si el sistema est ubicado en el usuario de Juan. En este mismo caso, ~/ seria el sinnimo relativo de la ruta /home/juan/.

23

Servidores II

Tambin se puede crear, borrar, copiar, etc. directorios y archivos con este tipo de ruta desde una interfaz de lnea de comandos. Algunos ejemplos: mkdir ~/Fotos chmod 777 ~/ rm ~/foto.jpg

Ejercicios 1. Investigue cuales son los comandos internos para manejo de procesos en background de bash Ejemplos de estos comandos son cd, chdir, alias, set o export. 2. En el ejemplo de arriba el operador '&' funciona como operador de composicin paralela. Cul es el operador de composicin secuencial en Bourne shell? secuencial de comandos con el smbolo &&. cmd1 && cmd2 && && cmdn ejecuta en secuencia los comandos indicados hasta que falle alguno de ellos. En ese caso los comandos que vienen a continuacin no se ejecutan. De esta forma, el comando que buscbamos para enviar nuestras cartas a los morosos sera el siguiente: $ morosos && mail cat morosos.txt < carta Otra posibilidad para ejecutar comandos en secuencia es separndolos con el smbolo ||. cmd1|| cmd2 || || cmdn ejecuta los comandos especificados hasta que uno de ellos no falle. De esta forma si queremos mostrar un mensaje de error en caso de que no se haya podido enviar la carta a todos los morosos, podemos usar el siguiente 9 4. Indique cuantas letras 'a' debera imprimir el siguiente programa. Generalice.
fork(); fork(); fork(); printf("a");

Pgina

Cuando se crea un proceso, se le asignan tres identificadores de archivos (file descriptors): stdin, stdout y stderr. Si se lee desde stdin, los datos que se reciben sern

24

Redireccin de la Entrada/Salida

Servidores II

dirigidos desde el teclado al file descriptorstdin. Similarmente, los datos escritos en stdout, stderr sern mapeados a la pantalla de la terminal. El usuario puede redefinir el stdin desde la lnea de comandos del shell si se provee al final del comando un embudo de entrada '<' y un nombre de archivo. Este archivo reemplazar la corriente estandar de entrada, por lo que los valores que lea el comando sern extraidos desde el archivo. Similarmente podemos redefinir el file descriptor de stdout con el embudo de salida '>' y un nombre de archivo al final del comando y los argumentos, para indicar que toda la salida estandar del comando se acumule en el archivo. Como ejemplo podemos recolectar estadsticas sobre un header del cdigo fuente del kernel y ponerlo en un archivo de estadsticas.

[juan@hal juan]$ wc < kernel.h > kernel.h.stats

O si nuestros programas cpu-bound generan sus resultados en pantalla podemos ejecutarlos concurrentemente y mantener sus salidas separadas, mientras las monitoreamos con el comando tail.

[juan@deepblue juan]$ forest3d -n 0.2 > n0.2.out & [juan@deepblue juan]$ forest3d -n 0.3 > n0.3.out & [juan@deepblue juan]$ tail -f n0.2.out n0.3.out Ejercicios 1. Las corrientes estandar stdout y stderr estn dirigidas ambas a la consola. Cmo podemos utilizar los opeardores de redireccin para separarlas? 2. De ms ejemplos de como usar la redireccion de entrada? Tenga cuidado que muchos programas deshabilitan la posibilidad de redirigir la entrada estandar a otra cosa que no sea una terminal. 3. Podemos redirigir de manera independiente la entrada y la salida de una secuencia de comandos separados por &? Qu sucede con la composicin sequencial ;? (piense en este comportamiento en caso de que realice los puntos complementarios).

Las tuberas o pipes son el principal mecanismo de Comunicacin entre Procesos (IPC) para *NIX. Una tubera se compone de dos puntas, una entrada y una salida, cada una conectada a un

Pgina

25

Tuberas (o ... la plomera continua)

Servidores II

proceso. Las puntas de una tubera son un par de filedescriptors, uno para escribir y el otro para leer. Un pipe es bsicamente un buffer FIFO, donde tenemos un productor, sobre el write-end y un consumidor sobre el read-end. Como sabemos que todas las colas que se encuentran en el sistema operativo son acotadas (memoria finita), adems de tener un read bloqueante cuando no hay datos para consumir, tenemos un send bloqueante cuando la capacidad del buffer est excedida. El shell provee la funcionalidad de un pipe a travs del operador '|', denominado justamente pipe, el cual conecta la salida estandar del proceso lanzado por el comando de la izquierda del pipe, con la entrada estandar del proceso que se genera con el comando a la derecha del smbolo de tubera. Las tuberas se pueden componer secuencialmente para generar una linea de produccin de datos, el cual es un estilo arquitectural denominado pipes&filters. Estos ejemplos cuentan cuantas veces Juan ingres al sistema, los pids (process identifiers) de todos los morzillas, y el listado ordenado de mayor a menor de todos los usuarios del sistema que tienen bash,

[juan@hal juan]$ last juan | wc -l [juan@hal juan]$ ps aux | grep mozillabin [juan@hal juan]$ grep bash /etc/passwd | cut -d ":" -f 1 | sort -r

mientras que el siguiente es un poco ms complicado y permite reestablecer interactivamente un dump de una particin ext2, que ha sido partido para sortear la limitacin de 2GB de tamao del sistema de archivos ext2.

[juan@hal juan]$ cat backupL0.gza? | gzip -dc | /sbin/restore -i -f Ejercicios 1. Cal es el mecanismo para que este estilo pipes&filters, hasta ahora absolutamente lineal, permita bifurcaciones? Si tuvieramos bifurcaciones (o "T's" para un plomero), podramos capturar la salida estandar en un archivo y al mismo tiempo visualizarla en consola. 2. Los pipes existen en el filesystem mientras dura el comando. Dnde se encuentran y que atributos tiene? 3. Cmo es el pipe de comandos para generar el dump de nivel 0 que se reestablece interactivamente con el ejemplo anterior? 4. Muestre el uid mximo en su sistema NIS (ypcat passwd realiza el trabajo bsico).

Pgina

26

Servidores II

5. Muestre todos los login repetidos de su sistema NIS. Tareas El problema se divide en 3 partes, de manera que su concrecin se realice en forma progresiva. Es una gua de como llegar al resultado final, nuestro baash, sin tener que sortear todos los problemas de diseo y tcnicos de una sola vez. Parte A Escriba un programa en "C" que acte com una concha de intrprete de lnea de comandos para el sistema operativo Linux. Su programa deber utilizar la misma sintaxis de Bourne shell para correr programas. comando argumento1 argumento2 ... Efectuando la bsqueda del comando segn se presente como path absoluto, relativo o involucre una bsqueda en la secuencia de la variable de entorno PATH. El programa deber generar un proceso hijo para correr el comando, a fin de protegerse de comportamientos malos, y pasarle los argumentos correspondientes. Es preferible imprimir un prompt con informacin relevante a la izquierda de donde se introduce el comando. El nombre del host, el nombre del usuario y el camino corriente pueden ser algunos ejemplos. El nico comando interno que se implementa es exit, el que termina con la ejecucin del intrprete de comandos. Nota 18 Sept: Tambin hace falta implementar el comando interno cd (cambiar de directorio actual). Fijense la syscall chdir(). Luego de implementar esta parte su baash deber ser capaz de invocar desde simples peticiones como date,que involucran bsquedas en PATH, hasta llamadas a complicados comandos de compilacin o linking utilizando path relativos y decenas de opciones. Parte B Agregue al shell de la parte anterior, la funcionalidad de correr programas como procesos en background, o mejor dicho concurrentemente con el mismo baash. El usuario incluir el operador '&' a la derecha del ltimo argumento para activar esta capacidad. Pruebe la nueva versin de la siguiente manera

baash-0.01> ./ksamp -l 3 120 & baash-0.01> ./ksamp -l 1 120 &

Pgina

27

Debera obtener un entrelazado no determinstico (efecte varias corridas) de la informacin generada por el programa del laboratorio 1.

Servidores II

Parte C Incorpore las funcionalidades de redireccin y tuberas a baash, de manera tal que se interpreten los opeardores < filename, > filename y | command2 argumento2_1 argumento2_2 ... al final de los argumentos del comando. Deber soportar slo uno de los cuatro operadores al mismo tiempo. Utilize todo el poder de baash con los ejemplos dados en la introduccin que respeten la restriccin de "a lo ms un operador". Cmo atacar los problemas La principal fuente de informacin son los captulos V, VI de: D. M. Ritchie and K. Thompson, "The UNIX Time-Sharing System" [html] [ps] [pdf] Este documento indica de manera extremadamente clara como se logr la implementacin del shell. Parte A Se puede ir paso a paso, generando programas de prueba que realicen tareas cada vez ms complejas y cercanas al enunciado de la parte A. Si usted se siente confiado respecto a poder solucionar el problema sin hacer desarrollo incremental, puede saltar estos pasos. 1. Escriba un programa que inicialice las variables e ingrese en un lazo que pida entrada por teclado y que termine slo cuando se ingresa una condicin de EOF (end of file) como Ctrl-D o el comando interno exit. 2. Refine el punto anterior de manera tal que haga parsing de la lnea de comandos y lo ponga en el array char *argv[]. Tambin compute argc. A manera de debug imprima, luego del parsing, el contenido deargc y argv. 3. En el siguiente refinamiento, use argv[0] para encontrar el archivo ejecutable. En esta versin slo imprima el fullpath del archivo. 1. Haga una versin simple que solamente pueda encontrar archivos de comando que estn en el directorio corriente. 2. Mejore su programa para que acepte path absolutos y relativos. 3. Active en su prototipo la posibilidad de buscar en los directorios de la lista PATH. 4. Ahora si cree el hijo y ejecute el comando con sus argumentos. Esta parte debera ser un reflejo exacto del poder de las llamadas a sistema para manejo de procesos fork, execv, y wait. Todo lo que resta es el parsing de la lnea de comandos y la impresin del prompt. Veamos un ejemplo de uso del fork y wait para crear toda una parentela de procesos. Notar el interleaving que se produce en las ejecuciones.

fork.c

Pgina

28

Servidores II

#include #include #include #include

<stdio.h> <stdlib.h> <unistd.h> <sys/wait.h>

#define N 8 int main (int argc, char **argv) { unsigned int i,j,h,s; int status; if (argc!=2) { fprintf(stderr,"Uso: %s cantidad_de_hijos\n",argv[0]); exit(1); } h = atoi(argv[1]); for (i=0;i<h;i++) { s = fork(); if (s<0) { perror("Creando el hijo"); exit(1); } else if (s==0) { for(j=0;j<N;j++) printf("Hijo pid=%5d: iteracin %3d\n",getpid(),j); return 0; /*no quiero nietos!*/ } else printf("PADRE: hijo pid=%5d, creado\n",s); } for (i=0;i<h;i++) { s = wait(&status); if (s<0) { perror("Esperando el hijo"); exit(1); } printf("PADRE: hijo pid=%5d, terminado\n",s); } return 0;

Pgina

29

Servidores II

El otro syscall a utilizar es execv, el cual reemplaza la imagen del proceso por una nueva que se encuentra en un archivo. En este pequeo ejemplo, se reemplaza el proceso actual por el que ejecuta el programa date. execvp.c #include <stdio.h> #include <unistd.h> int main (int argc, char **argv) { execvp("date",argv); printf("Llega hasta aca?\n"); return 0; } Aunque el syscall execvp, parece que le soluciona todos los problemas relativos a la bsqueda el fullpath del ejecutable, no se permite su utilizacin y debern codificar o reutilizar algoritmos y estructuras de datos apropiadas. Parte B El proceso que ejecuta el programa baash deber correr concurrentemente con el proceso hijo creado para ejecutar el comando, si es que hay un operador '&' a la derecha de todos los argumentos. Simplemente no hay que esperar! Parte C Cuando se crea un proceso, este hereda de los descriptores de archivos abiertos de su padre. Adems como el proceso 1, denominado init y padre de los restantes procesos del sistema (ps aux | grep init, o bienpstree para obtener el rbol genealgico), tiene abierto los tres primeros identificadores de archivos stdin, stdout y stderr (0,1 y 2) a descriptores de archivos asociados a la terminal de entrada y a la terminal de salida; todos los hijos heredan estos fileid's asociados a los filedescriptors. Para implementar los operadores de redireccin bastara con cambiar los filedescriptors asociados a los fileid's de stdin, stdout y stderr. Esto se puede hacer con la syscall dup, que duplica el filedescriptor indicado en su argumento, en el menor fileid libre. Veamos un ejemplo que redirige la salida a un archivo. Notar que las syscall para manejo de archivos que no son las habituales de la libc (fopen, fclose, ...). dup.c

Pgina

30

Servidores II

#include #include #include #include #include #include

<stdio.h> <stdlib.h> <unistd.h> <sys/types.h> <sys/stat.h> <fcntl.h>

#define STDOUT_FID 1 int main (int argc, char **argv) { int fid; int flags,perm; flags = O_WRONLY|O_CREAT|O_TRUNC; perm = S_IWUSR|S_IRUSR; fid = open("redireccion.out", flags, perm); if (fid<0) { perror("open");exit(1); } close(STDOUT_FID); /* stdout def. en stdio.h es un FILE* */ if (dup(fid)<0) { perror("dup"); exit(1); } printf("Hello World!\n"); close(fid); return 0; } Para implementar el operador de tubera '|', debemos utilizar la syscall pipe, la cual crea en el espacio del filesystem un nuevo nodo de este tipo y devuelve dos fileid's que sern la salida y la entrada de la tubera. Veamos un sencillo ejemplo de IPC. pipe.c #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <sys/wait.h>

Pgina

int main (int argc, char **argv) {

31

Servidores II

int fork_id; int srv_client_pipe[2]; int client_srv_pipe[2]; if (pipe(srv_client_pipe)<0) { perror("srv_client_pipe");exit(1); } if (pipe(client_srv_pipe)<0) { perror("client_srv_pipe");exit(1); } if ((fork_id = fork())<0) { perror("fork");exit(1); }; if (fork_id!=0) { /* soy padre, soy cliente */ int status; int x,fx; x = 8; printf("CLIENTE: envia %d\n",x); write(client_srv_pipe[1], &x, sizeof(int)); read(srv_client_pipe[0], &fx, sizeof(int)); printf("CLIENTE: recibe %d\n",fx); wait(&status); close(srv_client_pipe[0]); close(srv_client_pipe[1]); close(client_srv_pipe[0]); close(client_srv_pipe[1]); } else { /* soy hijo, soy server */ int in,out; read(client_srv_pipe[0], &in, sizeof(int)); printf("SERVIDOR: recibe %d\n",in); out = in*in; printf("SERVIDOR: envia %d\n",out); write(srv_client_pipe[1], &out, sizeof(int)); } return 0; } Notar que este programa aunque concurrente, presenta slo un interleaving en su salida. Se dice que el programa est fuertemente sincronizado debido a las primitivas de comunicacin.

Pgina

32

Servidores II

Tips El problema de la bsqueda en la secuencia PATH es un simple problema de bsqueda de secuencia, que con una buen TAD secuencia implementado sobre listas se debera resolver de manera compacta. Planteen el problema de parseo de forma general, ya saben todas las posibilidades que hay para parsear, asi que no debera ser difcil realizar una funcion parse_command que devuelva una estructura command que contega toda la informacin necesaria para ejecutar el o los comandos, y aplicar los operadores. Si es lo suficientemente general, los puntos adicionales saldrn sin esfuerzo adicional. El shell refleja tan bien la estructura interna de los syscalls de *NIX para creacin de procesos, manejo de corrientes e IPC, como se refleja en "The UNIX Time-Sharing System" en su seccin VI, que el programa principal debera ser muy compacto. Si no logra esto reorganice sus ideas intentando ser lo ms econmico posible. Se recomienda fuertemente leer este artculo. Estudiantes del 2003 y 2004 realizaron una traduccin al castellano de las secciones V y VI del paper "The UNIX Time-Sharing System". El libro "Advanced Linux Programming", muestra le uso del assert en la pgina 30, y como manejar correctamente los errores que pueden devolver las llamadas a sistema en la pgina 33. Estudien este material antes de comenzar la codificacin. Los ejemplos de cdigo contienen un poco de programacin defensiva. Para ver cuanto se sigue la programacin defensiva en la prctica usual de desarrollo de software vayan a freshmeat.net, busquen proyectos cualquiera en C, con fuentes disponibles, bajen la ltima versin, y encontrar en los fuentes una syscall de la cual se ignora el resultado. Miren el cdigo de OpenSSH. Qu notan? Este tip est tomando la forma de ejercicio obligatorio y debe comentarse en la documentacin del laboratorio. Material adicional:

"Pipes, Redirection, and Filters" del libro "The Art of Unix Programming". Captulos 3 (Process) y 5 (Interprocess Communication) del libro "Advanced Linux Programming". Captulo "Implementing a Job Control Shell", de "The GNU C Library Reference Manual"

Tareas Adicionales Si les sobra tiempo pueden hacer las siguientes mejoras:

Pgina

Posibilidad de mezclar los 4 operadores "&<>|", a lo ms una vez cada uno, en la misma lnea de comandos. Operador de composicin secuencial ';', operador de composicin paralela general '&'. Manejar bien los procesos lanzados en background para que no se generen zombies. Pueden consultar la seccin 3.4.3 de "Advanced Linux Programming", que est en la pgina 57. Prompt configurable desde la variable de entorno PS1.

33