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

发布于 2024-10-06 12:19:26 字数 6045 浏览 0 评论 0原文

我有一个关于父进程从子进程读取标准输出的具体问题。我的问题是,当我运行程序时,子程序应该在循环中多次执行新程序,但它只运行一次并退出到父进程。子进程正在运行一个简单的程序,该程序将消息打印到标准输出。 提前致谢。

#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<seconds>] [-f<seconds>] <program> <emergency> <logfile>\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);
}

和反应堆计划:

#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);
   }
}

I have a specific question regarding the parent process reading the stdout from child. My problem is that when I run the program, the child program should execute a new program multiple times in a loop but it runs it only once and exits to the parent process. The child process is running a simple program that prints a message to stdout.
Thanks in advance.

#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<seconds>] [-f<seconds>] <program> <emergency> <logfile>\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);
   }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风轻花落早 2024-10-13 12:19:26

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

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

Well... you use fork() call to create a child process then execl() to execute another program. The problem is execl() replaces current proces image (your child process) with the image of the command you are executing. So at the end of first pass of for() loop your program gets replaced by the executing command. When it finishes it's job, it just simply quits, terminating the child process.

I think what you need to do is to call popen() instead of execl(). This will cause command to get executed in a separate process, rather than replacing your current process. If you want, you can even start all the commands at once (calling popen() in a loop) and then use select()/epool() to read data from child processes as soon as it becomes available.

梦亿 2024-10-13 12:19:26

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

It will not loop inside the child process because you are doing exec which typically means that it overlays the child process and will exit.
If you want to loop , you will have to spawn another child process from your loop in which you will typically do only exec, so as it iterates it will spawn a child process inside which you do exec it will overlay and exit.
So what you need to do is the following:-

for(cnt = 0; cnt < 5; cnt++){
    sleep(start_period);
    fflush(stdout);
    child2_fd = fork();
    if (child2_fd == 0){
       prg_r = execl(reactor,"",NULL);
    }
}
长不大的小祸害 2024-10-13 12:19:26

您正在调用反应器程序,就好像它是一个库函数一样。这个答案基于这样的假设:这就是您真正想要的。 (这里可能是一个错误的假设,但对其他人来说可能不是。)

也就是说,您希望当前在 reactor.c:main() 中表达的代码块在循环中重复。您已经使用 fork() 创建了一个单独的进程。因此,另一个解决方案是重组整个项目:将 Reactor.c 的角色指定为库 (libreactor.a:reactor_func(int argc, char *argv[])其中反应器代码被重构为可调用函数),而不是作为不透明的可执行文件(reactor:main()),并在编译时链接到顶级可执行文件。然后 execl(reactor_executable_path, args...) 就变成了简单的:reactor_func(args...)。

You are calling upon the reactor program as if it were a library function. This answer is based on the assumption that that is what you Really Wanted. (Maybe a false assumption here but perhaps not for others.)

That is, you want a block of code, currently expressed in reactor.c:main(), to repeat in a loop. You have already taken care to create a separate process with fork(). So another solution is to restructure the whole project: mandate the role of reactor.c as a library (libreactor.a:reactor_func(int argc, char *argv[]) where the reactor code is re-factored into a callable function) rather than as an opaque executable (reactor:main()), and linked at compile-time to the top executable. Then execl(reactor_executable_path, args...) becomes simply: reactor_func(args...).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文