0% encontró este documento útil (0 votos)
13 vistas5 páginas

000 LinuxIPCTutorial

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
13 vistas5 páginas

000 LinuxIPCTutorial

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 5

Tutorial: Comunicación entre procesos en Linux

Iñaki Rañó

Notas
Esta práctica se debe realizar en GNU/Linux, y se utilizarán comandos básicos de bash que
permitirán a cierto nivel “programar” en bash, ası́ que ya puedes abrir una terminal para comenzar
este tutorial.
Es necesario completar las tareas y responder de forma justificada y breve a las preguntas
indicadas (QXX) y entregar a través del Campus Virtual un documento en formato texto, doc o
pdf con las respuestas:
A01: Aquı́ la respuesta a la pregunta Q01
A02: Aquı́ la respuesta a la pregunta Q02

1 Encadenando comandos con | (pipe)


Todos los programas que se ejecutan en Linux (procesos) tienen asociados tres flujos de datos
estándar (standard streams) llamados entrada estándar (stdin), salida estándar (stdout) y salida
de error estándard (stderr). Estos flujos de datos estándar tienen asociados descriptores de
ficheros o variables como los de C++: std::cin, std::cout y std::cerr. Algunos programas no
requiren flujo de entrada y normalmente los que lo requieren lo toman del teclado. Por ejemplo,
el comando cat se usa para mostrar el contenido de un fichero (que es el flujo de entrada) por
pantalla, pero se puede ejecutar sin argumentos. Teclea en una terminal:

$ cat

Intenta escribir algo. (Q01) ¿Qué es lo que sucede? Para salir puedes usar ctrl-c o
ctrl-d1 . Al ejecutar programas desde una terminal tanto la salida como la salida de error
estándar aparecen en la terminal en forma de texto. Por ejemplo, si tecleas:

$ ls -la

verás la lista de ficheros en el directorio actual (incluidos los ocultos) que aparece en la salida
estándar. Pero si tecleas

$ ls -l este\_fichero\_no\_existe

el texto aparecerá en la salida de error estándar2 .


Olvidando la salida de error estándar, podemos redirigir la salida estándar a un fichero a través
del operador de redirección “>”, por ejemplo si en la terminal tecleas:

$ ls -lR /usr > kk


$ ls -lh kk
1
Esta combinación de teclas es interpretada como fin de transmisión, y puede usarse p.e. para cerrar terminales
o sesiones en Linux
2
A no ser que haya un fichero llamado ası́ en el directorio en el que estás.

1
puedes ver dos cosas: 1) el primer comando tarda bastante y 2) el fichero kk es bastante
pesado. El fichero kk contiene la salida del comando ls -lR /usr que muestra recursivamente
(opción R) los ficheros en el directorio /usr incluyendo tamaño, permisos, propietario. . . Para ver
el contenido de kk puedes usar los comandos cat, more o less.

$ cat kk
$ more kk
$ less kk

Si no conocı́as los comandos more o less para salir/terminar el programa puedes pulsar la
tecla ‘q’, mientras que el comando cat se puede parar con ctrl-c. El otro operador de redirección
es “>>” que a diferencia del anterior no borra el contenido del fichero al que se redirige la salida,
añade la salida al final del fichero.
El problema al ejecutar cat kk es que la información se muestra demasiado rápido por la
terminal. Esto se puede resolver usando el operador pipe (tuberı́a) en Linux, por ejemplo:

$ cat kk | less

Aunque el resultado de ejecutar este comando es el mismo que less kk, lo que pasa inter-
namente es muy diferente. La salida estándar del comando cat kk es pasada por bash como
entrada al comando less a través del operador pipe. En realidad el operador pipe se puede usar
para encadenar otros comandos, redirigiendo la salida de uno a la entrada de otro, por ejemplo:

$ cat kk|grep "\.hpp"|sed ’s/hpp/h/’|cut -d ’ ’ -f 12

Esta cadena de comandos hace lo siguiente:

1. cat kk muestra el contenido del fichero kk

2. grep "_
hpp" muestra las lı́neas de texto que contienen el la cadena “.hpp”

3. sed ’s/hpp/h/’ reemplaza (substituye) el texto “hpp” por “h”

4. cut -d ’ ’ -f 12 toma el campo/columna número 12 de un texto separado por espacios

Prueba a ejecutar los comandos uno a uno y entender qué es lo que hace cada uno de ellos.
Como puedes ver el operador pipe (|) permite automatizar muchas operaciones cuando se en-
cadenan secuencias de comandos simples, pero la lección principal es la existencia del operador
pipe, que es un mecanismo de comunicacion entre procesos.
(Q02) Crea una serie de comandos usando el operador pipe que encuentre el múmero
de ficheros con permiso de lectura, escritura y ejecución (rwx, no pueden ser enlaces
simbólicos) en el directorio /usr de Linux combinando los comandos ls, grep y wc.
Hint 1: El comando grep selecciona lı́neas de texto que contienen una cadena de caracteres,
pero con la opción -v selecciona las que no contienen la cadena.
Hint 2: El comando wc cuenta caracteres (opción -c), palabras (opción -w) y lı́neas (opción
-l) de un fichero de texto o la entrada estándar.

2 Programas, procesos y señales en Linux (kill)


Cuando se ejecuta un programa desde una terminal en Linux normalmente la terminal se bloquea
hasta que el programa termina. Por ejemplo, si abres una terminal y ejecutas el editor de texto
emacs:

$ emacs

2
aparece la ventana de emacs pero ya no se puede utilizar esa terminal. Para que bash siga
aceptando comandos puedes terminar el programa usando desde la terminal la combinación de
teclas ctrl-c (lo que termina el programa) o ctrl-z (lo que para la ejecución del programa). Ctrl-c
cierra la ventana de emacs, mientras que al pulsar ctrl-z emacs deja de responder, i.e. no se puede
utilizar. En cualquier caso bash sigue aceptando comandos. Si has interrumpido la ejecucion de
emacs puedes hacer que vuelva a responder usando el comando fg (foreground).

$ emacs # pulsa ctrl-z


^Z
[1]+ Stopped emacs
$ fg
emacs

Cuando se para un proceso con ctrl-z, para poder seguir usando la terminal mientras el pro-
grama sigue corriendo se utilizar el comando bg (background). Si repites los pasos anteriores
pero usas bg en vez de fg verás que la ventana de emacs ahora responde. Esto se puede hacer
para cuantos programas quieras, y cada uno de los procesos parados o ejecutandose en back-
ground pueden verse con el comando jobs.

$ emacs # pulsa ctrl-z


^Z
[1]+ Stopped emacs
$ bg
[1]+ emacs &
$ jobs
[1]+ Running emacs &
$

Prueba a ejecutar el comando jobs parando el programa con ctrl-z pero sin ejecutar bg. Todo
este proceso se puede simplificar si desde el principio se usa el operador & después del programa
a ejecutar, por ejemplo:

$ emacs &

Esta forma de ejecución corre directamente el programa en background, y también aparece


al ejecutar el comando jobs. Como una nota, cada proceso que corres en background tiene
asociado un ı́ndice (que aparece entre corchetes [1]). Si hay varios procesos parados se pueden
ejecutar los comandos fg y bg indicando a qué proceso nos referimos usando el sı́mbolo % (p.e.
fg %2).
Como veremos, cada programa que se ejecuta en Linux (proceso) tiene asociado un PID
(IDentificador de Proceso, número natural) único que se puede encontrar usando el comando
ps3 . En el fichero “zip” correspondiente a esta sesión de laboratorio contiene una carpeta con un
fichero C y un fichero de compilación makefile. Descomprime esta carpeta y desde una terminal
(estando en el directorio src) ejecuta make para compilar el programa y después ejecutalo:

$ cd [directoriobase]/src
$ make
$ ./funny-program

Este programa simplemente incrementa un contador cada segundo, pero nos será útil para
ver cómo funciona el comando kill en Linux. Cuando ejecutas el programa puedes usar las
combinaciones de teclas ctrl-c o ctrl-z para interrumpir su ejecución o pararla respectivamente.
3
Este número es distinto del ı́ndice anterior de procesos en una terminal.

3
Comprueba que puedes usar los comandos que hemos visto anteriormente para poner el proceso
en background o foreground tras pulsar ctrl-z en la terminal.
El comando kill se usa para mandar señales a procesos en Linux (y otros sistemas Unix)4 .
Como veremos, las señales son un mecanismo de comunicación software muy sencillo que imitan
el funcionamiento de interrupciones hardware. Para mandar una señal a un proceso necesitas
conocer su PID. En este caso vendrá bien tener dos terminales abiertas, una donde se ejecutará
el programa y otra desde donde se le mandarán señales. Ası́ en la primera terminal ejecuta el
programa:

$ ./funny-program

y en la segunda terminal escribe:

$ ps u|grep funny
[PID] [terminal] [estado] [tiempo] ./funny-program
$ kill -9 [PID]

Donde los elementos entre corchetes ([]) dependen de tu ordenador, terminal. . . y [PID] es
el número natural que identifica al proceso5 . La señal 9 es solo una de las differentes señales
que se puede mandar a un proceso. Ejecuta el programa otra vez y cambia el argumento de kill
para mandar al proceso las señales 10, 12 y 14. Observa el comportamiento del programa y lee
el código fuente. (Q03) ¿Puedes explicar lo que está pasando? (para entenderlo puedes leer
las páginas del manual de la función signal() y el comando kill, man signal y man kill).
El programa funny-program puede ejecutarse con un argumento (o más) que en realidad son
ignorados, pero que cambian el modo en que el proceso corre. Por ejemplo, puedes ejecutarlo:

$ ./funny-program cualquiercosa

Ahora intenta parar el proceso (con ctrl-c) o suspenderlo (con ctrl-z). (Q04) ¿Que ocurre?
¿Como se te ocurre que se puede parar la ejecucion del proceso?
El comando top muestra en una tabla información variada sobre los procesos que se es-
tan ejecutando en Linux generalmente ordenados según el uso de CPU (de mayor a menor).
Abre una nueva terminal y ejecuta el comando top, en la primera terminal ejecuta el programa
funny-program y observa si aparece listado entre los procesos que más CPU requieren. En la
segunda terminal ejecuta el comando kill enviando al PID correspondiente a funny-program la
señal número 14, i.e. kill -14 [PID]. (Q05) ¿Qué sucede? ¿Aparece ahora funny-program
entre los procesos que más CPU consumen? ¿Por qué?
Hint: Cuando un programa llama a la función sleep() el proceso no consume CPU durante
los segundos que se usan como argumento de la función).

3 Crear un chat en una lı́nea de código bash


El último mecanismo de comunicación que usaremos en este tutorial son las tuberı́as con nombre
(named pipes) que veremos más adelante. El comando | es un tipo de tuberı́a que se llama
anónima y permite encadenar la salida de un proceso a la entrada del siguiente. Las tuberı́as
con nombre se pueden usar para enviar datos (e.g. texto) entre procesos que conocen el nombre
de la tuberı́a y son estructuras FIFO (First In First Out). Para crear una tuberı́a con nombre en
lı́nea de comando se usa el comando mkfifo seguido del nombre de la tuberı́a6 , por ejemplo:
4
El uso más común de este comando es terminar la ejecución de un proceso que no responde, kill -9 [PID] o
kill -15 [PID]
5
Ya sabes qué hace ps a|grep funny.
6
Para que procesos de distintos usuarios puedan acceder a la tuberı́a suele crearse en directorios de acceso
universal como /tmp, aunque para esta sesión eso no es importante.

4
$ mkfifo /tmp/myNamedPipe

Si hacemos ahora un ls -l /tmp/myNamedPipe veremos que los permisos que se muestran


son prw-rw-rw-, donde el primer caracter indica el tipo de fichero d para directorio, - para un
fichero ordinario, c para un dispositivo de caracteres, y p para named pipes.
Ahora que nuestra tuberı́a con nombre esta creada podemos enviar mensajes a través de
ella. Por ejemplo, si abrimos dos terminales y el la primera escribimos:

$ cat /tmp/myNamedPipe

haremos que cualquier texto que entre en la tuberı́a aparezca en la terminal. Como aún no
hemos mandado nada el comando cat se queda bloqueado a la espera. Ahora en la segunda
terminal introducimos el comando:

$ cat > /tmp/myNamedPipe

que redirecciona la entrada estándar a la tuberı́a, lo que permite escribir texto que se enviará a
la tuberı́a. En la segunda terminal escribe unas lı́neas de texto (terminalas con enter) y observa
qué pasa. Si escribes ahora algo en la primera terminal y pulsas enter verás que no pasa nada.
Para terminar los procesos y cerrar la tuberı́a hay dos opciones, ambas a usar en la segunda
terminal: 1) pulsar ctrl-c, lo cual hace que el primer proceso termine o 2) pulsar ctrl-d que manda
el comando de fin de transmisión. En cualquier caso el comando de la primera terminal también
finaliza (lo cual no ocurre si usas ctrl-c en la primera). Al enviar el comando de fin de transmision
la terminal que recibe el texto entiende que el “fichero” que tiene que mostrar ha terminado. Como
has podido ver la comunicación a través de tuberı́as con nombre (o sin nombre for that matter )
es unidireccional, es decir un proceso manda información y el otro la recibe.
El objetivo de esta parte de la sesión es implementar un chat sencillo en el que debe haber co-
municación bidireccional, lo cual implica la creación de dos tuberı́as con nombre, p.e. /tmp/pipe1
y /tmp/pipe2 de forma que un usuario escribe en una y lee de la otra, mientras que el segundo
usuario lo hace al revés. También se necesitan dos terminales, una para cada usuario del chat,
en la que los usuarios escribirán alternativamente de forma indefinida (o hasta que uno pulse
ctrl-c). Una vez creadas las dos tuberı́as, el código que debe usar el primer usuario (desde la
primera terminal) es:

$ while :; do cat > /tmp/pipe1 ; cat /tmp/pipe2 ; done

que ejecuta un ciclo sin fin (while :; do ... ; done) en el que manda la entrada del teclado
(entrada estándar) a la tuberı́a /tmp/pipe1 y lee de la tuberı́a /tmp/pipe2.
(Q06) ¿Cuál es la lı́nea que debe ejecutar el usuario de la otra terminal para que el chat
funcione? ¿Qué debe pulsar cada usuario para dejar escribir al otro? ¿Puede un tercer
usuario que conozca el nombre de la tuberı́a leer la conversacion? ¿Como?

También podría gustarte