8

そこで、C で Unix ミニシェルを作成し、入力、出力、およびエラーのリダイレクトを実装していますが、ファイルに関する問題に遭遇しました。リダイレクト演算子を見つけるループでファイルを開き、fd を返す open() を使用します。次に、それに応じて子の fd を割り当て、実行関数を呼び出します。

私のシェルが外に出てプログラムを見つけ、execvp() でそれらを実行しているときは、あまり問題はありません。唯一の問題は、次のコマンド ラインのプロンプトを表示する前に、ファイル記述子で close() を呼び出す必要があるかどうかを知ることです。fdリークが心配ですが、その仕組みがよくわかりません。

組み込みコマンドを使用すると、私の本当の問題が発生します。「read」という組み込みコマンドがあります。これは、環境変数名(まだ存在しない可能性があります)という1つの引数を取ります。Read は値の入力を求め、その値を変数に割り当てます。次に例を示します。

% read TESTVAR
test value test value test value
% echo  ${TESTVAR}
test value test value test value

さて、私がこのようなことを試したとしましょう:

% echo here's another test value > f1
% read TESTVAR < f1
% echo  ${TESTVAR}
here's another test value

read は親プロセス内で実行されることに注意してください。組み込みであるため、execvp で read を呼び出しません。Read は、fd ではなくストリーム変数を必要とする gets を使用します。そのため、irc フォーラムを少し調べたところ、ファイル記述子からストリームを取得するために fdopen を使用するように言われました。get を呼び出す前に、次のように呼び出します。

rdStream = fdopen(inFD, "r");

それから電話する

if(fgets(buffer, envValLen, rdStream) != buffer) 
{
    if(inFD) fclose(rdStream);
    return -1;
}
if(inFD) fclose(rdStream);

ご覧のとおり、現時点では fclose() でストリームを閉じています。ただし、stdin(0) と等しくない限りです。これは必要ですか?ストリームを閉じる必要がありますか? それともファイル記述子だけですか?または両方?どちらも同じファイルを別の方法で参照しているため、どちらを閉じるべきか非常に混乱しています。現時点では fd を閉じていませんが、絶対に閉じるべきだと思います。メモリをリークすることなく、単一のセッションで数千のコマンドを実行できるようにしたいので、シェルがファイルをリークしていないことを確認するのを誰かに手伝ってもらいたいです。

ありがとう、もうコードを投稿してほしい場合は、お尋ねください。

4

2 に答える 2

11

標準は次のように述べています。

fclose() 関数は、stream が指すストリームに関連付けられたファイル記述子に対してa と同等の処理を実行します。close()

したがって、電話fcloseで十分です。記述子も閉じます。

于 2012-12-03T20:30:04.133 に答える
2

FILE標準 C ライブラリのバッファリング オブジェクトです。(標準C関数)を実行fcloseすると、最終的にclose(Unixシステム関数)が呼び出されますが、Cライブラリバッファがフラッシュされていることを確認した後でのみです。したがって、 を使用する場合は、 だけでなくを使用する必要がfopenあります。そうしないと、一部のデータが失われる危険があります。fwritefcloseclose

于 2012-12-03T20:41:37.400 に答える