2009-11-07 52 views
9

Tôi đang cố tạo một trình bao đơn giản trong C cho Unix. Tôi đã có thể làm tất cả việc phân tích cú pháp các lệnh và thực thi, nhưng tôi đang gặp vấn đề với đường ống. Tôi nghĩ rằng vấn đề là tôi không hooking vào đúng ống cho đầu vào của lệnh thứ hai.Sự cố với các lệnh đường ống trong C

Ví dụ: nếu tôi nhập "ls | wc", nó sẽ tạm dừng sau lệnh "wc", điều mà tôi nghĩ là do chờ đợi đầu vào. Tôi nghĩ rằng vấn đề là khi tôi sử dụng dup2 (đọc [i], 0), và nó không hooking vào đúng ống.

Tôi biết đây là một câu hỏi rộng, nhưng nếu có bất kỳ gợi ý nào tôi có thể nhận được, tôi sẽ đánh giá cao nó. Đây là đoạn mã tạo ra các quy trình mới và cố gắng làm chúng.

int fileds[2]; 
    int reading[num_cmds]; 
    int writing[num_cmds]; 

    int p; 
    for(p=0; p < num_cmds; p++) 
    { 
     reading[p] = -1; 
     writing[p] = -1; 
    } 

    int j; 
    for(j=0; j < num_cmds-1; j++) //Create pipes for commands 
    { 
     int fileds[2]; 
     pipe(fileds); 
     reading[j+1] = fileds[0]; 
     writing[j] = fileds[1]; 
    } 

    int i = 0; 
    for(i = 0; i < num_cmds;i++) 
    {   
     cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); //Get command and args 

     pid_t childpid; 
     int status; 
     childpid=fork(); 

     if (childpid >= 0) 
     { 
      if (childpid == 0) 
      {    
       if(writing[i] != -1) 
       { 
        dup2(writing[i],1); 
        close(writing[i]); 
       } 

       if(reading[i] != -1) 
       { 
        dup2(reading[i],0); 
        close(reading[i]); 
       } 

       int h; 
       for(h = 0; h < num_cmds; h++) 
       { 
        close(writing[h]); 
        close(reading[h]); 
       } 

       if(execvp(cmd_args[0],cmd_args) == -1) 
       { 
        perror("Problem with command"); 
        exit(0); 
       } 
      } 
      else 
      { 
       wait(&status); 
       int m; 
       for(m = 0; m < num_cmds; m++) 
       { 
        if(writing[m] != -1) close(writing[m]); 
        if(reading[m] != -1) close(reading[m]); 
       } 
      } 
     } 
     else 
     { 
      perror("fork"); 
      continue; 
     } 


     input_file[0] = 0; 
     output_file[0] = 0; 
     run_bg = 0; 
    } 

} 



UPDATE: tôi đã có thể hình dung nó ra, nhờ Richard. Đó là sự kết hợp của việc đóng các bộ mô tả tập tin theo thứ tự sai và không đóng một chút nào. Đây là mã làm việc.

int fileds[2]; 
    int reading[num_cmds]; 
    int writing[num_cmds]; 

    int p; 
    for(p=0; p < num_cmds; p++) 
    { 
     reading[p] = -1; 
     writing[p] = -1; 
    } 

    int j; 
    for(j=0; j < num_cmds-1; j++) 
    { 
     int fileds[2]; 
     pipe(fileds); 
     reading[j+1] = fileds[0]; 
     writing[j] = fileds[1]; 
    } 

    int i = 0; 
    for(i = 0; i < num_cmds;i++) 
    {   
     cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); 

     pid_t childpid; 
     int status; 
     childpid=fork(); 

     if (childpid >= 0) 
     { 
      if (childpid == 0) 
      {    
       if(writing[i] != -1) 
       { 
        close(1); 
        dup2(writing[i],1); 
       } 

       if(reading[i] != -1) 
       { 
        close(0); 
        dup2(reading[i],0); 
       } 

       if(execvp(cmd_args[0],cmd_args) == -1) 
       { 
        perror("Problem with command"); 
        exit(0); 
       } 
      } 
      else 
      { 

       wait(&status); 
       close(writing[i]); 

       if(i > 0) 
       { 
        close(reading[i]); 
       } 
      } 
     } 
     else 
     { 
      perror("fork"); 
     } 


     input_file[0] = 0; 
     output_file[0] = 0; 
     run_bg = 0; 
    } 

Trả lời

2

Tôi nghĩ rằng vấn đề của bạn có thể là bạn đợi cho mỗi tiến trình bên trong vòng lặp và sau đó đóng tất cả các bộ mô tả tập tin. Điều này làm cho các bộ mô tả tệp không hợp lệ cho cuộc gọi tiếp theo tới dup2() và kết quả là stdin cho quá trình tiếp theo không thay đổi.

Chỉ cần đoán, tôi chưa chạy mã.

+0

Tôi nghĩ bạn nói đúng. Tôi đã cố gắng bình luận ra nếu (đọc [m]! = -1) đóng (đọc [m]); trong vòng lặp, và đó là cho phép tôi để đường ống 2 lệnh. Cám ơn đã chỉ tôi hướng đi đúng! – mbxtr

0

Khi tôi nhập "ls | wc" wc làm như mong đợi và in số từ xuất ra bằng lệnh ls. Hãy nhớ rằng khi bạn đang sử dụng lệnh piping bằng cách sử dụng "|" bạn không cần tạo đường ống trong ứng dụng của mình. Lệnh đầu tiên cần xuất ra lệnh stdout và lệnh thứ hai cần đọc kết quả đó từ chuẩn.

+0

Đây là một dự án để hiểu cách thức hoạt động của đường ống, vì vậy tôi cần có khả năng thiết lập đường ống. "ls | wc" hoạt động trong một thiết bị đầu cuối bình thường, nhưng tôi cần mô phỏng điều đó trong chương trình này. Từ những gì tôi hiểu, tôi cần đặt đầu ra của lệnh đầu tiên - "ls" trong trường hợp này là đầu ra của đường ống, và đầu vào của lệnh thứ hai, là đầu vào của đường ống. – mbxtr

+0

Vâng, nếu bạn đang thực hiện một trình bao để cung cấp cơ chế đường ống này thì bạn cần sử dụng các đường ống hoặc một số cơ chế tương tự. Tôi nghĩ người hỏi biết những vấn đề này; anh ấy hỏi về lý do tại sao nó không hoạt động. – BobbyShaftoe

Các vấn đề liên quan