2016-12-06 7 views
1

このCの演習で問題が発生しました。 タスクは2つのプロセスを作成することです。 2つのパイプは2つのパイプで接続され、子供の標準と標準で終了します。子プロセスはbcに置き換えられます。 これで、親から子プロセス(bc)に用語(例えば1 + 2)を書き込むことになっています。Cのパイプを使ってbcに用語を書く

パイプは彼らがやろうとしていることをしていますが、BCは入力を好まないようです。私はパイプに書き込むとき、BCは、以下の複数行で応答:

(standard_in) 1: illegal character: ^@ 

これは、これまでのところ私のソリューションです:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(int argc, char *argv[]) { 

    /*Create two pipes: 
     One from parent to child (pipe_pc) 
     and one from child to parent (pipe_cp). 
    */ 
    int pipe_pc[2], pipe_cp[2]; 

    int cid; 

    if (pipe(pipe_pc) == -1 || pipe(pipe_cp) == -1) { 
     printf("Could not pipe\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Create child process 
    cid = fork(); 

    if (cid == -1) { 
     printf("Could not fork.\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Child process 
    if (cid == 0) { 

     // Redirect pipes 
     close(STDOUT_FILENO); 
     close(STDIN_FILENO); 
     close(pipe_pc[1]); // Close writing end 
     close(pipe_cp[0]); // Close reading end 

     dup2(pipe_pc[0], STDIN_FILENO); // Take stdin from parent 
     dup2(pipe_cp[1], STDOUT_FILENO); // Give stdout to parent 

     int err; 

     // Replace child with bc 
     err = execl("/usr/bin/bc", "bc --quiet", (char*) NULL); 

     printf("%s %d\n", "Could not start bc:", err); 
     exit(err); 
    } 

    // Parent Process 
    else { 

     char input[128] = ""; 
     char buffer[128] = ""; 

     printf("%s\n", "Parent process running"); 

     // Copy argv to a single string 
     for(int i=1; i < argc; i++) { 
      strcat(input, argv[i]); 
     } 

     // Write the input to the child's stdin 
     write(pipe_pc[1], input, sizeof(input); 

     // Read the child's stdout 
     read(pipe_cp[0], buffer, sizeof(buffer)); 

     printf("Result: %s\n", buffer); 

     return 0; 
    } 

} 

ヒントとヘルプは大歓迎され、感謝を事前に!

答えて

0

問題はあなたがパイプに正しく書いていないということでしたので、bcは不正な入力を受けました。

elseブランチを書き換えました。

パイプで送信する内容がわからない場合は、パイプ記述子を一時的に0(i/fd)に置き換えて、行ったことを視覚的に確認してください。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(int argc, char *argv[]) { 

    /* Create two pipes: One from parent to child (pipe_pc) and one 
     from child to parent (pipe_cp). 
    */ 
    int pipe_pc[2], pipe_cp[2]; 

    int cid; 

    if (pipe(pipe_pc) == -1 || pipe(pipe_cp) == -1) { 
     printf("Could not pipe\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Create child process 
    cid = fork(); 

    if (cid == -1) { 
     printf("Could not fork.\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Child process 
    if (cid == 0) { 

     // Redirect pipes 
     close(STDOUT_FILENO); 
     close(STDIN_FILENO); 
     close(pipe_pc[1]); // Close writing end 
     close(pipe_cp[0]); // Close reading end 

     dup2(pipe_pc[0], STDIN_FILENO); // Take stdin from parent 
     dup2(pipe_cp[1], STDOUT_FILENO); // Give stdout to parent 

     int err; 

     // Replace child with bc 
     err = execl("/usr/bin/bc", "bc --quiet", (char*) NULL); 

     printf("%s %d\n", "Could not start bc:", err); 
     exit(err); 
    } 

    // Parent Process 
    else { 
     char buffer[128] = ""; 

     // printf("%s\n", "Parent process running"); 

     for(int i=1; i < argc; i++) 
      write(pipe_pc[1], argv[i], strlen(argv[i])); 

     write(pipe_pc[1], "\n", 1); 

     read(pipe_cp[0], buffer, sizeof(buffer)); 

     printf("Result: %s\n", buffer); 

     return 0; 
    } 

} 
0

コードには未定義の動作が多数あります。


write(pipe_pc[1], input, sizeof(input); 

あなたは、すべての入力配列を書き込みます。しかし、コピーするものはstrcat()で書く必要があります。 strlenを使用してください。ここ

write(pipe_pc[1], input, strlen(input)); 

strcat(input, argv[i]); 

あなたが128オクテットを超えないことを確認する必要があります。ここ

if (strlen(input) + strlen(argv[i]) + 1 > 128) { 
    break; 
} 
strcat(input, argv[i]); 

read(pipe_cp[0], buffer, sizeof(buffer)); 

あなたはバッファが有効なC文字列であることを確認していません。あなたが親

close(pipe_pc[0]); 
close(pipe_cp[1]); 

とあなたの読み取り/あなたはあなたの後の子供で、パイプを閉じることを忘れ

close(pipe_pc[1]); 
close(pipe_cp[0]); 

を書き終えた後に、パイプを閉じることを忘れ

ssize_t ret = read(pipe_cp[0], buffer, sizeof(buffer) - 1); 
if (ret < 0) 
    return 1; 
buffer[ret] = '\0'; 

dup2()

close(pipe_pc[1]); 
close(pipe_cp[0]); 

dup2より前に古いfdを閉じる必要はありません。彼はあなたのためにそれを行います。そして、あなたがエラーをチェックしないでくださいdup2()