2009-12-05 3 views
2

희망을 포기하기 시작했습니다. 숙제 때문에 머리를 숙이세요. 어째서 어리석은 짓일까요?다중 포크(), 파이프() 및 선택()에서 길을 잃었습니다.

컨텍스트 : 쉘과 같은 실행됩니다 어떤 프로그램 유무 :
logn [--tick N] cmd를 [인수] 기본적으로

... [[인수] cmd를]를, 그것의 프로그램을 여러 개 동시에 사용할 수 있습니다.

구속 : 각 출력 라인 형식의 printf 전면에서의 명령 번호로 시작하는 "%의 D %의" 예 : 0 : 첫 번째 명령의 첫 번째 줄.
0 : 첫 번째 명령의 두 번째 줄.
1 : 두 번째 명령의 첫 번째 줄.
0 : 첫 번째 명령의 세 번째 줄.
1 : 두 번째 명령 줄.

틱이 지정된 경우 시스템은 n 초 동안 출력이 보내지지 않으면 마침표를 인쇄합니다.
Select()를 사용해야 함
마지막 출력이 마침표 인 경우 시스템에서 다른 마침표를 인쇄하지 않습니다.

이제 내 문제가 있습니다. 나는 그것을 하나의 명령으로 작동시킬 수 있었다. 여러 명령을 만들려고 할 때 실패하는 것 같습니다. 나는 그것이 내 접근일지도 모른다라고 생각한다. 어쩌면 당신 중 일부는 나를 도울 수있을 것입니다.

다음은 Multiple Cmd에서 시도한 것입니다.

당신은 루프의 모든 아이를 포크 할 필요가
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/time.h> 
#include "readline.h" 

// Reference: http://www.gnu.org/s/libc/manual/html_node/Waiting-for-I_002fO.html 
int input_timeout (int filedes, unsigned int seconds) 
{ 
    fd_set set; 
    struct timeval timeout; 

    /* Initialize the file descriptor set. */ 
    FD_ZERO (&set); 
    FD_SET (filedes, &set); 

    /* Initialize the timeout data structure. */ 
    timeout.tv_sec = seconds; 
    timeout.tv_usec = 0; 

    /* select returns 0 if timeout, 1 if input available, -1 if error. */ 
    return (select (FD_SETSIZE,&set, NULL, NULL, &timeout)); 
} 

/* Fetches the number of commands in parameters. Number of Commas + 1 */ 
int getNbCmd(char ** argv) 
{ 
    int nbCmd = 1; 
    int i;  
    while(argv[i] != '\0') 
    {   
     if(strcmp(argv[i], ",") == 0) 
      nbCmd++; 
     i++; 
    } 

    return nbCmd; 
} 


/* Fills the Command Array */ 
void getCommandes(char *** tbCmd, int argc, char ** argv) 
{  
    int indexArgv = 1; 
    int indexCmd = 0; 
    int indexTbCmd = 0;   

    char ** cmd = (char **)malloc(argc*sizeof(char *)); 

    if(strcmp(argv[indexArgv], "--tick") == 0) 
     indexArgv = 3; 

    while (indexArgv < argc) 
    { 

     if(strcmp(argv[indexArgv], ",") == 0) 
     {  
      cmd[indexCmd] = (char *) 0; 
      tbCmd[indexTbCmd] = cmd; 
      free(cmd); 
      cmd = (char **)malloc(argc*sizeof(char *)); 

      indexTbCmd++; 
      indexCmd = 0; 
     } 
     else 
     { 
      char * arg; 
      arg = argv[indexArgv]; 
      cmd[indexCmd] = arg;   

      indexCmd++; 
     } 
     indexArgv++; 
    } 

    cmd[indexCmd] = (char *) 0; 
    tbCmd[indexTbCmd] = cmd; 
    free(cmd);   
} 


int main (int argc, char ** argv) 
{ 
    int nbCmds = getNbCmd(argv);  
    int tick = -1;  

    char *** tbCmd = (char ***) malloc (nbCmds*sizeof(char **)); 

    if(strcmp(argv[1], "--tick") == 0) 
     tick = atoi(argv[2]); 

    getCommandes(tbCmd, argc, argv); 

    int i; 

    pid_t pidM[nbCmds];  
    int p[nbCmds][2]; 

    for (i = 0;i < nbCmds;i++) 
    {    
     if (pipe(p[i]) != 0){ perror("pipe()"); exit(1); } 

     // fork() to get child process   
     pidM[i] = fork();  

     if (pidM[i] < 0){ perror("fork()"); exit(1); } 
     else if (pidM[i] == 0) 
     { 
      close(p[i][0]); 
      dup2(p[i][1], STDOUT_FILENO);  

      int ret; 
      ret = execvp(tbCmd[i][0], tbCmd[i]);    
     } 
     else 
     { 
      close(p[i][1]); 

      char * buffer; 
      int retval = 1; 
      int pntAfficher = 0; //Boolean for Period Printing 
      /* select returns 0 if timeout, 1 if input available, -1 if error. */ 
      if(tick >= 0) 
       retval = input_timeout(p[i][0], tick); 
      if (retval == 0 && pntAfficher == 0) 
      { 
       printf(".\n"); 
       pntAfficher = 1; 
      } 

      buffer = readline(p[i][0]); 
      while(buffer[0] != '\0') 
      {     
       printf("%d: %s",i, buffer); 
       free(buffer); 

       /* select returns 0 if timeout, 1 if input available, -1 if error. */ 
       if(tick >= 0) 
        retval = input_timeout(p[i][0], tick); 
       if (retval == 0 && pntAfficher == 0) 
       { 
        printf(".\n"); 
        pntAfficher = 1; 
       } 
       buffer = readline(p[i][0]); 
       pntAfficher = 0; 

      free(buffer); 
      } 
     } 
    } 
free(tbCmd); 

} 
+1

문제와 관련이 없습니다 (아래 답변하는 사람들이 문제를 정확히 지적 했음). select() 대신 poll()을 사용합니다. 그것은 더 좋은 인터페이스를 가지고 있으며 일반적으로 fd_set보다 더 많은 파일 기술자를 지원합니다. – asveikau

답변

2

, 다음 두 번째 루프에서, 모든 아이로부터 모든 데이터를 읽어 : 나는 도움을 필요로하는 이유는, 따라서, 내가 완전히 잘못임을 possbile 수 있습니다.

당신은 모든 아이들의 결과를 평행하게 듣고 싶습니다. (이것은 select이 당신을 위해 무엇을하고 있는지를 보여줍니다.) 그러나 모든 아이들이 그 일을하기 위해서는 실행되어야합니다. 현재 for 루프가 아이를 생성 한 다음 select ...으로 바뀌며 적절한 장소가 아닙니다.

1

당신이 "실패한 것 같아"라고 말하면 무슨 뜻인지는 모르겠지만 모든 아이들의 말을 듣기 위해 코드를 수정해야하는 것처럼 보입니다. select를 사용하면 FD_SET을 사용하여 여러 개의 FD를 추가하려고 시도합니다. 선택 항목을보고 FD_SET을 사용하여 여러 FD를 추가하려고 시도합니다.