fork()について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kazuo

fork()について

#1

投稿記事 by kazuo » 18年前

unixでいうパイプの機能を実現したいのですが、どうもうまくいきません。以下にプログラムを載せるので、
アドバイスを宜しくお願いします。
forkしてdup2をしてexecvpで実行する、という手順は踏んでいるのですが、リダイレクトや’;’,’&’等も使いたいので、
孫プロセスを呼び出して実行したいのです。
OSはFC5、コンパイラはgccです。現在システムコールについて学んでおります。
詳細やヘッダのincludeを省略すると、以下のようにしてみました:
pipe(fd);

if(fork()==0){
  
  dup2(fd[1], STDOUT_FILENO);
  close(fd[0]); 
  close(fd[1]);
  arg[0] = "ls";
  arg[1] = NULL;

  if(fork()==0){
     execvp(arg[0], arg);
    }
}

if(fork()==0){

  dup2(fd[0], STDIN_FILENO);
  close(fd[0]);
  close(fd[1]);
  arg[0] = "wc";
  arg[1] = NULL;
  
  if(fork()== 0){
    execvp(arg[0], arg);
    }

}
これで、ls|wcが実行できると思い、コンパイルして実行するのですが、実行するとファイル記述子のエラー,
と出てしまいます。
if(fork()==0){
execvp(arg[0], arg);
}
の部分を、単に
execvp(arg[0], arg);
とすれば実行はうまくいきます。これはどういうわけなのでしょうか。アドバイス宜しくお願いします。

ぽん太

Re:fork()について

#2

投稿記事 by ぽん太 » 18年前

*****印のところを付け加えたらこちらの環境では正しく動作しました。
パイプバッファをオープンしているプロセスが混在するのを防止する措置です。
この措置によりパイプバッファの書き込みと読み込みはそれぞれ1つずつのプロセスになります。
lsやwc内部でread(),write()から呼び出されるシステムコールに相等するものがが呼ばれていると思います。
これらのライブラリの仕様を見てみるとread()の場合はどこかの書き込みが開いている限り読み込み続けます。
なのでlsプログラムが書き込みを終えて書き込みを閉じても他のプロセスが開いているのでwcが読み込みをするためにブロックに陥ります。それを回避するためにclose()をそれぞれのプロセスで行いました。
実際こちらの環境ではブロックらしき挙動が見受けられました。
実際ぼくも本日数時間前に学校でシステムプログラムを習ったばかりでしかも何の説明もなくいきなり
演習しろー!と言われて演習していただけなので完全なる憶測ですが参考になれば幸いです。
pipe(fd);

if(fork()==0){
  
  dup2(fd[1], STDOUT_FILENO);
  close(fd[0]); 
  close(fd[1]);
  arg[0] = "ls";
  arg[1] = NULL;

  if(fork()==0){
     execvp(arg[0], arg);
    }
   ***** _exit(0);
}

if(fork()==0){

  dup2(fd[0], STDIN_FILENO);
  close(fd[0]);
  close(fd[1]);
  arg[0] = "wc";
  arg[1] = NULL;
  
  if(fork()== 0){
    execvp(arg[0], arg);
    }
 ***** close(STDIN_FILENO)
}
  ***** close(fd[0]);
  ***** close(fd[1]);

閉鎖

“C言語何でも質問掲示板” へ戻る