2013-06-01 46 views
6

Tôi cần tạo hai quy trình con. Một đứa trẻ cần phải chạy lệnh "ls -al" và chuyển hướng đầu ra của nó đến đầu vào của tiến trình con tiếp theo, do đó sẽ chạy lệnh "sort -r -n -k 5" trên dữ liệu đầu vào của nó. Cuối cùng, quá trình cha mẹ cần phải đọc (dữ liệu đã được sắp xếp) và hiển thị nó trong thiết bị đầu cuối. Kết quả cuối cùng trong thiết bị đầu cuối (khi thực thi chương trình) phải giống như khi tôi nhập lệnh sau đây trực tiếp trong trình bao: "ls -al | sort -r -n -k 5". Đối với điều này tôi cần phải sử dụng các phương pháp sau đây: pipe(), fork(), execlp().pipe() và fork() trong c

Biên dịch chương trình của tôi, nhưng tôi không nhận được kết quả mong muốn cho thiết bị đầu cuối. Tôi không biết có gì sai. Đây là mã số:

#include <sys/types.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

int main() 
{ 
    int fd[2]; 
    pid_t ls_pid, sort_pid; 
    char buff[1000]; 

    /* create the pipe */ 
    if (pipe(fd) == -1) { 
     fprintf(stderr, "Pipe failed"); 
     return 1; 
    } 

    /* create child 2 first */ 
    sort_pid = fork(); 
    if (sort_pid < 0) {       // error creating Child 2 process 
     fprintf(stderr, "\nChild 2 Fork failed"); 
     return 1; 
    } 
    else if(sort_pid > 0) {      // parent process 

     wait(NULL);        // wait for children termination 

     /* create child 1 */ 
     ls_pid = fork(); 
     if (ls_pid < 0) {      // error creating Child 1 process 
      fprintf(stderr, "\nChild 1 Fork failed"); 
      return 1; 
     } 
     else if (ls_pid == 0) {     // child 1 process 
      close(1);       // close stdout 
      dup2(fd[1], 1);      // make stdout same as fd[1] 
      close(fd[0]);      // we don't need this end of pipe 
      execlp("bin/ls", "ls", "-al", NULL);// executes ls command 
     } 

     wait(NULL); 
     read(fd[0], buff, 1000);    // parent reads data 
     printf(buff);       // parent prints data to terminal 
    } 
    else if (sort_pid == 0) {     // child 2 process 
     close(0);        // close stdin 
     dup2(fd[0], 0);       // make stdin same as fd[0] 
     close(fd[1]);       // we don't need this end of pipe 
     execlp("bin/sort", "sort", "-r", "-n", "-k", "5", NULL); // executes sort operation 
    } 

    return 0; 
} 
+5

Trừ khi nếu bạn đang thực thi từ '/', hãy thử thay thế "bin/ls" bằng "/ bin/ls" (tương tự cho "/ bin/sort") – wildplasser

+0

Dường như bạn đang không kiểm tra lỗi. Bạn nên thêm một số, điều đó sẽ giúp bạn chẩn đoán vấn đề. –

+0

Tôi có các câu lệnh printf() bên trong các khối con. Không có "/", nó cho tôi thấy cả hai câu lệnh con nhưng khi tôi đặt "/" nó không hiển thị những câu lệnh đó; nó giống như là nó không chạm đến các khối trẻ em. – user2443819

Trả lời

3

Quy trình cha mẹ của bạn wait s để quá trình sắp xếp kết thúc trước khi tạo quy trình ls.

Quy trình sắp xếp cần đọc đầu vào của nó trước khi có thể hoàn tất. Và đầu vào của nó đến từ các ls sẽ không được bắt đầu cho đến sau wait. Deadlock.

Bạn cần tạo cả hai quy trình, sau đó wait cho cả hai.

Ngoài ra, thao tác mô tả tệp của bạn không hoàn toàn chính xác. Trong cặp cuộc gọi này:

close(0); 
dup2(fd[0], 0); 

đóng là thừa, vì dup2 sẽ tự động đóng fd 0 hiện tại nếu có. Bạn nên làm một close(fd[0]) sau khi có dup2, vì vậy bạn chỉ có một bộ mô tả tập tin được gắn vào đầu ống đó. Và nếu bạn muốn thực sự mạnh mẽ, bạn nên kiểm tra wither fd[0]==0 rồi, và trong trường hợp đó bỏ qua dup2 và đóng.

Áp dụng tất cả điều đó cho dup2 khác.

Sau đó, có vấn đề về quy trình cha mẹ đang giữ đường ống mở. Tôi muốn nói rằng bạn nên đóng cả hai đầu của đường ống trong cha mẹ sau khi bạn đã truyền chúng cho trẻ em, nhưng bạn có lạ read từ fd[0] sau khi wait cuối cùng ... Tôi không chắc tại sao lại có. Nếu đường ống ls|sort chạy đúng, đường ống sẽ trống sau đó, vì vậy sẽ không có gì để đọc. Trong mọi trường hợp, bạn chắc chắn cần phải đóng fd[1] trong phụ huynh, nếu không quá trình sắp xếp sẽ không kết thúc vì đường ống sẽ không cho biết EOF cho đến khi tất cả các nhà văn được đóng lại.

Sau khi read lạ là số printf có thể sẽ bị lỗi, vì bộ đệm đọc sẽ không bị '\0' -terminated.

Và điểm sử dụng execlp là việc thực hiện tra cứu $PATH cho bạn để bạn không phải chỉ định /bin/. Lần chạy thử nghiệm đầu tiên của tôi không thành công do sắp xếp của tôi là trong /usr/bin/. Tại sao hardcode đường dẫn khi bạn không phải?

+0

cảm ơn bạn rất nhiều; Tôi nhận nó hoạt động ngay bây giờ. Tôi lấy ra phần dư thừa trước khi dup2; Tôi cũng đã đọc read() từ df [0] sau lần chờ cuối cùng(). Tôi nhận ra điều đó là không cần thiết. Tôi đã thêm một câu lệnh mở (1) bên trong khối sắp xếp để đầu ra của sắp xếp được hiển thị trong terminal, và cuối cùng tôi đã lấy biến buff hoàn toàn và printf cuối cùng vì chúng không cần thiết. – user2443819

+0

Oh !, và tôi chỉ làm việc chờ (NULL) sau khi cả hai quá trình con. – user2443819