首页 文章

子进程中运行的程序不循环

提问于
浏览
3

我有一个关于从孩子那里阅读stdout的父进程的具体问题 . 我的问题是,当我运行程序时,子程序应该在循环中多次执行一个新程序,但它只运行一次并退出到父进程 . 子进程正在运行一个向stdout输出消息的简单程序 . 提前致谢 .

#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
 

 volatile sig_atomic_t aborting = 0; 

 void chld_handler (int sig)
     {
       if(sig == SIGINT){ 

  aborting++;

   }

 }
 

 int rand_start(int low, int high){
  int s;
  int r = 0;
  srand(time(NULL)); 

 s = rand(); 

 r = s % high + low; 

 return r; 

 } 

 void Usage(){ 

 printf("Usage :schedule [-s] [-f]   \n");
  exit(1); 

 } 

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

 /getopt variablen/
  int opt;
  int index; 

 int sflag = 0;
  int fflag = 0; 

 char *svalue;
  char *fvalue; 

 int sseconds = ssec;
  int fseconds = fsec; 

 char *reactor;
  char *emergency;
  char *logfile; 

 /**/
  char *endptr;
  /Pipe and child/ 

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

 int child1_fd;
  int child2_fd; 

 FILE *log;
  FILE *pipe_reader; 

 char *p; 
  char *buf;
  int waitFc;
  int status;
  /prgm/
  int prg_r;
  int prg_e; 

 /termination/
  int cnt = 0;
  int start_period;
  p = malloc(fgbuf * sizeof(char));
  buf = malloc(fgbuf * sizeof(char)); 

 (void)signal(SIGINT,chld_handler); 

 if(argc < 4){ 

 Usage();
 

 }else 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("Pipe created\n");} 

 /erzeuge child1/
  child1_fd = fork(); 

 if(child1_fd < 0){ 

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

 } 

 if(child1_fd == 0){
    printf("CHILD\n");
    /close pipe read/
    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);

}
 

 }else{ 

 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);
  exit(0);  

 }
 

 and the reactor program :


 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 

 int main(){ 

 srand(time(NULL));
  int i;
  int s; 

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

    嗯...你使用fork()调用来创建一个子进程然后execl()来执行另一个程序 . 问题是execl()将当前进程映像(您的子进程)替换为您正在执行的命令的映像 . 因此,在for()循环的第一次传递结束时,您的程序将被执行命令替换 . 当它完成它的工作时,它只是简单地退出,终止子进程 .

    我认为你需要做的是调用popen()而不是execl() . 这将导致命令在单独的进程中执行,而不是替换当前进程 . 如果需要,您甚至可以立即启动所有命令(在循环中调用popen()),然后使用select()/ epool()在子进程可用时立即读取数据 .

  • 2

    它不会在子进程内循环,因为你正在执行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);
        }
    }
    

相关问题