340 likes | 504 Views
Pipes. ARISO 2 Rubén Barrio Guerrero Escola Tècnica Superior d’Enginyeria de Telecomunicació de Barcelona ( Universitat Politècnica de Catalunya). Licencia Creative Commons.
E N D
Pipes ARISO 2 Rubén Barrio Guerrero EscolaTècnica Superior d’Enginyeria de Telecomunicació de Barcelona (UniversitatPolitècnica de Catalunya)
Licencia CreativeCommons Esta obra está bajo una licencia Reconocimiento-No comercial-Compartir bajo la misma licencia 2.5 España de CreativeCommons. Para ver una copia de esta licencia, visite: http://creativecommons.org/licenses/by-nc-sa/2.5/es/ o envíe una carta a: CreativeCommons, 559 NathanAbbottWay, Stanford, California 94305, USA.
Licencia CreativeCommons Eres libre de: • copiar, distribuir y comunicar públicamente la obra • hacer obras derivadas Bajo las condiciones siguientes: • Atribución. Debes reconocer la autoría de la obra en los términos especificados por el propio autor o licenciante. • No comercial. No puedes utilizar esta obra para fines comerciales. • Licenciamiento Recíproco. Si alteras, transformas o creas una obra a partir de esta obra, solo podrás distribuir la obra resultante bajo una licencia igual a ésta. • Al reutilizar o distribuir la obra, tienes que dejar bien claro los términos de la licencia de esta obra. • Alguna de estas condiciones puede no aplicarse si se obtiene el permiso del titular de los derechos de autor Advertencia: • Los derechos derivados de usos legítimos u otras limitaciones reconocidas por ley no se ven afectados por lo anterior. • Esto es un resumen legible por humanos del texto legal (la licencia completa)
Pipes Comunicación entre Procesos
Comunicación entre procesos • Los procesos no comparten memoria • Interesa que los procesos puedan pasarse información • El SO debe ofrecer mecanismos para: • Envío/Recepción de información • Sincronización Memoria
Comunicación entre procesos • Comunicación • Envío/recepción de información • Un proceso envía información a otro proceso • Ambos procesos conocen el formato de la información • SO: ficheros, pipes, named pipes, sockets • Sincronización • Un proceso avisa de la finalización de una tarea necesaria para que otro proceso (o él mismo) puedan realizar otra tarea • No hay información relacionada, solamente es un aviso (evento) • SO: signals, pipes, sockets
Pipes Teoría
Pipe • Una pipe es un buffer circular de bytes • Sirve para comunicar 2+ procesos entre sí Los datos que se leen de la pipe desaparecen • Dependiendo de la implementación pueden ser: • Unidireccionales: solo se puede leer o solo escribir • Bidireccionales: se puede leer y escribir PIPE desaparece crece lectura escritura
Pipe • Tipos de Pipes • Named Pipes • [Unnamed] Pipes • Procesos emparentados • Pipes • Named pipes • Procesos NO emparentados • Named pipes
Named Pipes • Utilizadas por dos procesos cualquiera • Emparentados o no • Tienen una representación en el sistema de ficheros • Crear un fichero especial (named_pipe) • Solamente es necesario crear una vez este fichero • Se abre como un fichero normal (open) • Se trabaja con él como si fuese un fichero normal (read, write, close)
Named Pipes intmknod (char *nompipe, int mode, dev_tdevice) • Crea un dispositivo (genérico), lo usaremos sólo para pipes • nompipe: nombre que tendrá el fichero tipo pipe • mode: indica que es una pipe y las protecciones del fichero • device: no es necesario ponerlo en el caso de una pipe • Devuelve 0 si OK y –1 si ERROR Ejemplo: mknod(“mi_pipe”,S_IFIFO|0666,0) • Después ya se puede abrir como un fichero normal: Ejemplo: open(“mi_pipe”, O_RDONLY)
Named Pipes • Necesitan 1+ lector y 1+ escritor • 2 opens en 2 procesos diferentes • open (“nam_pip”, O_RDONLY) • open (“nam_pip”, O_WRONLY) Tabla de i-nodos virtuales Tabla de ficheros abiertos Tabla de canales I-nodo especial para NAMED PIPES
Pipes [Unnamed] • Utilizadas por dos procesos emparentados • Padre-hijo, padre-nieto, hermano-hermano • No tienen representación en el sistema de ficheros • Son buffers en memoria del SO • Se crea y se abre a la vez
Pipes [Unnamed] int pipe (intfd[2]); • Llamada a sistema que devuelve dos canales ya abiertos • Abre dos canales de acceso a una pipe • fd[0] canal de sólo lectura • fd[1], canal de sólo escritura • Devuelve 0=OK, -1=Error • Lo que se escribe en fd[1] se lee por fd[0] write(fd[1],...) read(fd[0],...)
Pipes [Unnamed] • Necesitan 1+ lector y 1+ escritor • intfds[2]; • pipe(fds); Tabla de ficheros abiertos Tabla de canales Buffers de SO
Llamadas a sistema E/S • Open: bloquea hasta que exista la pareja • Solo se usa open con named pipes • Read(Si la pipe está vacía): • Si ningún procesola tiene abierta para escritura devuelve 0 • Si existeESCRITOR nos bloqueamos hasta: • Alguien escriba • Se desbloquea y lee lo escrito • Los ESCRITORES desaparecen • Devuelve 0
Llamadas a sistema E/S • Write: • Si escribimos en una pipe que no tiene lectores devuelve –1 y errno=EPIPE y el proceso recibe un evento (signal) SIGPIPE • Si la pipe está llena el proceso se bloquea • Lseek • No se aplica a las pipes
Pipes Ejercicios solucionados
Ejercicio 1 • Escribe un programa donde un proceso reciba 2 ficheros como parámetros. Este leerá el fichero de entrada (1er parámetro) y enviará todos los bytes leídos a un segundo proceso mediante una PIPE. El segundo proceso escribirá un fichero (2º parámetro) solo con las vocales que reciba por la pipe, desechando las demás.
Ejercicio 1 main() { int pid,fd1,fd2,pipefd[2]; char c; pipe(pipefd); pid = fork(); if (pid > 0) { close(pipefd[0]); fd1 = open(argv[1], O_RDONLY); while(read(fd1, &c, 1)>0) { write(pipefd[1], &c, 1); } close(fd1); close(pipefd[1]); }
Ejercicio 1 else { close(pipefd[1]); fd2 = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600); while (read(pipefd[0],&c,1) > 0) { if ((c=='a')||(c=='e') /* || .. */ ) { write(fd2,&c,1); } } close(fd2); close(pipefd[0]); } }
Ejercicio 2 • Escribe un programa que cree tantos hijos como se le indique (1er parámetro). Cada hijo le enviará al padre su PID mediante una PIPE y luego morirá. El padre escribirá en un fichero (2º parámetro) de manera explicativa todos los identificadores que le lleguen por la PIPE.
Ejercicio 2 main(intargc, char *argv[]) { intfd[2], hijos, i, fd2, pid; char s[80]; hijos=atoi(argv[1]); if (pipe(fd) < 0) { exit(0); } for (i=0; i<hijos; i++) { switch (fork()) { case -1: printf(“Error fork”); exit(0); case 0: pid=getpid(); write(fd[1], &pid, sizeof(pid)); close(fd[0]);close(fd[1]); exit(0); } }
Ejercicio 2 close(fd[1]); fd2=open(argv[2], O_WRONLY|O_CREAT|O_TRUNC,0600); for (i=0; i<hijos; i++) { read(fd[0], &pid, sizeof(pid)); sprintf(s, "Pidleido = %d\n", pid); write(fd2, s, strlen(s)); } close(fd[0]); close(fd2); }
Ejercicio 3 • Escribe un programa que emule el comportamiento del shell de manera que pueda enlazar con una PIPE dos comandos. > comando1 | comando2 > ./ejer1 comando1 comando2
Ejercicio 3 intmain(intargc,char **argv) { intfd[2]; pipe(fd); if (fork() == 0) { close(0); dup(fd[0]); close(fd[0]); close(fd[1]); execlp(argv[2], argv[2], NULL); exit(0); } if (fork() == 0) { close(1); dup(fd[1]); close(fd[0]); close(fd[1]); execlp(argv[1], argv[1], NULL); exit(0); } close(fd[0]); close(fd[1]); wait(NULL); wait(NULL); }
Ejercicio 1 v. Named • Escribe un programa donde un proceso reciba 2 ficheros como parámetros. Este leerá el fichero de entrada (1er parámetro) y enviará todos los bytes leídos a un segundo proceso mediante una NAMED_PIPE. El segundo proceso escribirá un fichero (2º parámetro) solo con las vocales que reciba por la pipe, desechando las demás.
Ejercicio 1 v. Named main() { int pid,fd1,fd2,fdpipe; char c; mknod("ej1.pipe",S_IFIFO|0666,0); pid = fork(); if (pid > 0) { fd1 = open(argv[1], O_RDONLY); fdpipe = open("ej1.pipe", O_WRONLY); while(read(fd1, &c, 1)>0) { write(fdpipe, &c, 1); } close(fd1); close(fdpipe); }
Ejercicio 1 v. Named else { fd2 = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600); fdpipe = open("ej1.pipe", O_RDONLY); while (read(fdpipe,&c,1) > 0) { if ((c=='a')||(c=='e') /* || .. */ ) { write(fd2,&c,1); } } close(fd2); close(fdpipe); } }
Ejercicio 4 • Como pasarías información de un proceso a otro lanzados en shells diferentes? Queriendo simular la siguiente operación. > ls –lisa | sort
Ejercicio 5 • Escribe un programa donde un padre (viejo) genere tantos hijos (palomas) como reciba en su primer parámetro. • El viejo tirará 100 granos de maíz para alimentar a las palomas. Las palomas deben competir por el alimento, de manera que cada grano de maíz solo puede ser “comido” por una paloma. • Al final, el abuelo espera a que las palomas se coman todo el maíz antes de irse. • Cada paloma se quedará comiendo hasta que no haya más maíz, una vez finalizada la papelina, anunciará cuantos granos ha comido y emprenderá el vuelo.
Ejercicio 5 intmain (intarvc, char *argv[]) { intnum,pipefd[2],i,val,total=0,pid; char c; num=atoi(argv[1]); pipe(pipefd); for(i=0;i<num;i++) { pid = fork(); if (pid==0) { close(pipefd[1]); do { num=read(pipefd[0],&val,sizeof(int)); if(num>0) total=total+val; } while(num>0); close(pipefd[0]); printf("Hijo %d (%d): %d\n",i,getpid(),total); exit(0); } }
Ejercicio 5 close(pipefd[0]); val=1; for(i=0;i<100;i++) { write(pipefd[1],&val,sizeof(int)); } close(pipefd[1]); for(i=0;i<num;i++) wait(NULL); }
Ejercicio 5 • Que habría que cambiar para que las palomas no dijesen nada (printfs), y fuese el viejo el que escribiese cuantos granos ha comido cada paloma?