2011-11-11 10 views
6

特定の標準入力でプログラムを実行しようとしています。私は標準入力に入れたいものがあるファイルのファイルディスクリプタを使用して成功したが、私は標準入力に直接書き込むことができない:execv *とstdinに書き込む

$cat input.test 
echo Hello 
$ 

コードC:

int main(int argc, char **argv) 
{ 
    int fd = 0; 

    fd = open("input.test", O_CREAT); 
    close(STDIN_FILENO); 
    dup2(fd, STDIN_FILENO); 
    char *const args[] = { "bash", NULL }; 
    execvp("bash", args); 
} 

こと作品:

$./a.out 
Hello 
$ 

しかし、私はプログラムが何も表示されませんし、実行し続けるパイプ使用してSTDINに直接書き込むしようとした場合:

をあなたの助け

真心を込め、 バスティアン0

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

    pipe(fds); 
    close(STDIN_FILENO); 
    dup2(fds[1], STDIN_FILENO); 
    write(fds[1], "echo Hello;", 11); // Résults are identics with fds[0] 
    char *const args[] = { "bash", NULL }; 
    execvp("bash", args); 
} 

感謝。

EDIT問題解決:、

int main(void) 
{ 
    int fd[2]; 
    pid_t pid; 

    if (pipe(fd) < 0) 
     return EXIT_FAILURE; 

    if ((pid = fork()) < 0) 
     return EXIT_FAILURE; 
    else if (pid != 0) { /* father */ 
     close(fd[1]); 
     dup2(fd[0], STDIN_FILENO); 
     execlp("bash", "bash", (char *)0); 
    } else { /* son */ 
     close(fd[0]); 
     write(fd[1], "echo hello\n", 11); 
    } 

    return EXIT_SUCCESS; 
} 

答えて

4

書き込み側ではなく、パイプの読み取り側をstdinにdupする必要があります。あなたがいない場合(そして当然、書き込み側に書き込む。)

#include <unistd.h> 
#include <string.h> 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
    int fds[2]; 
    char cmd[] = "echo hello\nexit\n"; 

    pipe(fds); 
    close(STDIN_FILENO); 
    dup2(fds[0], STDIN_FILENO); 
    write(fds[1], cmd, strlen(cmd)); 
    char *const args[] = { "bash", NULL }; 
    execvp("bash", args); 
    return 0; 
} 

あなたががすべてのこれらの関数の戻り値をチェックしていることを確認し、あなたのコードをデバッグするために管理することは決してないだろう。

+0

なぜ他人を下ろしていますか?お問い合わせの心が知りたいです:) – Will

+0

私はすべての答えがdownvoted理由は考えていません。 – Mat

2

をあなたがパイプを呼び出すとfdが[0]の読み取り、およびFDのために開いている[1]である:ここにあなたの答えのための

おかげで、動作するコードを書くために開いている。読み込み側(fd [0])でstdinをdup'ingし、書き込み側(fd [1])に書き込む必要があります。 writeの戻り値をチェックします。おそらく-1です。

しかし、大きな問題があります。あなたは決してパイプの両側を閉じません。 bashは読み込みをブロックし、パイプの書き込み側が閉じられるまで何もしません。 dupとwriteの後、パイプの両側を閉じてください。 (またはFD_CLOEXECを設定します)。

3

execv現在の実行中のプログラムを指定したプログラムに置き換えます。彼らは戻りません - 代わりに新しいプログラムの開始時に実行が続けられます。

だから通常はforkで、フォークの1つにはexecvと呼んでください。その後、プログラムのパイプを読み書きし、もう一方のフォークで続けます。ほとんどの言語でこれを行うには通常popenの関数があります。 POSIXでは悲しいことですが、popen()は厳密には読み書きですが、双方向ではありません。

幸いにも、私はmade, tested and published a popen3機能です。これは、プロセスへのstdinのためのものと、stdoutとstderrのものとの2つのファイル記述子を返します。その後、stdinでwrite()を使用することができます。

0

また、パイプバッファサイズに依存していることに注意してください。あまりにも多く書くと、読者がいないので書き込みはブロックされます。それを確実に行うか、fork()を実行し、子プロセスでexecを実行し、親プロセスのパイプに書き込む必要があります。このようにパイプにはリーダーがあり、必要なだけ多くのデータを書き込むことができます。