GNU/Linux >> Linux の 問題 >  >> Linux

popen() がシェルを呼び出してプロセスを実行するのはなぜですか?

POSIX system() の 2004 年版 ドキュメントには、popen() に適用される可能性が高い根拠があります。 同じように。 system() に記載されている制限に注意してください 、特に「プロセス ID が異なる」と述べているもの:

<ブロック引用>

根拠

...

system() 関数には 3 つのレベルの指定があります。 ISO C 標準は最も基本的なものです。関数が存在する必要があり、アプリケーションがコマンド言語インタープリターが存在するかどうかを照会する方法を定義します。コマンド言語やコマンドが解釈される環境については何も述べていません。

IEEE Std 1003.1-2001 は、system() に追加の制限を課しています。コマンド言語インタープリターが存在する場合、環境は fork() および exec によって指定されたとおりでなければなりません。これにより、たとえば、close-on-exec が機能すること、ファイル ロックが継承されないこと、プロセス ID が異なることが保証されます。また、コマンド ラインを実行できる場合の system() からの戻り値も指定するため、コマンドの完了ステータスに関する情報がアプリケーションに提供されます。

最後に、IEEE Std 1003.1-2001 では、IEEE Std 1003.1-2001 の Shell and Utilitiesvolume で定義されているシェル コマンド言語でコマンドを解釈する必要があります。

「ISO C標準」への複数の参照に注意してください。 C 標準の最新バージョンでは、コマンド文字列がシステムの「コマンド プロセッサ」によって処理される必要があります。

<ブロック引用>

7.22.4.8 system 関数

あらすじ

#include <stdlib.h>
int system(const char *string);

説明

string の場合 null ポインター、system 関数は、ホスト環境にコマンド プロセッサがあるかどうかを判断します。 string の場合 null ポインターではなく、system 関数は string が指す文字列を渡します 実装が文書化する方法で実行されるコマンド プロセッサ。これにより、プログラムが system を呼び出す可能性があります 不適合な方法で行動する、または終了する。

返品

引数が null ポインターの場合、system function は、コマンド プロセッサが使用可能な場合にのみ、0 以外を返します。引数が NULL ポインタではなく、system 関数が返す場合、実装定義の値を返します。

C 標準では、システムの「コマンド プロセッサ」を system() に使用する必要があるため、 電話、私はそれを疑う:

<オール>
  • popen() を結び付ける POSIX の要件がどこかにあります system() に 実装。
  • 別のプロセスとして実行する必要があるため、「コマンド プロセッサ」を完全に再利用する方がはるかに簡単です。
  • したがって、これは 2 回削除された Glib の回答です。


    シェルを呼び出すと、シェルで実行できるすべてのことを実行できます。たとえば、

    FILE *fp = popen("ls *", "r");
    

    popen() で可能です (現在のディレクトリ内のすべてのファイルを展開します)。以下と比較してください:

    execvp("/bin/ls", (char *[]){"/bin/ls", "*", NULL});
    

    ls を実行することはできません *exec(2) のため、引数として * を解釈します

    同様に、パイプ (| )、リダイレクト (>< 、 ...) などは popen で可能です .

    そうでなければ、popen を使用する理由はありません シェルが必要ない場合 - それは不要です。余分なシェル プロセスが発生し、シェルで問題が発生する可能性があるすべてのことがプログラムでも問題になる可能性があります (たとえば、渡すコマンドがシェルによって正しく解釈されず、一般的なセキュリティの問題が発生する可能性があります)。 popen() そのように設計されています。 fork + exec シェルに関連する問題がなく、ソリューションはよりクリーンです。


    glib の答えは、POSIX 標準 ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ) がそう言っているからです。というか、コマンド引数が解釈のために /bin/sh に渡されるかのように振る舞うべきだと言っています。

    したがって、準拠する実装には、原則として、別のシェルプロセスをフォークして実行することなくシェルコマンドを解釈する内部ライブラリ関数もあると思います。私は実際にそのような実装を認識していません.すべてのコーナーケースを正しくするのはかなり難しいと思います.


    Linux
    1. POSIXとは何ですか? Linux / UNIXユーザーにとってなぜ重要なのですか?

    2. シェルコマンド置換が末尾の改行文字を飲み込むのはなぜですか?

    3. Bashrcが現在のシェルがインタラクティブであるかどうかをチェックするのはなぜですか?

    1. 履歴に保存せずにシェルでコマンドを実行するにはどうすればよいですか? [Linuxのヒント]

    2. 「sudo-i」ログインシェルがヒアドキュメントのコマンド文字列引数を壊すのはなぜですか?

    3. Bash(Linux シェル)で Ctrl + V が貼り付けられないのはなぜですか?

    1. 次のコマンドがシステムを強制終了するのはなぜですか?

    2. 「ls」を実行するために別のプロセスが必要なのはなぜですか?

    3. このシェル パイプラインが終了するのはなぜですか?