Página siguiente Página anterior Índice general

2.3 Comunicación y sincronización

Objetivos

Entender los mecanismos básicos de unix para comunicar y sincronizar procesos entre sí y con el mundo exterior.

Especificación

Tratamiento de señales

Compile el programa psignal.c:


/* psignal.c */

#include <unistd.h>
#include <signal.h>

void confirmar(int sig) {
  char resp[100];
  write(1, "¿Quiere terminar? (s/n):", 24);
  read(0, resp, 100);
  if (resp[0]=='s') exit(0);
  signal(SIGINT, confirmar);
}

int main(void) {
  int i, j;
  signal(SIGINT, SIG_IGN);
  for (i=0; i<10; i++) {
    write(1, "No hago caso a ^C\n", 18);
    for (j = 0; j < 10000000; j++);
  }
  signal(SIGINT, SIG_DFL);
  for (i=0; i<10; i++) {
    write(1, "Ya hago caso a ^C\n", 18);
    for (j = 0; j < 10000000; j++);
  }
  signal(SIGINT, confirmar);
  for (i=0; i<10; i++) {
    write(1, "Ahora lo que digas\n", 19);
    for (j = 0; j < 10000000; j++);
  }
  exit(0);
}


y ejecútelo, intentando abortarlo en varios momentos con CONTROL-C. Ejecútelo con strace y observe que signal no es una llamada al sistema, sino una rutina de biblioteca que llama a sigaction.

Sincronización con señales

Ejecute el programa esignal.c para observar que las señales transmiten información, aunque sea de forma rudimentaria.


/* esignal.c */

#include <unistd.h>
#include <signal.h>
#include <stdio.h>


void productor(int pid) {
  int i;
  for (i=1; i<=5; i++) {
    sleep(5);
    kill(pid, i);
  }
  sleep(5);
  kill(pid, SIGKILL);
  exit(0);
}


void atiende(int sig) {
   printf("Recibida %d\n", sig);
}

void consumidor(void) {
  int i;
  for (i=1; i<=5; i++)
     signal(i, atiende);
  for (;;) {
    write(1, ".", 1);
    sleep(1);
  }
}

int main(void) {
  int pid;

  if ((pid= fork())==0) 
    consumidor();
  else
    productor(pid);
}


Comunicación con tuberías

Ejecute el programa pipe.c, para observar como el productor y el consumidor se intercambian información:


/* pipe.c */

#include <unistd.h>
#include <stdio.h>


void productor(int esc) {
  int i;
  for (i=1; i<=10; i++) {
    write(esc, &i, sizeof i);
    sleep(1);
  }
  exit(0);
}


void consumidor(int lec) {
  int leidos, i;
  while ((leidos = read(lec, &i, sizeof i)) > 0) {
     printf("Recibido %d\n", i);
  }
  exit(0);
}

int main(void) {
  int pid, tubo[2];

  pipe(tubo);
  if ((pid= fork())==0) {
    close(tubo[1]);
    consumidor(tubo[0]);
  }
  else {
    close(tubo[0]);
    productor(tubo[1]);
  }
}


Programa de copia de ficheros con control de avance

Modifique el programa de copia de ficheros realizado por un proceso hijo para que el padre saque un punto por la salida estándar por cada segundo que pase. Úsese sleep o alarm para controlar el tiempo. El programa principal terminará al recibir la señal SIGCHLD, cuando el hijo termine.

Programa de copia de ficheros concurrente

Modifique el programa de copia de ficheros para que la lectura la haga un proceso y la escritura otro, comúnicándose a través de un pipe.


Página siguiente Página anterior Índice general