我有一个关于父进程从子进行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);
aborting++; } }
and the reactor program :
Usage();
reactor = argv[1]; emergency = argv[2]; logfile = argv[3];
/*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);
}
fprintf(stderr,"Fehler bei der Erzeugung der pipe\n");
exit(1);
答案 0 :(得分:2)
嗯......你使用fork()调用创建子进程然后execl()来执行另一个程序。问题是execl()用您正在执行的命令的图像替换当前的过程映像(您的子进程)。因此,在for()循环的第一次传递结束时,您的程序将被执行命令替换。当它完成它的工作时,它只是简单地退出,终止子进程。
我认为你需要做的是调用popen()而不是execl()。这将导致命令在单独的进程中执行,而不是替换当前进程。如果需要,您甚至可以立即启动所有命令(在循环中调用popen()),然后使用select()/ epool()在子进程可用时立即从中读取数据。
答案 1 :(得分: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);
}
}
答案 2 :(得分:0)
您正在调用反应器程序,就好像它是一个库函数。这个答案是基于这样的假设,那就是你真正想要的。 (这里可能是一个错误的假设,但对其他人可能不是。)
也就是说,您希望当前以 reactor.c:main()
表示的代码块在循环中重复。您已经使用 fork()
创建了一个单独的进程。所以另一种解决方案是重构整个项目:将 reactor.c
的角色授权为一个库(libreactor.a:reactor_func(int argc, char *argv[])
,其中反应器代码被重构为一个可调用的函数),而不是一个不透明的可执行文件({{ 1}}),并在编译时链接到顶级可执行文件。然后 reactor:main()
变成简单的:execl(reactor_executable_path, args...)
。