Программа, запущенная в дочернем процессе, не зацикливается - PullRequest
3 голосов
/ 09 декабря 2010

У меня есть конкретный вопрос относительно родительского процесса, считывающего стандартный вывод дочернего процесса. Моя проблема в том, что когда я запускаю программу, дочерняя программа должна выполнить новую программу несколько раз в цикле, но она запускает ее только один раз и выходит из родительского процесса. Дочерний процесс запускает простую программу, которая печатает сообщение на стандартный вывод. Заранее спасибо.

</p>

<p>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <sys/wait.h>


#define ssec 1
#define fsec 0
#define secBuf 5
#define decbase 10
#define fgbuf 60
</p>

<p>volatile sig_atomic_t aborting = 0;</p>

<p>void chld_handler (int sig)
     {
       if(sig == SIGINT){</p>

<pre><code> aborting++;

   }

 }

int rand_start (int low, int high) { int s; int r = 0; srand (время (NULL));

s = rand ();

r = s% высокий + низкий;

return r;

}

void Usage () {

printf («Использование: расписание [-s] [-f] \ n»); выход (1);

}

int main (int argc, char * argv []) {

/ переменная getoptn / int opt; int index;

int sflag = 0; int fflag = 0;

char * svalue; char * fvalue;

int sseconds = ssec; int fseconds = fsec;

чар * реактор; символ * аварийный; char * logfile;

/ ** / char * endptr; / Труба и ребенок /

int pipepc1 [2]; int pipepc2 [2];

int child1_fd; int child2_fd;

ФАЙЛ * log; FILE * pipe_reader;

char * p;
char * buf; int waitFc; статус int; / PRGM / int prg_r; int prg_e;

/ окончание / int cnt = 0; int start_period; p = malloc (fgbuf * sizeof (char)); buf = malloc (fgbuf * sizeof (char));

(пустоты) сигнал (SIGINT, chld_handler); * * тысяча пятьдесят-четырь

if (argc <4) {</p>

Usage();

} иначе if (argc == 4) {

reactor = argv[1];
emergency = argv[2];
logfile = argv[3];

} else if (argc> 4) {

/*argumentenbehandlung*/


while((opt = getopt(argc,argv,":s:f:")) != -1){
  printf("sflag %d fflag %d \n",sflag,fflag);
  printf("opt  %c \n", opt);
  printf("optind %d \n ",optind);
  switch(opt){

    case 's':
  if(sflag == 0){
    sflag++;
    svalue = optarg;
  }else{
    fprintf(stderr,"Widerholung der option -s\n");
    Usage();
  }

  break;

   case 'f':

 if(fflag == 0){

   fflag++;
   fvalue = optarg;
 }else {
   fprintf(stderr,"Widerholung der option -f\n");
   Usage();
 }
 break;

    case ':' :

  fprintf(stderr,"Option -%c brauch ein argument\n",optopt);
  Usage();
  break;

  case '?' : 
fprintf(stderr,"Nicht bekannte option -%c \n",optopt);
Usage();
break;

  default :
assert(0);

  }/*switch*/




}/*while getopt*/


for(index = optind; index < argc; index++){

  if((argc - index) == 3){

reactor = argv[index];

  }else if((argc - index) == 2){

emergency = argv[index];

  }else if((argc - index) == 1){

logfile = argv[index];

  }


}/*for schleife*/


/* */
if(sflag){

  sseconds = (int)strtol(svalue,&endptr,decbase);
  printf("%d ssec\n", sseconds);
}

if(fflag){

  fseconds = (int)strtol(fvalue,&endptr,decbase);
  printf("%d fsec\n", fseconds);

}

}

/ pipeing /

if (pipe (pipepc1) == -1) {

fprintf(stderr,"Fehler bei der Erzeugung der pipe\n");
exit(1);

} else {printf ("Создан канал \ n");}

/ erzeuge child1 / child1_fd = fork ();

if (child1_fd <0) {</p>

fprintf(stderr,"Fehler beim asfuehren von fork\n");
exit(0);

}

if (child1_fd == 0) { Е ( " РЕБЕНКА \ п"); / закрыть трубку читать / if (close (pipepc1 [0]) == -1) {

  fprintf(stderr,"Konnte nicht das Read-Ende vom pipepc1 schliessen\n");
  exit(1);
}

if(close(1) == -1){

  fprintf(stderr,"Konnte nicht das Read-Ende vom pipepc1 schliessen\n");
  exit(1);

}



if(dup(pipepc1[1]) !=STDOUT_FILENO){

  fprintf(stderr,"Das setzen des Read-Endes als stdout is Fehlgeschlagen\n");
  exit(1);

}

if(fseconds == 0){

  start_period = sseconds; 

}else start_period = rand_start(sseconds,(sseconds + fseconds));

for(cnt = 0; cnt < 5; cnt++){
  sleep(start_period);
  fflush(stdout);
  prg_r = execl(reactor,"",NULL);

  //printf("prg_r ist %d  \n", prg_r);
}

if(close(pipepc1[1]) == -1){

  fprintf(stderr,"Das neue stdout konnte nich geschlossen werden\n");
  exit(1);

}

} еще {

printf("**PARENT**\n");

log = fopen(logfile,"w");

/*schliesse pipe read*/
close(pipepc1[1]);

pipe_reader = fdopen(pipepc1[0],"r");


while((buf = fgets(p,fgbuf,pipe_reader)) != NULL){

  printf("from Child : %s \n",buf);
  fflush(pipe_reader);
}  

fclose(log);   

waitFc= waitpid(child1_fd,&status,0);

  if(waitFc == -1){

fprintf(stderr,"Das Warten ist fehlgeschlagen\n");
exit(1);

  }

  printf("child is done\n und waitFc = %d\n und satus %d",waitFc,status);
  fclose(pipe_reader);
  close(pipepc1[1]);

}

printf ("argc =% d \ n", argc); Выход (0);

}

и программа реактора: </p> <p> #include <stdio.h> #include <stdlib.h> #include <time.h> </p> <p>int main(){</p> <p>srand(time(NULL)); int i; int s;</p> <code>s = rand() % 7; /*printf("%d \n",s);*/ if(s != 6){ printf("OK\n"); fflush(stdout); }else { printf("PRESSURE TOO HIGH - IMMEDIATE SHUTDOWN REQUIRED"); exit(EXIT_FAILURE);

}

}

Ответы [ 2 ]

2 голосов
/ 07 марта 2018

Он не будет зацикливаться внутри дочернего процесса, потому что вы выполняете exec, что обычно означает, что он перекрывает дочерний процесс и завершается. Если вы хотите выполнить цикл, вам придется порождать другой дочерний процесс из вашего цикла, в котором вы, как правило, будете выполнять только exec, поэтому при его повторении он будет порождать дочерний процесс, внутри которого вы выполняете exec, он будет перекрываться и выходить. Так что вам нужно сделать следующее: -

for(cnt = 0; cnt < 5; cnt++){
    sleep(start_period);
    fflush(stdout);
    child2_fd = fork();
    if (child2_fd == 0){
       prg_r = execl(reactor,"",NULL);
    }
}
2 голосов
/ 09 декабря 2010

Ну ... вы используете вызов fork () для создания дочернего процесса, а затем execl () для выполнения другой программы. Проблема в том, что execl () заменяет текущее изображение процесса (вашего дочернего процесса) изображением команды, которую вы выполняете. Таким образом, в конце первого прохода цикла for () ваша программа заменяется исполняемой командой. Когда он заканчивает свою работу, он просто завершает работу, завершая дочерний процесс.

Я думаю, вам нужно вызвать popen () вместо execl (). Это приведет к тому, что команда будет выполнена в отдельном процессе, а не заменит ваш текущий процесс. Если вы хотите, вы можете даже запустить все команды одновременно (вызывая popen () в цикле), а затем использовать select () / epool () для чтения данных из дочерних процессов, как только они станут доступны.

...