000 LinuxIPCTutorial
000 LinuxIPCTutorial
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
$ 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
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:
2. grep "_
hpp" muestra las lı́neas de texto que contienen el la cadena “.hpp”
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.
$ 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).
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.
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 &
$ 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
$ 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).
4
$ mkfifo /tmp/myNamedPipe
$ 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:
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:
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?