将值异步返回到父进程

时间:2015-12-18 11:29:06

标签: c process fork child-process

我参与解决使用fork的练习。语句是这样的:1个父级创建3个子级,这些子级具有随机和不同的执行时间,并且必须将它们各自的值返回给父级。所以,到目前为止,我能够创建和执行子进程并捕获它们的一些值,但之后执行就变得坚果了。我到现在为止的代码是:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAXCAPOS 3
#define MAXCOMERCIOS 3

/* Funcion que calcula aleatorios */
int calculaAleatorios(int min, int max) {
    return rand() % (max-min+1) + min;
}

/* Funcion para dar más tiempo a que los negocios paguen */
void darPlazo() {
    printf("\nDON: ¡Chicos! Decidle a los comerciantes que me deben dinero, que como no paguen lo que me deben, la semana que viene quemare sus tiendas.");
}

/* Funcion para dar una leccion a los negocios */
void darLeccion() {
    printf("\nDON: ¡Chicos! Quemad los comercios que no han pagado esta semana.");
}

/* Funcion para generar un consejo */
void generaConsejo() {
    sleep(10);
    if(calculaAleatorios(0,1)==0) {
        printf("\nConsigliere: Ya he deliberado SIGUSR1");       
        kill(getppid(), SIGUSR1);
    } else {
        printf("\nConsigliere: Ya he deliberado SIGUSR2");
        kill(getppid(), SIGUSR2);
    }
}

int main(void){
  pid_t pidDon;
  pid_t pidCapo[MAXCAPOS];
  pid_t pidConsigliere;
  int i = 1, j = 1;
  int totalImpagos = 0;
  for (i; i <= MAXCAPOS; i++){
    /* Forkeando pidDon para obtener los capos */
    switch (pidDon = fork()){
      case -1:
        perror("Error en la llamada a la funcion fork()");
        exit(EXIT_FAILURE);
        break;
      case 0:
      {
        int noPagan = 0, tiempo = 0;
        pidCapo[i] = getpid();
        srand(pidCapo[i]); /*Generamos una semilla por el pid, dentro del proceso hijo para obtener semillas diferentes*/
        printf("\nDON: Contrato al capo%d (pid: %d)", i, pidCapo[i]);
        /* VISITAR LOS COMERCIOS Y RECIBIR CUANTOS HAN PAGADO (int) */
        for (j; j <= MAXCOMERCIOS; j++){
          tiempo = calculaAleatorios(5, 10); /* Genera un tiempo aleatorio entre 5 y 10 */
          printf("\n Capo%d: %d Segundos para despertar (pid: %d)", i, tiempo, pidCapo[i]);
          sleep(tiempo);
          printf("\n Capo%d: Visita el comercio %d (pid: %d)", i, j, pidCapo[i]);
          if (calculaAleatorios(0, 1) == 0){
            printf("\n Capo%d: El comercio %d no me ha pagado, malditas ratas!! (pid: %d)", i, j, pidCapo[i]);
            noPagan++;
          } else {
            printf("\n Capo%d: El comercio %d ha pagado (pid:%d)", i, j, pidCapo[i]);
          }
        }
        printf("\nCapo%d: tengo %d morosos", i, noPagan);
        exit(noPagan);
        break;
      }
      default:
        break;
    }
  }
  /*Proceso DON*/
  // Crear señales
  printf("\nDON: Voy a esperar noticias de mis capos... (pid: %d)", getpid());
  signal(SIGUSR1, darPlazo); // Unimos la señal SIGUSR1 a su procedimiento
  signal(SIGUSR2, darLeccion); //Unimos la señal SIGUSR2 a su procedimiento
  if (pidDon != 0 && pidDon != -1){
    for (i = 1; i <= MAXCAPOS; i++){
      int retorno;
      waitpid(pidCapo[i], &retorno, 0);
      retorno = WEXITSTATUS(retorno);
      printf("\nDON: Al capo %d no le han pagado %d comercios", i, retorno);
      totalImpagos += retorno;
    }
    sleep(30);
    if (totalImpagos == 0){
      printf("\nDON: Que bien, esta vez han pagado todos :D");
      printf("\nDON: He terminado mi dia\n");
      return (0);
    } else {
      if (totalImpagos == 1){
        printf("\nDON: No me ha pagado 1 comercio, grrrrrrrr!!!!");
      }
      if (totalImpagos > 1){
        printf("\nDON: No me han pagado %d comercios, estoy muy encabronado!", totalImpagos);
      }
      printf("\nDON: Consultare con mi consigliere");
      /*Proceso Consigliere*/
      pidConsigliere = fork();
      if (pidConsigliere == -1){
        perror("\nFallo al crear el proceso Consigliere");
        exit(EXIT_FAILURE);
      }
      else if (pidConsigliere == 0){
        signal(SIGUSR1, generaConsejo); // Unimos la señal SIGUSR1 a su procedimiento
        printf("\nConsigliere: Hola Don! Espero tu señal");
        pause();
        exit(0);
      }
      /*Vuelta al DON*/
      // Consulta al consigliere
      sleep(5);
      printf("\DON: Le mando una señal a mi consigliere");
      if (kill(pidConsigliere, SIGUSR1) == -1){ // Lanzamos kill contra pidConsigliere y evaluamos el error
        perror("\nFallo al enviar la señal al Consigliere");
        exit(EXIT_FAILURE);
      }
      printf("\nDON: Esperare mientras mi consigliere delibera");
      pause();
    }
  }
  printf("\nDON: He terminado mi dia\n");
  return (0);
}

所以,我需要知道如何正确地检索所有3个返回值。提前谢谢。

2 个答案:

答案 0 :(得分:0)

如何在父级中安装SIGCHLD的信号处理程序以及何时调用它,使用wait()waitpid()wait4()来获取孩子的退出状态?

这是规范的做法。我不确定SIGUSR1/2的目的是什么。

答案 1 :(得分:0)

  

所以,到目前为止,我能够创建和执行子进程和   抓住他们的一些价值观,但执行成功后就变得坚果了   这一点。

您正在使用pidCapo[i]的值从i1MAXCAPOS编制索引,这是错误的,因为数组是从0开始索引的。