2011-02-18 2 views
1

mkfifo()를 사용하여 여러 개의 FIFO 파이프를 만들어 운영 체제 셸 프로젝트에서 파이프 라이닝을 구현하려고합니다. 현재,이 프로그램은 첫 번째 FIFO를 쓰기 위해 열어 둔 것처럼 보입니다. 또한 FIFO는 작업 디렉토리에서 ls를 수행 할 때 나타납니다. 이 인스턴스에서 freopen()을 잘못 사용하고 있습니까? 일반적으로프로그램이 FIFO (명명 된 파이프)에 연결을 끊습니다.

void execute_external() 
{ 
    int backgrounding = 0; 
    if (raw_command[strlen(raw_command)-1] == '&') 
    { 
     pmesg(2, "Backgrounding requested.\n"); 
     raw_command[strlen(raw_command)-1] = '\0'; 
     raw_command = realloc(raw_command, strlen(raw_command)-1); 
     backgrounding = 1; 
    } 

    int numCommands = 1; 
    char **commands; 
    commands = malloc(sizeof(char *)); 

    if(strstr(raw_command, "|") != NULL)   
    { 
     numCommands = separate_pipeline_commands(commands); 
    } 
    else 
    { 
     commands[0] = malloc(strlen(raw_command) * sizeof(char)); 
     commands[0] = raw_command; 
    } 

    int i; 
    char *fifo = malloc(MAXFIFOLEN); 
    for (i = 0; i < numCommands; i++) 
    { 
     char **parameters_array = malloc(strlen(commands[i]) * sizeof(char *)); 
     int num_params; 
     num_params = str_to_str_array(commands[i], parameters_array); 
     pmesg(2, "Command is %s.\n", commands[i]); 

     if (numCommands > 1) 
     { 
      int j; 
      for (j = 0; j < numCommands - 1; j++) 
      { 
       sprintf(fifo, "fifo%i", j); 
       mkfifo(fifo, S_IWUSR | S_IRUSR); 
      } 
     } 

     pid_t pid = fork(); 

     pmesg(2, "Process forked. ID = %i. \n", pid); 
     if (pid < 0) 
     { 
      fprintf(to_write_to, "Could not fork a process to complete the external command.\n"); 
      exit(EXIT_FAILURE); 
     } 
     int status; 
     if (pid == 0) // This is the child process 
     { 
      pmesg(1, "input: [%s] output: [%s] input: %d, output: %d backgrounding is %d\n",input_file_name, output_file_name, redirect_input, redirect_output, backgrounding); 
      if (numCommands > 1 && i == 0) // we may be pipelining and this is the first process 
      { 
       sprintf(fifo, "%s%i", "fifo", i); 
       printf("Initial output: %s.\n", fifo); 
       freopen(fifo, "w", stdout); 
       //~ unlink(fifo); 
      } 
      else if (numCommands > 1 && i !=0 && (i != numCommands-1)) // we are pipelining and this is not the first or last process 
      { 
       sprintf(fifo, "%s%i", "fifo", i-1); 
       printf("Input for process %i: %s.\n", i, fifo); 
       freopen(fifo, "r", stdin); 
       //~ unlink(fifo); 
       sprintf(fifo, "%s%i", "fifo", i+1); 
       printf("Output for process %i: %s.\n", i, fifo); 
       freopen(fifo, "w", stdout); 
       //~ unlink(fifo_2); 
      } 
      else if (numCommands != 1 &&i == numCommands) 
      { 
       char *fifo = malloc(strlen("fifo")+2); 
       sprintf(fifo, "%s%i", "fifo", i); 
       freopen(fifo, "r", stdin); 
       free(fifo);    
      } 
      if(redirect_output == 1) 
      { 
       freopen(output_file_name, "w", stdout); 
      } 
      if(redirect_input == 1) 
      { 
       freopen(input_file_name, "r", stdin); 
      } 
      if (backgrounding != 0) 
      { 
       freopen("/dev/null", "w", stdout); 
      } 
      pmesg(2, "This is the child process, running execlp.\n"); 
      pmesg(1, "Command: [%s]\n", parameters_array[0]); 
      if (execvp(parameters_array[0], parameters_array) < 0) 
      { 
       fprintf(to_write_to, "Could not execute the external command. errno: %i.\n", errno); 
       exit(EXIT_FAILURE); 
      } 
      else { pmesg(2, "Executed the child process.\n");} 
     } 
     else 
     { 
      if (backgrounding != 0) 
      { 
       enqueue(&process_queue, pid, clock(), 0, 0); 
       printQueue(process_queue); 
      } 
      if (backgrounding == 0) { while(wait(&status) != pid); }// Wait for the child to finish executing 
     } 
     pmesg(1, "The child has finished executing.\n"); 
     free(parameters_array); 
    } 
    free(commands); 
} 

답변

1

을 시도하지만, XAder의 요약 전에 큰 그림을 이해하는 데 도움이, 처음 읽는 가치가있다 -

  • 나는, numofcommands 및 논리는 매우 불분명 내 상세한 첩.

    두 개의 명령 파이프 라인에 대해 실행할 정확한 코드를 작성한 다음 세 개의 명령 파이프 라인 코드와 네 개를 쓰는 것이 좋습니다. 그리고 다음에 루프를 배치하십시오. 중복 된 코드 (사실 fork() 한 개만 가지고 두 명령에 대한 코드를 작성했지만 세 가지 코드가 아니라는 것을 제안합니다. :)

    희망이 있습니다.

    /* if numCommands == 1 or 0, the rest is probably useless too 
        so this should guard the entire routine, not just the routine 
        that creates FIFOs */ 
    if (numCommands > 1) 
    { 
        int j; 
        for (j = 0; j < numCommands - 1; j++) 
        { 
         char *fifo = malloc(strlen("fifo")+1); /* BUG #1 */ 
         sprintf(fifo, "%s%i", "fifo", j); /* BUG #2 */ 
         mkfifo(fifo, S_IWUSR | S_IRUSR); 
         free(fifo); /* messy */ 
        } 
    } 
    
    /* Bug #1 The malloc(strlen()+1) is only good for "fifo", doesn't 
        actually allocate space for your number. Don't forget the 
        ascii NUL character at the end of the string. Add another +1. */ 
    /* Bug #2 works for numCommands < 10; with 10 commands, you'll need to +2 
        for two characters, and so on */ 
    /* messy -- maybe just have a 'char fifo[MAXFIFOLEN];' allocation, 
        and set MAXFIFOLEN to 255 or 4096 or something. No need to allocate 
        and free a simple little buffer a dozen times. */ 
    
    pid_t pid = fork(); 
    
    /* You should probably place fork() in a for loop; one new process 
        per command. Another choice is to write this whole routine recursively 
        which might be adding too many moving parts into one program */ 
    
    pmesg(2, "Process forked. ID = %i. \n", pid); 
    /* Note that parent and child get different values of 'pid', so printing 
        the value of pid here may be very confusing */ 
    int status; 
    if (fork < 0) /* BUG #3 fork() is a function; should be pid */ 
    { 
        fprintf(to_write_to, "Could not fork a process to complete the external command.\n"); 
    /* perror() is a wonderful routine! it helps users know _why_ something failed */ 
        exit(EXIT_FAILURE); 
    } 
    
    if (pid == 0) // This is the child process 
    /* only ONE path below will ever execute; this is why your fork() 
        should be in a loop over numCommands, so each command's process 
        can get its own individual stdin and stdout hooked together */ 
    { 
        pmesg(1, "input: [%s] output: [%s] input: %d, output: %d backgrounding is %d\n",input_file_name, output_file_name, redirect_input, redirect_output, backgrounding); 
        if (numCommands > 1 && i == 0) // we may be pipelining and this is the first process 
        { 
         char *fifo = malloc(strlen("fifo")+2); 
         sprintf(fifo, "%s%i", "fifo", i); /* could just be sprintf(fifo, "fifo%i", i); */ 
         printf("Initial output: %s.\n", fifo); 
         freopen(fifo, "w", stdout); 
         //~ unlink(fifo); 
         free(fifo); 
        } 
        else if (numCommands > 1 && i !=0 && (i != numCommands-1)) // we are pipelining and this is not the first or last process 
        { 
         char *fifo = malloc(strlen("fifo")+2); 
         sprintf(fifo, "%s%i", "fifo", i-1); 
         printf("Input for process %i: %s.\n", i, fifo); 
         freopen(fifo, "r", stdin); 
         //~ unlink(fifo); 
         char *fifo_2 = malloc(strlen("fifo")+2); 
         sprintf(fifo_2, "%s%i", "fifo", i+1); 
         printf("Output for process %i: %s.\n", i, fifo); 
         freopen(fifo_2, "w", stdout); 
         //~ unlink(fifo_2); 
         free(fifo); 
         free(fifo_2); 
        } 
        else if (numCommands != 1 &&i == numCommands) 
        { 
         char *fifo = malloc(strlen("fifo")+2); 
         sprintf(fifo, "%s%i", "fifo", i); 
         freopen(fifo, "r", stdin); 
         free(fifo);    
        } 
    
  • +0

    자세한 메모를 보내 주셔서 감사합니다. 자식 프로세스 부분에서이 코드는 실제로 루프에서 호출됩니다. 주변의 코드를 일부 명확하게 남겨두기를 희망하면서 질문에서 제외되었습니다. 분명히 최선의 결정이 아닙니다. –

    +0

    @Alex, 아하! 때로는 가능한 가장 작은 "재생기"로 문제를 줄이는 것이 실수를 찾는 데 중요하며 때로는 기본 문제를 찾기가 훨씬 어려워집니다. :) 가장 작은 재생기를 찾는 것은 그 자체로 예술 형식입니다. 나는 당신의 원래 문제가 잘 진행되기를 희망한다. – sarnold

    +0

    쉘이 만기가되기 전날 밤 나는이 일을 맡았습니다 ... 프로젝트 파트너는 마지막 순간까지 그것을 할 수 있다고 생각했습니다. 기능을 종료 한 채로 끝났습니다. 그래도 도와 ​​줘서 고마워! –

    0

    : 코드에 의한에서는 mkfifo 파일 이름

  • 에 대한

    • 잘못된 메모리 할당이 논리는 자식 프로세스 그리고 그렇게 항상 한 3의 경로 만 하나를 갈 수있다 프로세스는 파일을 열고 man 페이지에 따라 두 당사자가 fh를 열 때까지 차단됩니다. 나는 아래의 코드에 인라인 몇 가지 의견을 배치 한이 approach
  • +0

    전체 블로그 게시물을 읽었습니까? 저자는 최후에 pseudocode 방법을 얼마나 싫어하는지에 대해 논의합니다. 그것 이외에, 비평을위한 감사합니다. –

    관련 문제