como comunicar 2 procesos emparentados mediante una pipe sin nombre

27
Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

Upload: silvio-cardo

Post on 23-Jan-2016

213 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

Como comunicar 2 procesos emparentados

Mediante una pipe sin nombre

Page 2: 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.

Page 3: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

¿Que hace la Shell al hacer esto?

shell

ps -A grep

fork fork

• 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

Page 4: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

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

Page 5: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

PASO 1: Esquema de procesos (simplificado)void main(int argc,char *argv[]){ int pid_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"); }else if (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"); }else if (pid_grep<0) error_cs("Error en el segundo fork(GREP)");while(waitpid(-1,NULL,0)>0); // El padre simplemente esperará }

Page 6: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

void main(int argc,char *argv[]){

int pid_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"); }else if (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"); }else if (pid_grep<0) error_cs("Error en el segundo fork(GREP)");while(waitpid(-1,NULL,0)>0); // El padre simplemente esperará }

PASO 2: Creamos la pipe

Necesitamos un vector de 2 enteros

P[0] tendrá el canal de lectura y p[1] el de escritura

Page 7: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

… 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"); }else if (pid_ps<0) error_cs("Error en el primer fork (PS)");…

PASO 3: Redireccionar canales(ps)

ps 1

• El proceso ps escribirá en el canal 1• El canal 1 debe estar vinculado a la

pipe

• 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

Page 8: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

… 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"); }else if (pid_ps<0) error_cs("Error en el primer fork (PS)");…

PASO 4: cerrar canales(ps)

ps 1

• El proceso ps solo necesita elcanal 1

Antes de mutar!!!!!!

Page 9: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

… 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"); }else if (pid_grep<0) error_cs("Error en el segundo fork (GREP)");…

PASO 3: Redireccionar canales(grep)• El proceso grep leerá en el canal 0• El canal 0 debe estar vinculado a la

pipe

• 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

grep0

Page 10: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

… 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"); }else if (pid_grep<0) error_cs("Error en el segundo fork (GREP)");…

PASO 4: cerrar canales(grep)• El proceso grep solo necesita

el canal 0

grep0

Antes de mutar!!!!!!

Page 11: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

void main(int argc,char *argv[]){ int pid_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 ……. }else if (pid_ps<0) error_cs("Error en el primer fork (PS)"); pid_grep=fork(); if (pid_grep==0){ // El hijo mutará a grep ….. }else if (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á }

PASO 5: cerrar canales (padre)

El padre no usa la pipeAntes del waitpid!!!!

Page 12: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

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

Page 13: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

¿Como afecta a las estructuras de datos? Suponed que el programa se llama ps_grep y lo lanzamos asi:

# ps_grep bash

• La entrada y salida std por defecto será la consola (“tty” en la tabla)

0 0

1 0

2 0

3

4

Canal; entrada_tfo 0 3 RW - 0

1

2

3

4

5

T.CanalesProceso inicial

Tabla Ficheros Abiertos

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1

2

Ent.; refs. Inodo;

Page 14: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

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”

Page 15: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

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

Page 16: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

Secuencia del padre

1. pipe(p); 2. fork();3. fork()4. close(p[0]);close(p[1]);5. while(waitpid(-1,null,0)>0);

Page 17: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfo 0 3 RW - 0

1 1 R - 1

2 1 W - 1

3

4

5

T.CanalesProceso inicial

Tabla Ficheros Abiertos

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

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.

Page 18: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfo 0 9 RW - 0

1 3 R - 1

2 3 W - 1

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

2.3. Fork: no modifica la tabla de canales del padre

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “ps”

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “grep”

Page 19: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfo 0 9 RW - 0

1 3 2 R - 1

2 3 2 W - 1

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

4. Cierra los canales : close(3);close(4)

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “ps”

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “grep”

Page 20: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

Secuencia ps

1. 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

2. close(p[0]);close(p[1]); close(3); close(4);• Actualizar contador de referencias

3. execlp(“ps",“ps",”-A”,(char *)NULL); No afecta a la tabla de canales, solo es un cambio del binario

Page 21: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3

4

Canal; entrada_tfo 0 9 8 RW - 0

1 2 R - 1

2 2 3 W - 1

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

1. Cambios proceso PS: dup2(4,1)

0 0

1 0 2

2 0

3 1

4 2

Canal; entrada_tfoProceso “ps”

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “grep”

Page 22: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3

4

Canal; entrada_tfo 0 8 RW - 0

1 2 1 R - 1

2 3 2 W - 1

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

2. Cambios proceso PS: close(3);close(4);

0 0

1 2

2 0

3 1

4 2

Canal; entrada_tfoProceso “ps”

0 0

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “grep”

Page 23: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

Secuencia grep

1. 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

2. close(p[0]);close(p[1]); close(3); close(4);• Actualizar contador de referencias

3. execlp(“grep",“grep",argv[1],(char *)NULL); No afecta a la tabla de canales, solo es un cambio del binario

Page 24: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3

4

Canal; entrada_tfo 0 8 7 RW - 0

1 1 2 R - 1

2 2 W - 1

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

1. Cambios proceso grep: dup2(3,0);

0 0

1 2

2 0

3

4

Canal; entrada_tfoProceso “ps”

0 0 1

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “grep”

Page 25: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3

4

Canal; entrada_tfo 0 7 RW - 0

1 2 1 R - 1

2 2 1 W - 1

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

2. Cambios proceso grep: close(3);close(4);

0 0

1 2

2 0

3

4

Canal; entrada_tfoProceso “ps”

0 1

1 0

2 0

3 1

4 2

Canal; entrada_tfoProceso “grep”

Page 26: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

0 0

1 0

2 0

3

4

Canal; entrada_tfo 0 7 RW - 0

1 1 R - 1

2 1 W - 1

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1 2 “pipe”

2

Ent.; refs. Inodo;

Este es el estado cuando el proceso padre está en el waitpid y los hijos están haciendo el ps y el grep

0 0

1 2

2 0

3

4

Canal; entrada_tfoProceso “ps”

0 1

1 0

2 0

3

4

Canal; entrada_tfoProceso “grep”

Page 27: Como comunicar 2 procesos emparentados Mediante una pipe sin nombre

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?

0 0

1 0

2 0

3

4

Canal; entrada_tfo 0 3 RW - 0

1

2

3

4

5

Proceso inicial

Ent.; refs. Modo; l/e; Ent. T.Inodo0 1 “tty”

1

2

Ent.; refs. Inodo;

Cuando un proceso terminase cierran todos los canalesque le queden abiertos