Entender los mecanismos de creación y terminación de procesos de Unix.
Compile el programa fork.c:
/* fork.c */
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char* argv[]) {
int i, j, pid, salida;
char c;
for (i=1; i<argc; i++) {
if ((pid= fork())==0) {
if ((salida = open(argv[i], O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) {
write(2, "Error\n", 6);
exit(1);
}
for (j=0; j < 100000; j++) {
c= 'A' + i - 1;
write(salida, &c, 1);
}
exit(0);
}
}
exit(0);
}
y ejecútelo de diversas maneras, explicando los resultados. Pruebe, por ejemplo, con:
./fork f1 f2 f3 f4 f5 f6
./fork /dev/tty
./fork /dev/tty /dev/tty /dev/tty /dev/tty
Note que /dev/tty
es un seudodispositivo asociado siempre
al terminal de control.
Puede vigilar también su ejecución
con strace
, usando las opciones -f
, para seguir todos
los procesos, y -tt
para ver los tiempos en que ocurren las cosas
(disminuya el contador de escrituras a un valor pequeño, para no generar
un fichero demasiado grande).
Lance ahora varias ventanas (xterm
)
y determine el dispositivo asociado a cada
una de ellas con el programa tty
. Ejecute de nuevo el programa
fork
pasándole como argumento todas las ventanas, y observe el
comportamiento. Por ejemplo:
./fork /dev/ttyp1 /dev/ttyp2 /dev/ttyp3
Ahora ejecute de alguna forma inteligente la siguiente modificación, explicando el resultado:
/* forkwait.c */
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
int i, j, pid, salida, estado;
char c;
for (i=1; i<argc; i++) {
if ((pid= fork())==0) {
if ((salida = open(argv[i], O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) {
write(2, "Error\n", 6);
exit(1);
}
for (j=0; j < 100000; j++) {
c= 'A' + i - 1;
write(salida, &c, 1);
}
exit(0);
}
printf("Arrancado el proceso %d\n", pid);
}
for (i=1; i<argc; i++) {
pid = wait(&estado);
printf("Termina el proceso %d\n", pid);
}
exit(0);
}
Modifique el programa de copia de ficheros de la práctica anterior, para que la copia la haga un proceso hijo. El principal sólo lo lanzará y esperará a que termine.