1 amelia guillén rodríguez michael kokaly kokaly linux : pipe

37
1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

Upload: fidelia-razon

Post on 28-Jan-2016

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

1

Amelia Guillén Rodríguez

Michael Kokaly Kokaly

Linux : Pipe

Page 2: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

2

PIPE : INTRODUCCION

• Transmisión de datos entre procesos a través de un canal : datos escritos en un extremo se leen en el otro extremo.

• Podemos comparar tuberías con una cola FIFO de caracteres.

Page 3: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

3

PIPE:INTRODUCCION

• Las tuberías no ofrecen comunicación estructurada.

• Desventaja : lectura de datos independiente de la escritura.

• Ventaja : permite leer de una sola vez los datos escritos en varias ocasiones.

• La gestión de las tuberías esta integrada en el sistema de archivos.

• Acceso a las tuberías por descriptores de entrada/salida : uno para lectura en la tubería y otro para la escritura en la tubería

Page 4: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

4

TUBERIAS : TIPOS

• Tubería anónima :

• Creada por un proceso.

• Transmisión de descriptores sólo por herencia hacia sus descendientes.

• Mecanismo restrictivo : sólo comunicación entre procesos cuyo antecesor común es el creador de la tubería.

Page 5: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

5

TUBERIAS : TIPOS

• Tubería con nombre :

• Existen físicamente en el sistema de archivos.

• Se manipulan como archivos respecto a operaciones de apertura,cierre,lectura y escritura,por lo que no existe la restricción de las anónimas.

• Para identificar un archivo tipo tubería con nombre utilizamos el atributo p del comando ls.

Page 6: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

6

TUBERIAS ANONIMAS.CREACION

• Llamada pipe para crear una tubería anónima.

• Para poder crearla se pasan como parámetro una tabla de dos enteros :

#include <unistd.h> int pipe (int filedes[2]);

• Si la llamada ha sido exitosa filedes[0] contendrá el descriptor de lectura y filedes[1] contendrá el descriptor de escritura.

Page 7: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

7

TUBERIAS ANONIMAS CREACION : ERRORES

• La llamada pipe puede generar errores :

• EFAULT : La tabla pasada como parámetro no es válida.

• EMFILE : Se ha alcanzado el número máximo de archivos abiertos para el proceso actual.

• ENFILE : Se ha alcanzado el número máximo de archivos abiertos en el sistema

Page 8: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

8

TUBERIAS ANONIMAS

• Se pueden utilizar funciones de alto nivel para operaciones de lectura y escritura : printf,scanf,sprintf…

• Problemas : todo carácter escrito no está disponible en el otro extremo de inmediato ya que usan memorias intermedias.

Page 9: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

9

TUBERIAS ANONIMAS

• La llamada al sistema close permite cerrar descriptores inutilizados.

• El proceso lector queda bloqueado hasta que lee la cantidad de datos precisa en la llamada read.

Page 10: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

10

TUBERIA ANONIMA:CREACION TUBERIA-EJECUCION

PROGRAMA

• Una tubería puede emplearse para comunicarse con un programa externo.

• Para ello dos funciones de biblioteca :

#include <stdio.h>

FILE *popen (const char *command, const char *type);

int pclose (FILE *stream);

• Popen crea una tubería y un proceso hijo.

• El proceso hijo ejecuta el comando especificado por command.

• Pclose cierra la tuberia (fclose) y finaliza el proceso hijo asociado

Page 11: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

11

TUBERIA ANONIMA:CREACION TUBERIA-EJECUCION

PROGRAMA• Popen devuelve un descriptor de entradas/salidas

correspondiente a la tubería, según el valor de parámetro type:

• Si type es la cadena <<r>>, el descriptor es accesible en lectura, y permite acceder a la salida estándar del mandato.

• Si type es la cadena <<w>>, el descriptor es accesible en escritura, y permite acceder a la entrada estándar del mandato.

Page 12: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

12

IMPLEMENTACION

• Desde el punto de vista de i-nodo de una tubería, el campo i_pipe se pone a 1, lo que identifica el tipo de i-nodo.

• El campo u del i-nodo está constituido, en el caso de una tubería (anónima o no), por la estructura pipe_inode_info descrita en el archivo <linux/pipe_fs_i.h>.

• El tamaño de la tubería se limita a 4 KB (valor de la constante PIPE_BUF definida en el archivo <linux/limits.h>).

• Este límite corresponde al valor límite para la realización de una escritura atómica en la tubería. El usuario puede escribir más datos en la tubería, pero dejará de tener garantizada la atomización de la operación.

Page 13: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

13

PIPE_INODE_INFOTipo Campo Descripción

Struct wait_queue* Wait Sincroniza los accesos concurrentes a la tubería

Char* Base Puntero a la página de memoria destinada a los datos

Unsigned int Start Posición en la página de memoria

Unsigned int Len Número de bytes es espera en la tubería

Unsigned int Lock Bloqueo sobre la tubería

Unsigned int Rd_openers Número de procesos que han abierto la tubería con nombre en lectura

Unsigned int Wr_openers Número de procesos que han abierto la tubería con nombre en escritura

Unsigned int Readers Número de procesos que tienen acceso en lectura a la tubería

Unsigned int writers Número de procesos que tienen acceso en escritura a la tubería

Page 14: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

14

DO_PIPEint do_pipe(int *fd) { … struct inode * inode;struct file *f1, *f2;int error;…error = -ENFILE;f1 = get_empty_filp();if (!f1)goto no_files;f2 = get_empty_filp();if (!f2) goto close_f1;inode = get_pipe_inode(); //creación del i-nodo de 1

tuberíaif (!inode)goto close_f12;error = get_unused_fd();

Page 15: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

15

DO_PIPE

if (error < 0)goto close_f12_inode; i = error;error = get_unused_fd();if (error < 0)goto close_f12_inode_i; j= error;Error= -ENOMEM;sprintf(name, "[%lu]", inode->i_ino);//Escribe el número

que caracteriza el inodethis.name= name;…dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);if (!dentry)….d_add(dentry, inode); //Añade el inode al directorio dentry

Page 16: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

16

GET_PIPE_INODE(fs/pipe.c)

static struct inode* get_pipe_inode(void)

{//crea el inodo

struct inode *inode = new_inode(pipe_mnt->mnt_sb);

if (!inode)

goto fail_inode;

if(!pipe_new(inode)) //asigna una pagina de memoria para contener los datos

goto fail_iput;

//inicializaciones

PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;

inode->i_fop = &rdwr_pipe_fops; //operaciones

Page 17: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

17

GET_PIPE_INODE(fs/pipe.c)

inode->i_state = I_DIRTY;

inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;

inode->i_uid = current->fsuid;

inode->i_gid = current->fsgid;

inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;

inode->i_blksize = PAGE_SIZE;

return inode;

Page 18: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

18

fail_iput:

iput(inode);

fail_inode:

return NULL;

}

GET_PIPE_INODE(fs/pipe.c)

Page 19: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

19

struct inode* pipe_new(struct inode* inode)

{

unsigned long page;

page = __get_free_page(GFP_USER);//asigna 1 pagina de memoria para contener los datos

if (!page)

return NULL;

inode->i_pipe = kmalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);//Crea la estructura pipe_inode_info

if (!inode->i_pipe)

goto fail_page;

PIPE_NEW(fs/pipe.c)

Page 20: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

20

init_waitqueue_head(PIPE_WAIT(*inode));PIPE_BASE(*inode) = (char*) page;PIPE_START(*inode) = PIPE_LEN(*inode) = 0;PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;PIPE_WAITING_READERS(*inode)=

PIPE_WAITING_WRITERS(*inode) = 0; PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;return inode; fail_page: free_page(page); return NULL; }

PIPE_NEW(fs/pipe.c)

Page 21: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

21

TUBERIAS CON NOMBRECREACION

• Prototipo función mkfifo :

#include <sys/stat.h>

int mkfifo (const char *path, mode_t mode);

• Esta función se implementa con la llamada mknod.

mknod (path, mode | S_IFIFO, 0);

• Las tuberías con nombre permiten e/s con bloqueo o sin bloqueo.

• Para no bloqueo especificar opción O_NODELAY o O_NONBLOCK al abrir con open.

• Salvo lseek todas las operaciones de manipulación de un archivo son válidas.

Page 22: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

22

IMPLEMENTACION :TUBERIAS CON NOMBRE

• La creación de una tubería con nombre corresponde a la creación de un archivo cualquiera, y se detalla en el archivo fs/fifo.c.

• Las operaciones de lectura y de escritura se encuentran en el archivo destinado a las tuberías anónimas fs/pipe.c.

Page 23: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

23

IMPLEMENTACION :Creación tubería con nombre

• La creación de una tubería con nombre se efectúa por la función fifo-open, definida en el archivo fuente fs/fifo.c. Esta función se llama mediante la función de inicialización de una tubería con nombre: init_fifo.

• La creación de una nueva tubería con nombre depende de las opciones de la creación. Las operaciones autorizadas sobre el i-nodo se fijan en función de estas opciones.

• Lectura exclusiva: connecting_fifo_fops en el caso de una lectura sin bloqueo, read_fifo_fops en caso contrario

• Escritura exclusiva: write_fifo_fops• Lectura y escritura: rdwr_fifo_fops

Page 24: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

24

FIFO_OPEN(fs/fifo.c)Static int fifo_open(struct inode *inode, struct file *filp) { int ret;

ret = -ERESTARTSYS; lock_kernel(); if (down_interruptible(PIPE_SEM(*inode))) goto err_nolock_nocleanup; if (!inode->i_pipe) { ret = -ENOMEM; if(!pipe_new(inode)) goto err_nocleanup; }

Page 25: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

25

FIFO_OPEN(fs/fifo.c)

switch (filp->f_mode) { case 1: //solo lectura filp->f_op = &read_fifo_fops; PIPE_RCOUNTER(*inode)++; PIPE_READERS(*inode)++; ...case 2: //solo escritura

ret = -ENXIO; ...

filp->f_op = &write_fifo_fops; PIPE_WCOUNTER(*inode)++;

PIPE_WRITERS(*inode)++; ...

Page 26: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

26

FIFO_OPEN(fs/fifo.c)case 3: // lectura y escritura

filp->f_op = &rdwr_fifo_fops; PIPE_READERS(*inode)++; PIPE_WRITERS(*inode)++;

PIPE_RCOUNTER(*inode)++; PIPE_WCOUNTER(*inode)++;

....default:

...} /* Ok! */ up(PIPE_SEM(*inode)); unlock_kernel(); return 0;

Page 27: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

27

Operaciones de entradas/salidas

• Todas las operaciones de entradas/salidas, ya se trate de tuberías con nombre o anónimas, se encuentran en el archivo fs/pipe.c.

• Las lecturas y las escrituras se efectúan en una memoria intermedia de tamaño PIPE_BUF (4KB). En función de las lecturas y escrituras de datos en la tubería, la ventana que contiene los datos de la tubería se desplaza de manera circular en el interior de la memoria intermedia.

Page 28: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

28

Operaciones de entradas/salidas

• pipe_read recorre la página de memoria de la tubería copiando los datos contenidos en la memoria intermedia destinada al usuario.

• Durante esta operación, la tubería se bloquea.

• Lectura sin bloqueo => se devuelve el error EAGAIN si la tubería está bloqueada o vacía.

• Lectura con bloqueo => el proceso que llama se queda en espera mientras la tubería esté vacía.

Page 29: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

29

Operaciones de entradas/salidas• pipe_write escritura en la tubería de datos pasados

como parámetros en la memoria intermedia, dentro del límite de tamaño restante disponible.

• Mientras dura la operación, los accesos a la tubería están bloqueados.

• Esta función efectúa un bucle hasta escribir todos los datos en la tubería.

• En cada pasada por el bucle, comprueba si quedan procesos lectores en la tubería. Si es así, se envía la señal SIGPIPE al proceso que llama. En caso contrario, la tubería se bloquea, los datos se copian desde la memoria intermedia proporcionada por quien llama, y la tubería se desbloquea.

Page 30: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

30

Operaciones de entradas/salidas

• pipe_ioctl la única operación de ioctl permitida es la designada por FIONREAD, que permite recuperar el número de bytes de datos almacenados actualmente en al tubería. Se devuelve el contenido de campo len de la escritura pipe_inode_info

Page 31: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

31

Operaciones de entradas/salidas

• pipe_select para operación de multiplexado asociada a la llamada select, esta función verifica ciertas condiciones de validez antes de indicar si es necesario volver a las entradas o salidas sobre la tubería

• multiplexado en lectura: es necesario que la tubería no esté vacía y que al menos un proceso tenga acceso a la tubería en escritura

• multiplexado en escritura: es necesario que la tubería no esté llena y que al menos un proceso tenga acceso a la tubería en lectura

• excepciones: la tubería debe ser accesible al menos por un proceso en lectura y en escritura

Page 32: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

32

Operaciones de entradas/salidas

• Se utilizan estas funciones únicamente en el contexto de las tuberías con nombre, cuando al crear la tubería, ningún proceso ha abierto la tubería en escritura:

• connect_read Sólo modifica las operaciones realizables sobre el i-nodo asignando el campo f_op a read_fifo_fops. Tras esta modificación, se lanza una llamada a la función de lectura en una tubería (pipe_read).

Page 33: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

33

Operaciones de entradas/salidas

• connect_select Esta función modifica el campo f_op en el caso del multiplexado en lectura.

Page 34: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

34

Operaciones de entradas/salidas

• Se utilizan estas funciones para cerrar descriptores:

pipe_read_release decrementa nºprocesos con acceso en lectura a la tubería

pipe_write_release decrementa nºprocesos con acceso en escritura a la tubería

pipe_rdwr_release decrementa nºprocesos con acceso en lectura y escritura a la tubería

Page 35: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

35

Operaciones de entradas/salidas

• Se utilizan estas funciones para creación de un nuevo proceso que hereda la tubería:

• pipe_read_open incrementa nºprocesos con acceso en lectura a la tubería

pipe_read_open(struct inode *inode, struct file *filp)

{

down(PIPE_SEM(*inode));

PIPE_READERS(*inode)++;

up(PIPE_SEM(*inode));

Page 36: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

36

Operaciones de entradas/salidas

• pipe_write_open incrementa nºprocesos con acceso en escritura a la tubería.

pipe_write_open(struct inode *inode, struct file *filp)

{

down(PIPE_SEM(*inode));

PIPE_WRITERS(*inode)++;

up(PIPE_SEM(*inode));

Page 37: 1 Amelia Guillén Rodríguez Michael Kokaly Kokaly Linux : Pipe

37

Operaciones de entradas/salidas

• pipe_rdwr_open incrementa nºprocesos con acceso en lectura y escritura a la tubería.

pipe_rdwr_open(struct inode *inode, struct file*filp)

{

down(PIPE_SEM(*inode));

if (filp->f_mode & FMODE_READ)

PIPE_READERS(*inode)++;

if (filp->f_mode & FMODE_WRITE)

PIPE_WRITERS(*inode)++;

up(PIPE_SEM(*inode));

}