以下の短いプログラムは、コマンドラインから渡されたargvを反復し、各引数をexecすることを意図しています。これは私の宿題ではなく、むしろ私が宿題をする準備としてやっていることです。Unixファイル記述子がC言語でどのように機能するのか理解していますか?
最初の引数は、STDINおよびSTDOUTからの入力を取得し、パイプに書き込みます。各繰り返しの最後に(最後のものを除く)、ファイルディスクリプタがスワップされるので、最後のexecによって書き込まれたパイプは、次のパイプから読み込まれます。
./a.out /bin/pwd /usr/bin/wc
は、作業ディレクトリの長さだけを印刷するためにこのように私は、例えば、意図しています。コードは
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
main(int argc, char * argv[]) {
int i;
int left[2], right[2], nbytes; /* arrays for file descriptors */
/* pointers for swapping */
int (* temp);
int (* leftPipe) = left;
int (* rightPipe) = right;
pid_t childpid;
char readbuffer[80];
/* for the first iteration, leftPipe is STDIN */
leftPipe[0] = STDIN_FILENO;
leftPipe[1] = STDOUT_FILENO;
for (i = 1; i < argc; i++) {
/* reopen the right pipe (is this necessary?) */
pipe(rightPipe);
fprintf(stderr, "%d: %s\n", i, argv[i]);
fprintf(stderr, "%d %d %d %d\n", leftPipe[0], leftPipe[1], rightPipe[0], rightPipe[1]);
if ((childpid = fork()) == -1) {
perror("fork");
exit(1);
}
if (childpid == 0) {
/* read input from the left */
close(leftPipe[1]); /* close output */
dup2(leftPipe[0], STDIN_FILENO);
close(leftPipe[0]); /* is this necessary? A tutorial seemed to be doing this */
/* write output to the right */
close(rightPipe[0]); /* close input */
dup2(rightPipe[1], STDOUT_FILENO);
close(rightPipe[1]);
execl(argv[i], argv[i], NULL);
exit(0);
}
wait();
/* on all but the last iteration, swap the pipes */
if (i + 1 < argc) {
/* swap the pipes */
fprintf(stderr, "%d %d %d %d\n", leftPipe[0], leftPipe[1], rightPipe[0], rightPipe[1]);
temp = leftPipe;
leftPipe = rightPipe;
rightPipe = temp;
fprintf(stderr, "%d %d %d %d\n", leftPipe[0], leftPipe[1], rightPipe[0], rightPipe[1]);
}
}
/* read what was last written to the right pipe */
close(rightPipe[1]); /* the receiving process closes 1 */
nbytes = read(rightPipe[0], readbuffer, sizeof(readbuffer));
readbuffer[nbytes] = 0;
fprintf(stderr, "Received string: %s\n", readbuffer);
return 0;
}
UPDATEを次の:私はもともと/ binに/トイレ使用されるがしていた以下の試験例すべては、私が思ったところ水のクローゼットが全くないことをreveiled WCで。私は結果を修正する過程にある。
些細な場合の出力(./a.out /ビン/ PWD)は予想通りである:
1: /bin/pwd
Received string: /home/zeigfreid/Works/programmatical/Langara/spring_2012/OS/labs/lab02/play
最初の例(./a.out /ビンにこのプログラムを実行してから出力/ pwd/usr/bin/wc):
1: /bin/pwd
0 1 3 4
3 4 0 1
2: /bin/wc
この時点で、端末がハングアップしています(入力待ちの可能性があります)。
ご覧のとおり、文字列は受信されていません。私が想像していることは、上記の何かを間違って実行したことです。ポインタを交換したり、UNIXファイル記述子を理解できないことがあります。私の割り当ては、最終的には、任意に長いパイプを解釈することになります。これは私が問題を解決するために持っていたアイデアの1つです。私は木を吠える正しい道にいるかどうかを判断するのが難しい。私はUNIXファイル記述子を理解していますか?
UPDATE:
1: /bin/pwd
0 1 3 4
0 1 3 4
3 4 0 1
2: /bin/ls
3 4 5 6
Received string: a.out
log
pipe2.c
play.c
@
があります:第二引数として/ binは/ LSとそれを実行する
は、私は次の結果(数字は様々なポイントでのファイル記述子である)を得ましたそこにはまだゴミが残っていますが、今私はポインタを理解できないと心配しています!これらの2つのコマンドは互いに独立していますが、実際にはパイプを使用しません。
更新日:ガベージ文字は、文字列を閉じていないことが原因でした。今私はそれを閉じ、ごみはありません。
を私は 'すべてのあなたの'のprintf(...)を変更することをお勧めしたいと思います 'fprintfの(stderrのに呼び出します、...) '。低レベルのルーチンと標準IO( 'のprintf(3)')を混合する( 'パイプ(2)' 'dup2のは、(2)' '近い(2)')それは価値があるよりも多くの問題です。 – sarnold
Dulyが注目しました!私は副子が同意すると思います。 – Ziggy
あなたはそれを印刷する前に、文字列を終了していない、これはごみを説明しています。 'read'の後に' readbytes [nbytes] = 0'を試してください。 –