2011-07-15 18 views
1

パイプをパイプで再現しようとしています。例えばls |ソート まず、私はパイプをしようとしていますが、私は親が子供が実行された内容の結果を読み取るために取得することはできません。Cのパイプ、フォーク、シェルのコマンド

//pipes essai 
# include <stdio.h> 
# include <stdlib.h> 
# include <unistd.h> 
# include <sys/types.h> 
# include <sys/wait.h> 
# include <assert.h> 
# include <string.h> 
# include <sys/stat.h> 
# include <fcntl.h> 

enum { 
MaxLigne = 1024, // longueur max d'une ligne de commandes 
MaxMot = MaxLigne/2, // nbre max de mot dans la ligne 
MaxDirs = 100, // nbre max de repertoire dans PATH 
MaxPathLength = 512, 
// longueur max d'un nom de fichier 
}; 

void decouper(char *, char *, char **, int); 
int spawn(char * pathname, char * mot[]); 

# define PROMPT "? " 

int main(int argc, char * argv[]) { 
char ligne[MaxLigne]; 
char pathname[MaxPathLength]; 
char * mot[MaxMot]; 
char * dirs[MaxDirs]; 
int i, tmp, x; 
int fd[2]; 
int t, res = 0; 
char buf[1024]; 
char * mot2[10]; 

/* Decouper PATH en repertoires */ 
decouper(getenv("PATH"), ":", dirs, MaxDirs); 

/* read the command lines and try to execute them */ 
for (printf(PROMPT); fgets(ligne, sizeof ligne, stdin) != 0; printf(PROMPT)) { 
    decouper(ligne, " \t\n", mot, MaxMot); 
    if (mot[0] == 0) // empty line 
     continue; 

     //launch the pipe 
     int p=pipe(fd); 
     assert(p>=0); 


     tmp = fork(); // launch the pipe process 
     if (tmp < 0) { 
      perror("fork"); 
      continue; 
     } 

     if (tmp != 0) { // parent wait for end of child 

      //close this side of the pipe 
      close(fd[1]); 
      //waiting 
      while (wait(0) != tmp) 
       ; 
      //when finish waiting read what the child has written in the pipe 
      read(fd[0], buf, sizeof(buf)); 
      //print the result 
      printf("read %s\n", buf); 
      //get back the hand to the user 
      continue; 

     }else if (tmp==0){ 

     // child 

     //close this side of the pipe 
     close(fd[0]); 
     //close stdout 
     t=close(1); 
     //make sur stdout is closed 
     assert(t>=0); 
     //open the pipe for writing in it instead of in the stdout 
     FILE * sortie=fdopen(fd[1], O_WRONLY); 
     //make sure it is ok 
     assert(sortie!=NULL); 

     //try to execute the command 
     for (i = 0; dirs[i] != 0; i++) { 
      snprintf(pathname, sizeof pathname, "%s/%s", dirs[i], mot[0]); 
      execv(pathname, mot); 

     } 
     } 

     // if exec was unsuccessful 
     fprintf(stderr, "%s: not found\n", mot[0]); 
     exit(1); 

} 

    printf("Bye\n"); 
    return 0; 

} 

void decouper(char * ligne, char * separ, char * mot[], int maxmot){ 
int i; 

mot[0] = strtok(ligne, separ); 
for(i = 1; mot[i - 1] != 0; i++){ 
if (i == maxmot){ 
    fprintf(stderr, "Erreur dans la fonction decouper: trop de mots\n"); 
    mot[i - 1] = 0; 
} 
mot[i] = strtok(NULL, separ); 
} 
} 

このラインファイルに問題がある*出撃=のfdopen(FD [ 1]、O_WRONLY);

pipe1.c:機能において 'メイン': pipe1.c:4:81警告:通過 'のfdopen' の引数2キャスト /usr/include/stdio.h:303なし整数からポインタを行います:14:note:予想される 'const char *'ですが、引数の型は 'int'

ですが、パイプで出力するにはどうすればいいですか? freopenはどちらでも動作しません

結果: ? ls read

もちろん何も読まれません。私は何をすればいいのですか? ありがとうございます。

+0

fdopenは、fopenと同様に文字列モードをとります。 fdopen(fd [1]、 "w")と置き換えてみてください。これは役に立ちますか? – theamk

答えて

1

fdopenの署名はopenのものと混同しています。 fdopenは、その第2パラメータとしてconst char*をとります。


EDIT:あなたがいない正当な理由 fdopenを使用していることが表示されます

FILE * sortie=fdopen(fd[1], "w"); 

参照してみてください。具体的には、初期化後に私はsortieの使用を見ません。

私はあなたがexec'dプログラムのための標準を設定しようとしていると推測します。そのような場合は、dupdup2を使用する必要があります。

close(fd[0]); 
close(1); 
dup(fd[1]); 
close(fd[1]); 

//try to execute the command 
... as before 

参考:

+0

私はそれを "w"に置き換えました。もうエラーは出ませんでしたが、私はこの間違いを受け取ります:ls:erreur d'écriture:Mauvais descripteur de fichierは基本的に間違ったファイル記述子を意味します – vallllll

+0

freopenについては、 FILE * freopen(const char * path、const char * mode、FILE * stream);これは次の理由で使用しないでください。だから私はファイル名が必要です、私はファイル記述子しか持っていませんが、何とかそれを使用する方法はありますか? – vallllll

+0

@vallllll - 申し訳ありませんが、私はfdopenの誤った使い方を見て、それ以上は見えませんでした。あなたは 'fdopen'を望んでいません。それはあなたが思っていることをしません。 'dup'またはおそらく' dup2'が必要です。私の編集を参照してください。 –

2

別の問題...

は子供が書き込まれた場合パイプに多くの出力がある場合、親がいくつかを読み込むまでブロックされます。パイプの容量は限られています(怠惰は私が典型的な限界を調べるのを妨げます)。

親コードは、子プロセスが終了するまで読書を行いません。しかし、子供がパイプ出力をブロックすると、決して終了しません。デッドロック!

+0

当日は10x512でした。私は現代の限界が何であるか分かりません。よく書かれたプログラムは決して知らない。 –

+0

これはlsコマンドの出力です:arriere_plan ch-spawn.c decouper.c moncd.c validation arriere_plan.c co-main.c moncd pipe1 6ファイルのようにそれほど制限できませんか? – vallllll

+0

私はそれが唯一の問題ではないと主張しませんでした。ただの問題。 5Kかそこらは古い学校の限界の私の記憶だった。 –

関連する問題