Anda di halaman 1dari 30

DOCTORADO EN INFORMTICA

PROGRAMACIN DE SISTEMAS UNIX: COMUNICACIN ENTRE PROCESOS RAMN M. GMEZ LABRADOR


JUNIO 1.996

NDICE.
1. PROCESOS.
1. 2. 3. 4. Conceptos generales. Ejecucin de comandos. 1. Subrutina system. 2. Subrutinas exec. Creacin de procesos. 1. Subrutina fork. 2. Subrutinas wait y waitpid. Terminacin de un proceso. 1. Subrutina exit. 2. Subrutina atexit.

2. SEALES.
1. 2. 3. Conceptos generales. Lista de las seales ms importantes. Capturar seales. 1. Subrutina signal: 2. Subrutina sigaction: 3. Subrutina kill: Alarmas y temporizadores. 1. Subrutinas alarm y ualarm: Tratamiento de errores. 1. Lista de errores ms importantes. 2. Subrutina perror:

4. 5.

3. PIPES (TUBERAS).
1. 2. 3. 4. Conceptos generales. Redireccin. 1. Subrutinas dup y dup2: 2. Subrutina fcntl: Comunicacin entre procesos emparentados. 1. Subrutina pipe Comunicacin entre procesos no emparentados. 1. Subrutina mkfifo:

Lista de programas.
system.c - Listar los procesos del usuario usando system. exec.c - Listar los procesos del usuario usando exec. fork.c - Ejecucin conjunta de procesos padre e hijo. fork_huerf.c - Ejemplo de proceso hurfano. waitpid.c - Esperar la terminacin de un proceso hijo.

atexic.c - Ejecucin de una rutina al salir de un programa. signal.c - Contar el nmero de CTRL-C en 15 segundos. kill.c - Ejecucin con tiempo de espera usando kill. alarm.c - Esperar una alarma. dup2.c - Redireccin usando dup2. pipe.c - Tubera sin nombre entre procesos padre e hijo. pipe_conec.c - Tubera entre 2 comandos usando pipe. lector_fifo.c - Tuberia con nombre usando mkfifo. escritor_fifo.c - Tuberia con nombre usando mkfifo. fifo - Carga los procesos lector y escritor en 2o plano.

1. PROCESOS.
1,1. Conceptos generales.
Proceso: programa o comando en ejecucin. Caractersticas: Un proceso consta de cdigo, datos y pila. Los procesos existen en una jerarqua de rbol (varios Hijos, un slo padre). El sistema asigna un identificador de proceso (PID) nico al iniciar el proceso. El planificador de tareas asigna un tiempo compartido para el proceso segn su prioridad (slo root puede cambiar prioridades). Ejecucin en 1er plano: proceso iniciado por el usuario o interactivo. Ejecucin en 2o plano: proceso no interactivo que no necesita ser iniciado por el usuario. Demonio: proceso en 2o plano siempre disponible, que da servicio a varias tareas (debe ser propiedad del usuario root). Proceso zombi: proceso parado que queda en la tabla de procesos hasta que termine su padre. Este hecho se produce cuando el proceso padre no recoge el cdigo de salida del proceso hijo. Proceso hurfano: proceso en ejecucin cuyo padre ha finalizado. El nuevo identificador de proceso padre (PPID) coincide con el identificador del proceso init (1).

1,2. Ejecucin de comandos.


1,2,1. Subrutina system: - Descripcin: Llamada a un intrprete para ejecutar un comando. El proceso espera a que finalice la ejecucin de la subrutina y devuelve la salida del programa ejecutado. - Formato:
#include <stdlib.h> int system (cadena) const char *cadena;

- Parmetro: cadena - Comando a ejecutar. - Devuelve: Estado de salida del programa ejecutado. -1 o 127 en caso de error. - Comentarios: a) Se crea un proceso hijo (fork) y se lanza (exec) /usr/bin/bsh, que interpreta el comando a ejecutar. b) Si la llamada se hace con camino seguro, la orden exec ejecuta el intrprete /usr/bin/tsh. c) Se ignoran las seales SIGINT y SIGQUIT y se bloquea la seal SIGCHLD. d) La salida de system no afecta a la salida de los procesos hijos del proceso ejecutor.
- Ejemplo: /* system.c - Listar los procesos del usuario usando system. */ #include <stdio.h> #include <stdlib.h> int main () { int salida; char comando[100];

/* Salida del comando */ /* Comando a ejecutar */

printf ("Ejemplo de system.\n"); sprintf (comando, "/bin/ps -fu %s", getenv ("USER")); salida = system (comando); printf ("Salida del comando: %d\n", salida); exit (salida); } Ejemplo de system.

USER ramon ramon ramon ramon Salida del

PID PPID 3638 1 10089 10600 10600 11623 11623 3638 comando: 0

TTY hft/0 hfp/0 hft/0 hft/0

CMD -ksh /bin/ps -fu ramon bsh bsh bsh system.e

Suponiendo que no existe el comando MUSHO y sustituyendo la ejecucin de system por la siguiente lnea, se obtiene la salida mostrada a continuacin. salida = system ("MUSHO BETI"); Ejemplo de system. bsh: MUSHO: no encontrado. Salida del comando: 256

1,2,2. Subrutinas exec>: - Descripcin: Ejecuta un nuevo programa en el mismo proceso. Se crea un proceso imagen sustituyendo el programa actual por el nuevo. - Formatos:
#include <unistd.h> int execl (camino, arg0 [, arg1, ...] , 0) const char *camino, *arg0, *arg1, ...; int execle (camino, arg0 [, arg1, ...] , 0, p_entorno) const char *camino, *arg0, *arg1, ...; char *const p_entorno[]; int execlp (fichero, arg0 [, arg1, ...] , 0) const char *fichero, *arg0, *arg1, ...; int execv (camino, val_args) const char *camino; char *const val_args[]; int execve (camino, val_arg, p_entorno) const char *camino; char *const val_args[], *p_entorno[]; int execvp (fichero, val_args) const char *fichero; char *const val_args[]; int exect (camino, val_arg, p_entorno)

char *camino, *val_args, *p_entorno[];

- Sufijos: L - usa lista de parmetros, el ltimo debe ser 0. V - usa matriz de parmetros generada previamente, el ltimo debe ser 0. T - trazado del programa con ptrace (en desuso). E - usa la matriz de variables de entorno. P - bsqueda utilizando la variable PATH. - Parmetros: camino - Camino completo del fichero ejecutable. fichero - Nombre del fichero ejecutable. argN - Argumento N-simo. val_args - Puntero a la matriz de argumentos. p_entorno - Puntero a la matriz del entorno. - Devuelve: -1, en caso de error. - Comentarios: a) La rutina principal (main) de un programa C ejecutable recibe los siguientes parmetros:
int main (cont_args, val_args, p_entorno) int cont_args; /* Contador de argumentos. */ char *val_args; /* Puntero a la matriz de argumentos. */ char *p_entorno; /* Puntero a la matriz del entorno. */ Las variables val_args y p_entorno son similares a las utilizadas en las subrutinas exec.

b) Esta rutina principal llama a una subrutina de iniciacin que construye la variable de entrono. Dicha variable global es accesible desde el programa declarndola de la siguiente manera: extern char **environ; Las subrutinas exec que no usan el parmetro p_entorno utilizan la variable environ. c) Los descriptores de ficheros abiertos se pasan al nuevo proceso imagen, excepto los que tengan activo el bit FD_CLOEXEC (ver fcntl). d) Las seales capturadas se reasignan a sus acciones por defecto; las ignoradas, continan siendo ignoradas (ver sigaction).

e) Si el nuevo proceso imagen tiene activo el bit SUID, la identificacin efectiva de usuario (EUID) del nuevo proceso toma el valor del identificador del propietario. Idem, si tiene activo el bit SGID. f) Los identificadores reales de usuario y de grupo (RUID y RGID) mantienen el valor que tenan en el proceso llamador. g) El prrafo anterior puede aplicarse a ficheros remotos (previa traduccin de los identificadores). h) El prrafo e) no afecta a las shell-scripts. i) El proceso nuevo mantiene las siguientes caractersticas del proceso llamador: Identificadores de proceso (PID), de proceso padre (PPID) y de grupo de procesos (PGID). Valores de prioridad (nice), de TTY y del bit de trazado. Directorio actual y directorio raz. Mscara de ficheros, limites de longitud de ficheros, lmites de recursos. Tiempos para activar alarmas y subrutinas times. Identificador de usuario de conexin.
- Ejemplo: /* exec.c - Listar los procesos del usuario usando exec. */ #include <stdio.h> #include <unistd.h> int main () { int salida;/* Salida del comando */ printf ("Ejemplo de exec.\n"); execl ("/bin/ps", "ps", "-fu", getenv ("USER"), 0); printf ("Salida del comando: %d\n", salida); exit (salida); } Ejemplo de system. USER PID ramon 3638 ramon 10739

PPID 1 3638

TTY hft/0 hft/0

CMD -ksh /bin/ps -fu ramon

Suponiendo que no existe el comando MUSHO y sustituyendo la ejecucin de execl por la siguiente lnea, se obtiene la salida mostrada a continuacin. salida = execl ("MUSHO", "BETI", 0); Ejemplo de exec. Salida del comando: -1

1,3. Creacin de procesos.


1,3,1. Subrutina fork: - Descripcin: Crea un nuevo proceso (hijo), copia casi exacta del proceso generador (padre). - Formato:
#include <unistd.h> pid_t fork ();

- Devuelve: 0 al proceso hijo y PID del hijo al proceso padre (-1, si error). - Comentarios: a) La versin BSD (en la librera libbsd.a) es:
int vfork ();

b) Atributos que hereda el proceso hijo. Entorno. Bit FD_CLOEXEC para cada descriptor de fichero. Seales capturadas. SUID y SGID. Estado de privilegios y prioridades. Libreras compartidas y segmentos de memoria compartida. PGID y TTYGID. Directorio actual y directorio raz. Mscara y lmites de medida para ficheros. Eventos y estado de auditora. Estado de depuracin. c) Atributos diferenciadores entre padre e hijo: PID nico. PPID distintos (el PPID del hijo coincide con el PID del padre). El proceso hijo tiene su propia copia de los descriptores de fichero del padre, pero comparte con ste un puntero a fichero para cada descriptor del proceso padre.

Bloqueos de proceso, texto y datos no se heredan. Las subrutinas times se ponen a 0. Las alarmas pendientes toman su valor inicial. Se eliminan las seales pendientes para el proceso hijo.
- Ejemplos: /* fork.c - Ejecucin conjunta de procesos padre e hijo */ #include <stdio.h> #include <unistd.h> main () { printf ("Ejemplo de fork.\n"); printf ("Inicio del proceso padre. PID=%d\n", getpid ()); if (fork() == 0) { /* Proceso hijo */ printf ("Inicio proceso hijo. PID=%d, PPID=%d\n", getpid (), getppid ()); sleep (1); } else { /* Proceso padre */ printf ("Continuacin del padre. PID=%d\n", getpid ()); sleep (1); } printf ("Fin del proceso %d\n", getpid ()); exit (0); } Ejemplo de fork. Inicio proceso padre. PID=8153 Inicio proceso hijo. PID=6618, PPID=8153 Continuacin proceso padre. PID=8153 Fin del proceso 6618 Fin del proceso 8153 - Ejemplo: /* fork_huerf.c - Ejemplo de proceso hurfano * #include <stdio.h> #include <unistd.h> main () { printf ("Ejemplo de proceso hurfano.\n"); printf ("Inicio del proceso padre. PID=%d\n", getpid ()); if (fork () == 0) { printf ("Inicio proceso hijo. PID=%d, PPID=%d\n", getpid (), getppid ()); sleep (1); printf ("El proceso queda hurfano. PID=%d PPID=%d\n", getpid (), getppid ()); }

else printf ("Concinuacin del padre. PID=%d\n", getpid ()); printf ("Fin del proceso %d\n", getpid ()); exit (0); } Ejemplo de proceso hurfano. Inicio proceso padre. PID=11330 Inicio proceso hijo. PID=6467, PPID=11330 Continuacin proceso padre. PID=11330 Fin del proceso 11330 $punto indicativo> El proceso queda hurfano. PID=6467, PPID=1 Fin del proceso 6467 Notas: En el ejemplo, el proceso padre no espera la finalizacin del proceso hijo y termina antes que ste. Cuando un proceso queda hurfano, el proceso de iniciacin (init) se convierte en su padre. Una vez que finaliza el proceso padre, se devuelve el control al intrprete de comandos, de ah que aparezca el mensaje del "punto indicativo". El proceso hijo no deber mandar mensajes a la consola, como ocurre en este ejemplo.

1,3,2. Subrutinas wait y waitpid: - Descripcin: Espera a que pare o termine un proceso hijo, permitiendo obtener sus estados de salida. Una seal no bloqueada o no ignorada puede reactivar el proceso padre. - Formato:
#include <sys/wait.h> pid_t wait (estados) int *estados; pid_t wait ((void *) 0); pid_t waitpid (PID, estados, opciones) pid_t PID; int *estados, opciones;

- Parmetros:< PID - PID del proceso o grupo de proceso. Sus valores son: -1: waitpid acta igual que wait, esperando cualquier hijo. >0: PID de un proceso hijo determinado. 0: para cualquier hijo con el mismo grupo de procesos que el padre. <-1: para cualquier hijo cuyo grupo de proceso sea igaul al valor absoluto de PID. opciones - Mscara de opciones. Sus bits son:

WNOHANG: evita la suspensin del padre mientras est esperando a algn hijo. WUNTRACED: el padre obtiene informacin adicional si el hijo recibe alguna de las seales SIGTTIN, SIGTTOU, SIGSSTP o SIGTSTOP . estados - Puntero a una tabla con los estados de salida de los procesos. - Devuelve: 0, si no ha terminado ningn proceso. - Macros:
WIFSTOPPED (estado) /* !=0, si estado es de un hijo parado */ pid_t estado; int WSTOPSIG (estado) /* N de seal que ha causado la parada */ pid_t estado; WIFEXITED (estado) /* !=0, si estado es de salida normal */ pid_t estado; int WEXITSTATUS (estado) /* 8 bits bajos del estado de salida */ pid_t estado; WIFSIGNALED (estado) /* !=0, si estado es de salida anormal */ pid_t estado; int WTERMSIG (estado) /* N de saal que ha causado la slida */ pid_t estado;

- Cometarios: a) Estas subrutinas pueden verse afectadas por la seal SIGCHLD (ver sigaction). b) La subrutina wait espera la terminacin de cualquier proceso hijo.
- Ejemplos: /* waitpid.c - Esperar la terminacin de un proceso hijo */ #include <stdio.h> #include <signal.h> #include <sys/wait.h> main () { pid_t id_padre; pid_t id_hijo; int estado;

/* PID del proceso padre */ /* PID del proceso hijo */ /* Estado de salida */

printf ("Ejemplo de waitpid.\n"); printf ("Inicio proceso padre. PID=%d\n", getpid ()); id_padre = getpid (); if ((id_hijo = fork ()) == 0) { /* Proceso hijo */ printf ("Inicio proceso hijo. PID=%d, PPID=%d\n",

getpid (), id_padre); sleep (3); printf ("Salida proceso hijo. PID=%d\n", getpid ()); exit (getpid () > id_padre); /* 1, si PID > PPID */ } { signal (SIGINT, SIG_IGN); /* Ignorar CTRL-C */ while (waitpid (id_hijo, &estado, 0) != id_hijo); if (WIFSIGNALED (estado)) printf ("El proceso hijo ha recibido la seal %d\n", WTERMSIG (estado)); if (WIFEXITED (estado)) { printf ("Estado de salida del proceso hijo: %d\n", WEXITSTATUS (estado)); if (WEXITSTATUS (estado) == 1) printf ("PID hijo > PID padre.\n"); else printf ("PID padre > PID hijo.\n"); } printf ("Fin del proceso %d\n", getpid ()); exit (0); } Ejemplo de waitpid. Inicio proceso padre. PID=24213 Inicio proceso hijo. PID=31638, PPID=24213 Fin proceso hijo. PID=31638 Estado de salida del proceso hijo: 1 PID hijo > PID padre Fin del proceso 24213 La salida siguiente muestra el efecto de generar una seal de interrupcin pulsando [CTRL][C]. Dicha seal provoca la terminacin automtica del proceso hijo, mientras que el proceso padre la ignora (ver signal). Ejemplo de waitpid. Inicio proceso padre. PID=7240 Inicio proceso hijo. PID=5705, PPID=7240 ^CEl proceso hijo ha recibido la seal: 2 Fin del proceso 7240 else

1,4. Terminacin de un proceso.


1,4,1. Subrutina exit: - Descripcin: Termina la ejecucin de un proceso. - Formato:
#include <stdlib.h> void exit (estado) int estado;

- Parmetro:

Estado de salida del proceso. - Comentarios: a) El proceso de salida de un proceso es el siguiente: Llamada a la funcin _cleanup para limpiar las reas de E/S. Llamada a la subrutina especificada en la subrutina atexit. Llamada a la subrutina _exit para finalizar el proceso. b) Si _cleanup no puede cancelar las peticiones de E/S asncrona, la aplicacin se bloquea hasta que se completen dichas peticiones. c) Se cierran todos los descriptores de fichero. d) Si el proceso padre est en espera (ver wait), se devuelve el valor de los 8 bits menos significativos del estado de salida. e) Se enva una seal SIGCHLD al proceso padre. La accin por defecto es ignorar esta seal. Si no se ignora, el proceso hijo puede quedar como proceso zombi. f) La salida de un proceso no provoca la terminacin de sus hijos. El PPID de los hijos ser el PPID del proceso init (1). g) Se eliminan los bloqueos de ficheros (ver fcntl). h) Si para un proceso perteneciente a un grupo hurfano, se envan las seales SIGHUP y SIGCONT a cada proceso del grupo de procesos hurfanos.

1,4,2. Subrutina atexit: - Descripcin: Ejecuta una determinada funcin antes de la terminacin del proceso. - Formato:
#include <sys/limits.h> int atexit (funcin) void (*funcin) (void);

- Parmetro: Puntero a la funcin llamada. - Devuelve: 0: si no hay errores. - Comentarios: a) La funcin se ejecuta si se ha completado con xito la subrutina _cleanup.

- Ejemplo: /* atexic.c - Ejecucin de una rutina al salir de un programa */ #include <stdio.h> #include <sys/limits.h> int bucle=0; void salida (); int main () { int n; atexit (salida); printf ("Ejemplo de atexit.\n"); for (bucle=1; bucle<255; bucle++) { n=rand (); printf ("%d-%d\t", bucle, n); if (n > 30000) exit (1); } exit (0); } void salida () { printf ("El bucle ha dado %d vueltas.\n"); printf ("Hasta luega Lucas.\n"); } Ejemplo de atexit. 1-16838 2-5758 3-10113 4-17515 5-31051 El bucle ha dado 5 vueltas. Hasta luego Lucas. /* Contador de vueltas del bucle */ /* Prototipo de la funcin de salida */

2. SEALES.
2,1. Conceptos generales.
Seal: Evento que debe ser procesado y que puede interrumpir el flujo normal de un programa. Capturar una seal: Una seal puede asociarse con una funcin que procesa el evento que ha ocurrido. Ignorar una seal: El evento no interrumpe el flujo del programa. Las seales SIGINT y SIGSTOP no pueden ser ignoradas (ver tabla de seales). Accin por defecto:

Proceso suministrado por el sistema para capturar la seal (ver tabla de seales). Alarma: Seal que es activada por los temporizadores del sistema. Error: Fallo o accin equivocada que puede provocar la terminacin del proceso. Error crtico: Error que provoca la salida inmediata del programa.

2,2. Lista de las seales ms importantes.


Nm. Nombre Comentarios 1 SIGHUP Colgar. Generada al desconectar el terminar. 2 SIGINT Interrupcin. Generada por teclado. 3 SIGQUIT1 Salir. Generada por teclado. 4 SIGILL1 Instruccin ilegal. No se puede recapturar. 5 SIGTRAP1 Trazado. No se puede recapturar. 6 SIGABRT1 Abortar proceso. 8 SIGFPE1 Excepcin aritmtica, de coma flotante o divisin por cero. 9 SIGKILL1 Matar proceso. No puede capturarse, ni ignorarse. 10 SIGBUS1 Error en el bus. 11 SIGSEGV1 Violacin de segmentacin. 12 SIGSYS1 Argumento errneo en llamada al sistema. 13 SIGPIPE Escritura en una tubera que otro proceso no lee. 14 SIGALRM Alarma de reloj. 15 SIGTERM Terminacin del programa. 16 SIGURG2 Urgencia en canal de E/S. 17 SIGSTOP3 Parada de proceso. No puede capturarse, ni ignorarse. 18 SIGTSTP3 Parada interactiva. Generada por teclado. 19 SIGCONT4 Continuacin. Generada por teclado. 20 SIGCHLD2 Parada o salida de proceso hijo. 21 SIGTTIN3 Un proceso en 2o plano intenta leer del terminal. 22 SIGTTOU3 Un proceso en 2o plano intenta escribir en el terminal. 23 SIGIO2 Operacin de E/S posible o completada. 24 SIGXCPU Tiempo de UCP excedido. 25 SIGXFSZ Excedido el lmite de tamao de fichero. 30 SIGUSR1 Definida por el usuario nmero 1. 31 SIGUSR2 Definida por el usuario nmero 2. 34 SIGVTALRM Alarma de tiempo virtual. 36 SIGPRE Excepcin programada. Definida por el usuario. Notas sobre la accin por defecto para la seal. 1. Generar un fichero core. 2. Ignorar la seal. 3. Parar el proceso que recibe la seal. 4. Reiniciar o continuar el proceso que recibe la seal. Las seales comprendidas entre la 37 y la 58 (ambas inclusive) estn reservadas por el sistema. El rango de seales en el UNIX de Berkeley (BSD) es de 1 a 31.

2,3. Capturar seales.


2,3,1. Subrutina signal: - Descripcin: Asocia una accin determinada con una seal. - Formato:
#include <signal.h> void (*signal (seal, accin)) () int seal; void (*accn) ();

- Parmetros: seal: Nmero de seal, excepto SIGKILL. accin: Puntero a la rutina asociada con la seal o uno de los valores: SIG_DFL: accin por defecto para dicha seal. SIG_IGN: ignorar la seal, - Devuelve: Valor de la accin anteriormente asociada; -1, en caso de error. - Comentarios: a) Existe una versin de la subrutina signal compatible con el UNIX de Berkeley (BSD). b) No se permiten mscaras de bloqueo de seales y se activa el bit SA_OLDSTYLE (ver >sigaction).
- Ejemplo: /* signal.c - Contar el nmero de CTRL-C en 15 segundos */ #include <stdlib.h> #include <signal.h> int numcortes=0; int enbucle=1; void alarma (); void cortar (); /* Contador de CTRL-C */ /* Controlador de salida del bucle de espera */ /* Captura la seal de alarma SIGALRM */ /* Captura la seal de interrupcin SIGINT */

int main () { signal (SIGINT, cortar); signal (SIGALRM, alarma); printf ("Ejemplo de signal.\n"); printf ("Pulsa varias veces CTRL-C durante 15 segundos.\n"); alarm (15);

while (bucle); signal (SIGINT, SIG_IGN); printf ("Has intentado cortar %d veces.\n", numcortes); printf ("Hasta luego Lucas.\n"); exit (0); } void alarma () { signal (SIGALRM, SIG_IGN); bucle=0; /* Salir del bucle */ printf ("Alarma!\n"); } void cortar () { signal (SIGINT, SIG_IGN); printf ("Has pulsado CTRL-C\n"); numcortes++; signal (SIGINT, cortar); } Ejemplo de signal. Pulsa CTRL-C varias veces durante 15 segundo. ^CHas pulsado CTRL-C ^CHas pulsado CTRL-C ^CHas pulsado CTRL-C ^CHas pulsado CTRL-C ^CHas pulsado CTRL-C Alarma! Has intentado cortar 5 veces. Hasta luego Lucas.

2,3,2. Subrutina sigaction: - Descripcin: Especifica la accin a realizar cuando un proceso recibe una seal. - Formato:
#include <signal.h> int sigaction (seal, accin, accin_salida) () int seal; struct sigaction *accn, *accin_salida;

- Parmetros: seal: Nmero de seal, excepto SIGKILL. accin: Accin especificada cuando se recibe la seal. accin_salida: Accin a realizar cuando termine la funcin sigaction. - Campos de la estructura sigaction:

void (*sa_handler) ();

Puntero a la rutina asociada con la seal o uno de los valores:

SIG_DFL: accin por defecto para dicha seal. SIG_IGN: ignorar la seal. Especifica la mscara de las seales que sern bloqueadas durante la captura de la seal especificada.
sigset_t sa_mask; int sa_flags;

SA_ONSTACK: La captura de la seal se realiza en una pila de seales en vez de en la pila del proceso. SA_OLDSTYLE: El parmetro seal se asocia con la acin por defecto (SIG_DFL) antes de llamar a la rutina de captura (no recomendable, la seal puede recurrir). SA_NOCLDSTOP: Evita que el proceso padre reciba una seal SIGCHLD cuando para el proceso hijo. - Devuelve: 0, si es correcta; -1, en caso de error. - Comentarios: a) Las siguientes funciones pueden ser llamadas sin problemas desde una rutina de captura de seales:
_exit close fork getpgrp lseek readx sigaction sigpending tcflow tcsetpgrp ustat access creat fstat getpid mkdir rename sigaddset sigprocmask tcflush time utime alarm dup getegid getppid mkfifo rmdir sigdelset sigsuspend tcgetattr times write chdir dup2 geteuid getuid open setgid sigfillset sleep tcgetpgrp umask chmod exec getgid kill pause setpgrp sigismember statx tcsendbreak uname chown fcntl getgroups link pipe setuid signal tcdrain tcsetattr unlink

b) Una vez que una accin est instalada para una seal, contina hasta que haya otra llamada a sigaction o se llame a la subrutina exec, excepto si se ha activado el bit SA_OLDSTYLE.

c) Las seales SIGKILL y SIGSTOP no pueden ser ignoradas.

2,3,3. Subrutina kill: - Descripcin: Enva una seal a un proceso. - Formato:

#include <signal.h> int kill (proceso, seal) pid_t proceso; int seal;

- Parmetros: proceso: Identificador del proceso o del grupo de procesos que recibir la seal. Puede tomar los siguientes valores: >0: Identificador de un nico proceso. 0: Procesos cuyo identificador del grupo de procesos sea igual al PID del proceso actual. <-1: Procesos cuyo identificador del grupo de procesos sea igaul al valor absoluto de proceso. seal: Nmero de seal enviada. - Devuelve: 0, si se ha completado correctamente; -1, en caso de error. - Comentarios: a) La subrutina raise enva una seal al proceso actual.
#include <sys/signal.h> int raise (seal) int seal;

Este cdigo es equivalente al mostrado a continuacin:


error = kill (getpid (), seal);

b) La subrutina killpg enva una seal a un grupo de procesos. Esta subrutina es compatible con el UNIX de Berkeley (librera libbsd.a).
#include <signal.h> int killpg (int grupo_procesos, int seal);

El cdigo anterior equivale al mostrado a continuacin:


if (grupo_procesos < 0) { errno = ESRCH; return (-1); } return (kill(-grupo_procesos, seal));

c) Para enviar una seal a otro proceso deben coincidir el identificador de usuario (UID) real o efactivo de ambos procesos, o que el proceso emisor tenga prioridad de usuario root.
- Ejemplo:

/* kill.c - Ejecucin con tiempo de espera usando kill */ #include <stdlib.h> #include <signal.h> int espera; void hijo (); /* Tiempo de espera */ /* Controlador de fin de proceso hijo */

int main (int contargs, char *args[]); { pid_t pid; if (contargs < 3) { printf ("Formato: %s segundos comando [opciones].\n", args[0]); exit (1); } printf ("Ejemplo de kill.\n"); printf ("Ejecucin con tiempo de espera.\n"); signal (SIGCHLD, hijo); pid = fork (); if (pid == 0) { execvp (args[2]; &args[2]); perror (args[0]); } else { espera = atoi (args[1]); sleep (espera); printf ("El hijo %d ha excedido el tiempo de %d s.\n", pid, espera); signal (SIGCHLD, SIG_IGN); kill (pid, SIGINT); } exit (1); } void espera () { int id_hijo, est_hijo; id_hijo = wait (&est_hijo); printf ("El hijo %d ha terminado antes de %d s.\n", id_hijo, espera); exit (0); } $ kill.e 3 wc kill.c Ejemplo de kill. Ejecucin de un comando con tiempo de espera. 45 132 1065 kill.c El hijo 10489 ha terminado antes de 3 s. $ kill.e 3 sleep 5 Ejemplo de kill. Ejecucin de un comando con tiempo de espera. El hijo 10851 ha excedido el tiempo de espera de 3 s.

2,4. Alarmas y temporizadores.


2,4,1. Subrutinas alarm y ualarm: - Descripcin: Genera alarmas de reloj (seal SIGALRM) para el proceso actual. - Formato
#include <unistd.h> unsigned int alarm (segundos) unsigned int segundos; unsigned int ualarm (valor, intervalo) unsigned int valor, intervalo;

- Parmetros: segundos: Nmero de segundos para enviar al proceso la seal SIGALRM. valor: Nmero de seales generadas. intervalo: Intervalo (en ms.) entre las seales. - Devuelve: alarm devuelve el nmero de segundos que restan para generar la seal. ualarm devuelve el nmero de microsegundos que restan hasta la prxima seal. - Comentarios: a) Slo puede generarse una nica alarma (no son aplilables). b) El parmetro intervalo no puede ser menor que 10 para un usuario sin privilegios. c) Estas 2 subrutinas son compatibles con las primeras versiones del AIX, con UNIX System V y con UNIX de Berkeley (BSD). En AIX, se han programado como llamadas a la subrutina incinterval.
- Ejemplo: /* alarm.c - Esperar una alarma */ #include <stdlib.h> #include <unistd.h> int main () { printf ("Una alarma en 3 segundos.\n"); alarm (3); printf ("Esperando...\n"); while (1); printf ("Esta lnea no se ejecutar nunca.\n"); exit (0); }

Una alarma en 3 segundos. Esperando... Alarm clock

2,5. Tratamiento de errores.


2,5,1. Lista de errores ms importantes.
Nombre Descripcin 1 EPERM Operacin no permitida. 2 ENOENT El archivo o directorio no existe. 3 ESRCH El proceso no existe. 4 EINTR Llamada al sistema interrumpida. 5 EIO Error de E/S. 6 ENXIO No existe dispositivo o direccin. 7 E2BIG Lista de argumentos demasiado larga. 8 ENOEXEC Error en formato de ejecucin. 9 EBADF Descriptor de fichero errneo. 10 ECHILD No existe el proceso hijo. 11 EGAIN Recurso no disponible temporalmente. 12 ENOMEM No hay suficiente espacio de memoria. 13 EACCES Permiso denegado. 14 EFAULT Direccin de memoria errnea. 15 ENOTBLK Se necesita un fichero de bloques. 16 EBUSY Recurso ocupado. 17 EEXIST Fichero existente. 18 EXDEV Enlace impropio. 19 ENODEV Dispositivo inexistente. 20 ENOTDIR No es un directorio. 21 EISDIR Es un directorio. 22 EINVAL Argumento no vlido. 23 ENFILE Demasiados ficheros abiertos en el sistema. 24 EMFILE Demasiados ficheros abiertos. 26 ETXBUSY Fichero de texto ocupado. 27 EFBIG Fichero demasiado largo. 28 ENOSPC No queda espacio en el dispositivo. 29 ESPIPE Bsqueda no vlida. 30 EROFS Fichero slo de lectura. 32 EPIPE Tubera rota. 33 EDOM Error de dominio matemtico. 34 ERANGE Resultado fuera de rango. 78 ETIMEDOUT Excedido tiempo de conexin (NFS). 88 EDQUOT Cuota de disco excedida. Nota: No se tratan aqu los errores relativos a comunicaciones, ni a sockets. Nm.

2,5,2. Subrutina perror: - Descripcin: Escribe un mensaje explicando un error.

- Formato:
#include <errno.h> void perror (cadne) char *cadena;

- Parmetro: Cadena de caracteres que explica el error. - Variables globales de errno.h:


extern int errno;

Nmero de error. Tabla con la descripcin de los errores del sistema.

extern char *sys_errlist[];

- Comentarios: a) Se imprime en la salida normal con un formato equivalente a la siguiente orden:


printf ("%s: %s\n", cadena, sys_errlist[errno]);

3. PIPES (TUBERAS).
3,1. Conceptos generales.
Descriptor de fichero: Nmero entero positivo usado por un proceso para identificar un fichero abierto. Esta traduccin se realiza mediante una tabla de descriptores de fichero, ubicado en la zona de datos del proceso. Descriptores reservados: 0: entrada normal (stdin). 1: salida normal (stdout). 2: salida de error (stderr). Redireccin: Establecer copias del descriptor de ficheros de un archivo para encauzar las operaciones de E/S hacia otro fichero. Tubera: Mecanismo de intercomunicacin entre procesos que permite que 2 o ms procesos enven informacin a cualquier otro. Tubera sin nombre:

Enlace de comunicacin unidireccional, capaz de almacenar su entrada (hasta 4 KB en BSD o hasta 40 KB en System V). Tuberas nombradas (FIFO): Permiten una comunicacin menos restringida, ya que las colas FIFO existen en el sistema de archivos hasta que son borradas. Caractersticas: Permite comunicar procesos no emparentados. Tiene una entrada en el sistema de archivos. Usa una poltica de colas "primero en llegar, primero en servirse". Slo disponible en UNIX System V.

3,2. Redireccin.
3,2,1. Subrutinas dup y dup2: - Descripcin: Duplica un descriptor de fichero. - Formatos:
#include <unistd.h> #include <fcntl.h> #include <sys/types> int dup (desc_abierto) int desc_abierto; int dup2 (desc_abierto, desc_nuevo) int desc_abierto, desc_nuevo;

- Parmetros: desc_abierto: Descriptor de fichero abierto. desc_nuevo: Nuevo descriptor de fichero devuelto por dup2. - Devuelve: dup devuelve el menor descriptor de fichero que est libre. dup2 devuelve el valor de desc_nuevo. Ambas subrutinas devuelven el valor -1 en caso de error.

- Comentarios: a) Las subrutinas dup y dup2 son equivalentes a la subrutina fcntl de la siguiente forma:
dup: dup2: fcntl (desc_abierto, F_DUPFD, 0); close (desc_nuevo); fcntl (desc_abierto, F_DUPFD, desc_nuevo);

b) Puede redirigirse hacia un fichero cualquier descriptor especial.


- Ejemplo: /* dup2.c - Redireccin usando dup2 */ #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main (int contargs, char *args[]) { int desc_fich; if contargs < 3) { printf ("Formato: %s fichero comando [opciones].\n", args[0]); exit (1); } printf ("Ejemplo de redireccin.\n"); desc_fich = open (args[1], O_CREAT|O_TRUNC|O_WRONLY, 0); dup2 (desc_fich, 1); /* Redirige la salida normal */ close (desc_fich); execvp (args[2], &args[2]; /* Ejecuta comando */ exit (1); } $ dup2.e dup2.sal ls *.c Ejemplo de redireccin. $ chmod 600 dup2.sal; cat dup2.sal alarm.c atexit.c dup2.c exec.c fork.c fork_huerf.c lector_fifo.c pipe.c pipe_conec.c system.c waitpid.c escritor_fifo.c kill.c signal.c

3,2,2. Subrutina fcntl: - Descripcin: Realiza operaciones de control sobre ficheros abiertos, tales como: duplicar el descriptor, poner o leer caractersticas del descriptor, poner o leer estado del fichero, gestionar bloqueos de registros, gestionar la propiedad de la E/S asncrona,

cerrar varios ficheros. - Formato:


#include <unistd.h> #include <fcntl.h> #include <sys/types> int fcntl (descriptor, comando, argumento) int descriptor, comando, argumento);

- Parmetros: descriptor: Descriptor del fichero. comando: Operacin ha realizar. argumento: Parmetro del comando. - Devuelve: Valor devuelto por el comando; -1, en caso de error. - Operaciones:
F_DU Obtener el menor descriptor de fichero disponible que sea mayor que el parmetro descriptor. Mantiene el PFD: mismo puntero y las mismas caractersticas del fichero original. F_GE Obtener caractersticas del descriptor. TFD: F_SET Poner caractersticas del descriptor. FD: F_GE Obtener estado del fichero. TFL: F_SET Poner estado del fichero. FL: F_GE Obtener informacin de bloqueo. TLK: F_SET Poner bloqueo. LK: F_SET Poner bloqueo en una zona bloqueada. LKW: F_GE TOW Obtener PID (>0) o PGID (<0) del proceso que recibe las seales SIGIO o SIGURG. N: F_SET Poner PID (>0) o PGID (<0) del proceso gestor de la E/S asncrona. OWN: F_CL OSEM Cierra todos los descriptores desde descriptor hasta el valor mximo (OPEN_MAX). :

- Caractersticas del descriptor de ficheros: FD_CLOEXEC: Indica si el descriptor se cerrar ante una funcin exec. - Estados del modo de acceso al fichero:
O_RDONLY: O_RDWR: O_WRONLY: Abierto slo para lectura. Abierto para lectura y escritura. Abierto slo para escritura.

- Bloqueos:
F_RDLCK: F_WRLCK: F_UNLCK: Bloqueo de lectura (compartido). Bloqueo de escritura (exclusivo). Sin bloqueo.

- Comentarios: a) Un bloqueo de lectura evita que otros procesos activen bloqueos de lectura en cualquier zona del rea protegida. S se permiten otros bloqueos de lectura en toda el rea o en partes de ella. b) Un bloqueo de escritura evita que otros procesos bloqueen dicha zona. c) Los "abrazos mortales" en un sistema distribuido no siempre son detectables. El programa deber usar temporizadores para poder liberar sus bloqueos.

3,3. Comunicacin entre procesos emparentados.


3,3,1. Subrutina pipe - Descripcin: Crea un canal de comunicacin entre procesos emparentados. - Formato:
#include <unistd.h> int pipe (descriptores) int descriptores[2];

- Parmetros: Tabla que recibir los descriptores de entrada y de salida de la tubera. - Devuelve: 0, si se ha completado correctamente; -1, en caso de error. - Comentarios: a) descriptores[0] se abre para lectura y descriptores[1], para escritura. b) La operacin de lectura en descriptores[0] accede a los datos escritos en descriptores[1] como en una cola FIFO (primero en llegar, primero en servirse),
- Ejemplos: /* pipe.c - Tubera sin nombre entre procesos padre e hijo */ #include <stdlib.h> #include <unistd.h> #define LEER #define ESCRIBIR 0 1

int main () { int descr[2]; /* Descriptores de E y S de la turbera */ int bytesleidos; char mensaje[100], *frase="Veremos si la transferecia es buena."; printf ("Ejemplo de tubera entre padre e hijo.\n"); pipe (descr); if (fork () == 0) { close (descr[LEER]); write (descr[ESCRIBIR], frase, strlen(frase)); close (descr[ESCRIBIR]); } else { close (descr[ESCRIBIR]); bytesleidos = read (descr[LEER], mensaje, 100); printf ("Bytes leidos: %d\n"); printf ("Mensaje: %s\n", bytesleidos, mensaje); close (descr[LEER]); } } Ejemplo de tubera entre padre e hijo. Bytes ledos: 36 Mensaje: Veremos si la transferencia es buena. /* pipe_conec.c - Tubera entre 2 comandos usando pipe. */ #include <stdlib.h> #include <unistd.h> #define LEER #define ESCRIBIR 0 1

int main (int contargs, char *args[]) { int descr[2]; /* Descriptores de E y S de la turbera */ if (contargs != 3) { printf ("Formato: %s comando_ent comando_sal.\n", args[0]); exit (1); } pipe (descr); if (fork () == 0) { close (descr[LEER]); dup2 (descr[ESCRIBIR], 1); close (descr[ESCRIBIR]); execlp (args[1], args[1], NULL); perror (args[0]); } else { close (descr[ESCRIBIR]); dup2 (descr[LEER], 0); close (descr[LEER]); execlp (args[2], args[2], NULL);

perror (args[0]); }

$ pipe_conec.e ls wc 37 37 354

3,4. Comunicacin entre procesos no emparentados.


3,4,1. Subrutina mkfifo: - Descripcin: Crea un canal FIFO de comunicaciones entre procesos que no necesitan estar emparentados. - Formato:
#include <sys/mode.h> int mkfifo (camino, modo) const char *camino; int modo;

- Parmetros: camino: Camino completo del fichero FIFO. modo: Tipo de fichero y permisos de acceso. - Devuelve: 0, si se ha completado correctamente; -1, en caso de error. - Comentarios: a) La subrutina mkfifo es un interfaz de la rutina mknod para crear colas FIFO, las cuales no necesitan privilegios especiales del sistema. b) El comando ls -al identifica una tubera nombrada con el carcter descriptor p
- Ejemplos: /* lector_fifo.c - Tuberia con nombre usando mkfifo */ #include <stdlib.h> #include <fcntl.h> #include <sys/mode.h> int linea (int df, char *cad); int main () { int descr; char cadena[100]; unlink ("tuberia");

mkfifo ("tuberia", 0); chmod ("tuberia", 460); descr = open ("tuberia", O_RDONLY); while (linea (descr, cadena)) printf ("%s\n", cadena); close (descr); pritnf ("Fin del lector.\n"); } int linea (int df, char *cad) { int n; do { n = read (df, cad, 1); } while (n > 0 && *cad++ != NULL); return (n > 0); }

#include <stdlib.h> #include <fcntl.h> #include <sys/mode.h> int main () { int descr, longmens, i; char mensaje[100]; sprintf (mensaje, "Un saludo desde el proceso %d", getpid ()); longmens = strlen (mensaje) + 1; do { /* intentar la conexion */ descr = open ("tuberia", O_WRONLY); if (descr == -1) sleep (1); } while (descr == -1); for (i=0; i<3; i++) { write (descr, mensaje, longmens); sleep (3); } close (descr); printf "Fin del escritor %d\n", getpid ()); }

#!/bin/ksh # fifo - Carga los procesos lector y escritor en 2o plano. lector_fifo.e & escritor_fifo.e & escritor_fifo.e &

$ fifo $Un saludo desde el proceso 11996 Un saludo desde el proceso 10971 Un saludo desde el proceso 11996 Un saludo desde el proceso 10971 Un saludo desde el proceso 11996 Un saludo desde el proceso 10971 Fin del escritor 10971 Fin del escritor 11996 Fin del lector

http://www.fie.us.es/info/informatica.html - articError!Nombre de archivo no especificado.http://www.fie.us.es/info/informatica.html - artichttp://www.fie.us.es/~ramon/-Mn en la Telaraa.

Anda mungkin juga menyukai