为什么我的程序终止(使用管道)?

时间:2015-11-22 21:26:15

标签: shell pipe exec fork

我想制作一个可以使用管道的shell。当我使用此代码在我的shell中运行管道时,即使所有内容都在WHILE(1)循环中,我的shell也会终止。为什么?使用dup函数是否有问题?

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void)
{


  int pfds[2];
  pipe(pfds);
  char *ar1;
  const char sp = ' ';
  int temp, temp1, temp2, acc;
  int i, j;
  int t = 0;
  char *line=(char *) malloc(1024*sizeof(char));
  char *frsarg=(char *) malloc(1024*sizeof(char));
  char *firstcmd=(char *) malloc(1024*sizeof(char));
  char *seccmd=(char *) malloc(1024*sizeof(char));
  char *scmd=(char *) malloc(1024*sizeof(char));
  char *secondcmd=(char *) malloc(1024*sizeof(char));
  char *secarg=(char *) malloc(1024*sizeof(char));
  char *frscmd=(char *) malloc(1024*sizeof(char));
  char *cmd1=(char *) malloc(1024*sizeof(char));
  char *cmd=(char *) malloc(1024*sizeof(char));
  char *cmdf=(char *) malloc(1024*sizeof(char));
  char *arg1=(char *) malloc(1024*sizeof(char));
  char *allarg=(char *) malloc(1024*sizeof(char));
  char *arg2=(char *) malloc(1024*sizeof(char)); 
  char *arg3=(char *) malloc(1024*sizeof(char));
while (1) {
       /* Ektypwse to command prompt */
       printf("$ ");
       fflush(stdout);                            



       fgets(line, 1024, stdin);                  //Reads the command.


       for(i=0;i<1024;i++){

           if(line[i]=='\n')                      //Deletes the "Enter" from the end of the string.
             {
               line[i]='\0';                      //Replace "Enter" with \0.

             }
          if(line[i] == 'e' && line[i+1] == 'x' && line[i+2] == 'i' && line[i+3] == 't' ) {
           exit(1);
          }


        }

   seccmd = strchr(line, '|'); 
   acc = 0;
    for(i=0;i<1024;i++){ 
       if(line[i]=='|'){
         acc = i;   
         t=t+1; 
        }                    //Finds the second space.
    }





/*FIRST COMMAND AND ARGUMENT*/

if(acc != 0 ){
       //printf("OKIF\n");                         
       for(j=0;j<acc;j++){
          //printf("OKFOR\n");                     
          frscmd[j]= line[j];                         
       }
      //printf("FIRST COMMAND %s\n", frscmd);                  
    }
 /*FIRST ARG*/
 frsarg = strchr(frscmd, sp);
    if(frsarg != NULL){
          while(isspace(*frsarg)) ++frsarg;                
    }

    for (i=0;i<1024;i++){
        if (frsarg[i] == ' '){
        frsarg[i] = '\0';
        }
    }


 /*FIRST COMMAND*/


 acc = 0;
 for(i=0;i<1024;i++){ 
       if(frscmd[i]==' '){
         acc = i;   
         break;
        }  

  }

 if(acc != 0 ){
       //printf("OKIF\n");                         
       for(j=0;j<acc;j++){
          //printf("OKFOR\n");                     
          firstcmd[j]= frscmd[j];                         
       }

 }
 if(firstcmd != NULL){
       while(isspace(*firstcmd)) ++firstcmd;  
 }
 printf("FIRST COMMAND TEST %s TEST\n", firstcmd);  
 printf("FIRST ARGUMENT TEST %s TEST\n", frsarg);

// firstcmd == "ls" ,frsarg == "-l"

/*SECOND COMMAND AND ARGUMENTS */

//seccmd = " | ws -l



//SECOND COMMAND WITHOUT "|" secondcmd = _wc_-l


secondcmd = strchr(seccmd, sp);
    if(secondcmd != NULL){
          while(isspace(*secondcmd)) ++secondcmd;                
    }



//SECCOND COMMAND scmd


 acc = 0;
 for(i=0;i<1024;i++){ 
       if(secondcmd[i]==' '){
         acc = i+1;   

        }  

  }

 if(acc != 0 ){

       for(j=0;j<acc;j++){

          scmd[j]= secondcmd[j];                         
       }

 }

for (i=0;i<1024;i++){
        if (scmd[i] == ' '){
        scmd[i] = '\0';
        }
    }

 printf("SECOND COMMAND TEST %s TEST\n", scmd);  

//SECOND ARGUMENT secarg


secarg = strchr(secondcmd, sp);
if(secarg != NULL){
          while(isspace(*secarg)) ++secarg;                
    }


printf("SECOND ARGUMENT TEST %s TEST\n", secarg);  


//FIRST COMMAND = firstcmd____FIRST ARGUMENT = frsarg_____SECOND COMMAND = scmd_____SECOND ARGUMENT = secarg

if (!fork()) {
        close(1);       /* close normal stdout */
        dup(pfds[1]);   /* make stdout same as pfds[1] */
        close(pfds[0]); /* we don't need this */
        execlp(firstcmd, firstcmd, frsarg,(char*) NULL);
    } else {
        close(0);       /* close normal stdin */
        dup(pfds[0]);   /* make stdin same as pfds[0] */
        close(pfds[1]); /* we don't need this */
        execlp(scmd, scmd, secarg,(char*) NULL);
    }

   return 0;


}
}

1 个答案:

答案 0 :(得分:1)

嗯,这是一段非常漫长而复杂的代码,逻辑似乎如此 而 ad hoc 。剖析整体将花费我太长时间 的事情。

我确实观察到你fork()只有一次,然后每个分支都会调用 execlp()运行管道中的两个进程之一。离开了 没有进程继续运行shell。所以你真的需要fork() 两次。

让我们说原始流程是A。第一次打电话给 fork()我们有原始流程A和子A1A然后打电话 wait()暂停,直到A1终止。 A1再次致电fork() 运行流水线命令。

或类似的东西。看着我的代码库,我看到了最后一次 试验这些东西是在2000年,而我并没有做两件事 子过程就像你一样。但这应该是正确的一步 无论如何,方向。