2

私はCでunixコマンドシェルを複製するという宿題に取り組んでいます。

バックグラウンド実行(&)で単一コマンドを実行するまで実装しました。

現在、パイプを実装する段階にあり、この問題に直面しています。1より大きいパイプの場合、パイプを含む子コマンドは完了しますが、最終出力はstdoutに表示されません(最後のコマンドのstdinはreadに置き換えられます)最後のパイプの)

dup2(pipes[lst_cmd], 0);

fflush(STDIN_FILENO)親もやってみました。

プログラムの終了はCONTROL-Dであり、これを押すと、出力が表示されます(CONTROL-Dでの操作はexit(0)であるため、終了します)。

パイプの出力はstdoutバッファーにあると思いますが、表示されません。バッファ内のものをstdoutにするためにフラッシュする以外の手段はありますか?

4

1 に答える 1

0

コードを見た後(不当な利点)、主な問題は、パイプを完全に閉じないことと組み合わされたプロセス構造でした。

パイプラインのプロセス構造ps | sortは次のとおりです。

main shell
    - coordinator sub-shell
        - ps
        - sort

メインシェルはN本のパイプを作成していました(N = 1の場合ps | sort)。次に、コーディネーターシェルが作成されました。N+1の子を開始します。しかし、彼らが終了するのを待たず、パイプのコピーを閉じませんでした。また、メインシェルはパイプのコピーを閉じませんでした。

より通常のプロセス構造は、おそらくコーディネーターサブシェルなしで実行されます。子を生成するための2つのメカニズムがあります。従来、メインシェルは1つのサブプロセスをフォークしていました。パイプラインの最初のN個のプロセスの調整を行い(最初にパイプを作成することを含む)、次にパイプラインの最後のプロセスを実行します。メインシェルは1つの子が終了するのを待ち、パイプラインの終了ステータスは子の終了ステータス(パイプラインの最後のプロセス)です。

最近でbashは、メインシェルがパイプライン内の各子のステータスを取得するメカニズムを提供しています。それは調整を行います。

主な修正(主にマイナーなコンパイル警告を除く)は次のとおりです。

  1. コーディネーターをフォークした後、メインシェルはすべてのパイプを閉じます。
  2. メインシェルは、コーディネーターが完了するのを待ちます。
  3. コーディネーターは、パイプラインをフォークした後、すべてのパイプを閉じます。
  4. コーディネーターは、パイプライン内のすべてのプロセスが完了するのを待ちます。
  5. コーディネーターが終了します(決闘のデュアルプロンプトを提供するために戻る代わりに)。

より良い修正は、コーディネーターサブシェルを排除します(これは、説明されている従来のシステムのように動作します)。

于 2012-11-25T17:02:58.787 に答える