1 / 27

Como comunicar 2 procesos emparentados

Como comunicar 2 procesos emparentados. Mediante una pipe sin nombre. Que queremos hacer…. Lo mismo que haría la Shell al hacer…. ps –A |grep [COMANDO] Donde [COMANDO] será un texto que buscaremos en la salida del comando ps. ¿Que hace la Shell al hacer esto?. shell. fork. fork.

john
Download Presentation

Como comunicar 2 procesos emparentados

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

  2. Que queremos hacer… • Lo mismo que haría la Shell al hacer…. • ps –A |grep [COMANDO] • Donde [COMANDO] será un texto que buscaremos en la salida del comando ps.

  3. ¿Que hace la Shell al hacer esto? shell fork fork ps -A grep • El proceso que ejecutará ps escribe sus datos en la salida std (canal 1) •  Hay que redireccionar la salida std del proceso que hará el ps • El proceso que ejecutará el grep, lee sus datos de la entrada std (canal 0) •  Hay que redireccionar la entrada std del proceso que hará el grep

  4. Que necesitamos • 2 procesos (emparentados, sino no se pueden usar pipes sin nombre) • 1 pipe sin nombre • Como es solo para estos procesos, no tiene sentido crear una pipe con nombre, pero también se podría usar • La pipe la usarán el proceso ps y el grep hay que crearla antes que cualquiera de los dos procesos para que la hereden

  5. PASO 1: Esquema de procesos (simplificado) voidmain(intargc,char *argv[]) { intpid_ps,pid_grep; if (argc!=2) usage(); pid_ps=fork(); if (pid_ps==0){ // El hijo mutará a ps execlp("ps","ps","-A",(char *)NULL); error_cs("Fallo al mutar a ps"); }elseif (pid_ps<0) error_cs("Error en el primer fork (PS)"); pid_grep=fork(); if (pid_grep==0){ // El hijo mutará a grep execlp("grep","grep",argv[1],(char *)NULL); error_cs("Error al mutar a grep"); }elseif (pid_grep<0) error_cs("Error en el segundo fork(GREP)"); while(waitpid(-1,NULL,0)>0); // El padre simplemente esperará }

  6. PASO 2: Creamos la pipe voidmain(intargc,char *argv[]) { intpid_ps,pid_grep, p[2]; if (argc!=2) usage(); pipe(p); // Creamos la pipe antes del ps y el grep pid_ps=fork(); if (pid_ps==0){ // El hijo mutará a ps execlp("ps","ps","-A",(char *)NULL); error_cs("Fallo al mutar a ps"); }elseif (pid_ps<0) error_cs("Error en el primer fork (PS)"); pid_grep=fork(); if (pid_grep==0){ // El hijo mutará a grep execlp("grep","grep",argv[1],(char *)NULL); error_cs("Error al mutar a grep"); }elseif (pid_grep<0) error_cs("Error en el segundo fork(GREP)"); while(waitpid(-1,NULL,0)>0); // El padre simplemente esperará } Necesitamos un vector de 2 enteros P[0] tendrá el canal de lectura y p[1] el de escritura

  7. PASO 3: Redireccionar canales(ps) • El proceso ps escribirá en el canal 1 • El canal 1 debe estar vinculado a lapipe … if (pid_ps==0){ // El hijo mutará a ps dup2(p[1],1); execlp("ps","ps","-A",(char *)NULL); error_cs("Fallo al mutar a ps"); }elseif (pid_ps<0) error_cs("Error en el primer fork (PS)"); … ps 1 • Si el canal 1 estaba activo (lo normal), primero se cierra • Después se copia el contenido de la tabla de canales de la entrada p[1] en la entrada 1

  8. PASO 4: cerrar canales(ps) • El proceso ps solo necesita elcanal 1 … if (pid_ps==0){ // El hijo mutará a ps dup2(p[1],1); close(p[0]);close(p[1]); execlp("ps","ps","-A",(char *)NULL); error_cs("Fallo al mutar a ps"); }elseif (pid_ps<0) error_cs("Error en el primer fork (PS)"); … ps 1 Antes de mutar!!!!!!

  9. PASO 3: Redireccionar canales(grep) • El proceso grep leerá en el canal 0 • El canal 0 debe estar vinculado a lapipe … if (pid_grep==0){ // El hijo mutará a grep dup2(p[0],0); execlp(“grep",“grep",argv[1],(char *)NULL); error_cs("Fallo al mutar a grep"); }elseif (pid_grep<0) error_cs("Error en el segundo fork (GREP)"); … grep 0 • Si el canal 0 estaba activo (lo normal), primero se cierra • Después se copia el contenido de la tabla de canales de la entrada p[0] en la entrada 0

  10. PASO 4: cerrar canales(grep) • El proceso grep solo necesitael canal 0 … if (pid_grep==0){ // El hijo mutará a grep dup2(p[0],0); close(p[0]);close(p[1]); execlp(“grep",“grep",argv[1],(char *)NULL); error_cs("Fallo al mutar a grep"); }elseif (pid_grep<0) error_cs("Error en el segundo fork (GREP)"); … grep 0 Antes de mutar!!!!!!

  11. PASO 5: cerrar canales (padre) voidmain(intargc,char *argv[]) { intpid_ps,pid_grep, p[2]; if (argc!=2) usage(); pipe(p); // Creamos la pipe antes del ps y el grep pid_ps=fork(); if (pid_ps==0){ // El hijo mutará a ps ……. }elseif (pid_ps<0) error_cs("Error en el primer fork (PS)"); pid_grep=fork(); if (pid_grep==0){ // El hijo mutará a grep ….. }elseif (pid_grep<0) error_cs("Error en el segundo fork(GREP)"); close(p[0]);close(p[1]); while(waitpid(-1,NULL,0)>0); // El padre simplemente esperará } El padre no usa la pipe Antes del waitpid!!!!

  12. Probad el código!!! Veremos como afecta a las estructuras de datos

  13. ¿Como afecta a las estructuras de datos? • Suponed que el programa se llama ps_grep y lo lanzamos asi: • ps_grepbash • La entrada y salida std por defecto será la consola (“tty” en la tabla) Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo T.CanalesProceso inicial Tabla Ficheros Abiertos

  14. Estado inicial: comentarios • Tenemos tres canales ocupados: 0, 1 y 2 que corresponden con los canales de la entrada/salida/salida error std • Como la entrada/salida/salida error std. Asumimos que es la consola, podemos hacer que apunte a una única entrada de la TFO • Referencias=3 porque hay tres canales en total apuntando a ella • Como es de lectura/escritura el modo es RW • Como la consola no es un fichero de datos, no ofrece un acceso secuencial a la información, por lo tanto no ponemos un valor en la posición de l/e • Usamos la entrada 0 de la tabla de inodos • En la T. inodos deberíamos poner el número de inodo, pero en los casos que tengamos información del sistema de fichero lo simplificaremos con una etiqueta tipo “consola” o “pipe”

  15. Ejecución concurrente • Los tres procesos estará ejecutándose a la vez, las modificaciones que pondremos aquí corresponden a una posible secuencia • Por simplicidad asumiremos que primero se ejecuta el padre, luego añadiremos las modificaciones del proceso del ps y luego las del grep. • La tabla de canales está en el PCB, pero por simplicidad pintamos solo la tabla de canales • Cada vez que hagamos un fork: • Hemos de añadir una nueva tabla de canales • Será una réplica de la de su padre • Habrá que actualizar el contador de referencias

  16. Secuencia del padre • pipe(p); • fork(); • fork() • close(p[0]);close(p[1]); • while(waitpid(-1,null,0)>0);

  17. 1. Creamos la pipe • Hemos de añadir 1 entrada en la T.Inodos, 2 entradas en la TFO y 2 canales. Primero el acceso de lectura y luego el de escritura. Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo T.CanalesProceso inicial Tabla Ficheros Abiertos

  18. 2.3. Fork: no modifica la tabla de canales del padre Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Canal; entrada_tfo Canal; entrada_tfo Proceso “ps” Proceso “grep”

  19. 4. Cierra los canales : close(3);close(4) Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Canal; entrada_tfo Canal; entrada_tfo Proceso “ps” Proceso “grep”

  20. Secuencia ps • dup2(p[1],1);  dup2(4,1) • Cierra el canal 1  actualizar contador de referencias • Copia el canal 4 en la salida1  actualizar contador referencias • close(p[0]);close(p[1]);  close(3); close(4); • Actualizar contador de referencias • execlp(“ps",“ps",”-A”,(char *)NULL); • No afecta a la tabla de canales, solo es un cambio del binario

  21. 1. Cambios proceso PS: dup2(4,1) Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Canal; entrada_tfo Canal; entrada_tfo Proceso “ps” Proceso “grep”

  22. 2. Cambios proceso PS: close(3);close(4); Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Canal; entrada_tfo Canal; entrada_tfo Proceso “ps” Proceso “grep”

  23. Secuencia grep • dup2(p[0],0);  dup2(3,0) • Cierra el canal 0  actualizar contador de referencias • Copia el canal 3 en la entrada 0  actualizar contador referencias • close(p[0]);close(p[1]);  close(3); close(4); • Actualizar contador de referencias • execlp(“grep",“grep",argv[1],(char *)NULL); • No afecta a la tabla de canales, solo es un cambio del binario

  24. 1. Cambios proceso grep: dup2(3,0); Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Canal; entrada_tfo Canal; entrada_tfo Proceso “ps” Proceso “grep”

  25. 2. Cambios proceso grep: close(3);close(4); Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Canal; entrada_tfo Canal; entrada_tfo Proceso “ps” Proceso “grep”

  26. Este es el estado cuando el proceso padre está en el waitpid y los hijos están haciendo el ps y el grep Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Canal; entrada_tfo Canal; entrada_tfo Proceso “ps” Proceso “grep”

  27. Finalización de procesos • El primero en acabar será el ps y luego el grep, ya que uno produce datos y el otro los lee. ¿ Como estarán las tablas cuando solo quede el padre justo después del waitpid? Ent.; refs.Inodo; Ent.; refs. Modo; l/e; Ent. T.Inodo Canal; entrada_tfo Proceso inicial Cuando un proceso terminase cierran todos los canalesque le queden abiertos

More Related