8

system("PAUSE")usingは悪い習慣であり、std::cin.get()代わりに使用するとよく耳にします。システムコールについての私の理解では、システムコールはシステムコマンドラインに入力してOSと通信する文字列を取得するため、PAUSEはコマンドウィンドウで出力を一時停止するDOSコマンドです。これは、異なるキーワードを使用する Mac と UNIX でも同様に機能すると思います。OS 間の互換性がないため、システム コールの使用は推奨されません。(これについて間違っている場合は、修正してください)

私の質問はこれです: system() 呼び出しを使用するのが適切なのはいつですか? それらはどのように適用されるべきですか?それらはいつ適用されるべきではありませんか?

4

6 に答える 6

31

system("PAUSE")確かに理想的とは言えません。システムへの呼び出しを使用すると、サブプロセスが作成されます。これは、Windows ではかなり高価であり、いずれにせよ、どのオペレーティング システムでもそれほど安価ではありません。組み込みシステムでは、メモリのオーバーヘッドが大きくなります。

ネイティブであまり苦労せずにそれを行う方法があれば、それを行います。ユーザーが 1 つのボタンを押すのを待つ場合、cin.get() は非常に打ち負かされません。この場合、アプリケーション プロセスは stdin でブロックされ、カーネルに表示されるいくつかのフラグのみが設定されます。最も重要なことは、新しいメモリを割り当てず、新しいスケジューリング エンティティを作成せず、割り込みハンドラさえも作成しません。

さらに、OS が提供するものに依存するのではなく、言語の非常に標準的な部分の非常に基本的な機能のみを使用するため、すべての C++ コンパイラを備えたすべてのオペレーティング システムで同じように動作します。

編集:アイデア全体が一時停止するため、費用がかかるかどうかは問題ではないという懸念を予測します。まず第一に、それが高価であると、他の何が起こっているかのパフォーマンスを損なうことになります。(Windows 上で) 1 つのアプリケーションが起動しているときに、他の既に開いているアプリの応答が遅くなったことに気付いたことはありませんか? さらに、ユーザーは実際の人間ではなく、人間のユーザーに代わって動作する別のプログラム (たとえば、シェル スクリプト) である可能性があります。スクリプトは次に何をすべきかをすでに知っており、標準入力に文字を事前に入力して待機をスキップできます。ここでサブプロセスを使用した場合、スクリプトで (人間が認識できる) 遅延が発生します。スクリプトがこれを数百回 (または数億回!) 実行すると、実行に数秒かかるスクリプトが数日または数年かかることになります。

EDIT2: いつ使用するsystem()か: 別のプロセスが行う、簡単にできないことをする必要がある場合。 system()やや限定的な 2 つのことを行うため、常に最適な候補とは限りません。まず、サブプロセスと通信する唯一の方法は、入力としてコマンド ライン引数を使用し、出力として値を返すことです。2 つ目は、子プロセスが完了するまで親プロセスがブロックされることです。これらの 2 つの要因により、システムが使用できるケースが制限されます。

unixy システムでは、ほとんどのサブプロセスが発生しforkます。これは、同じプログラムが 2 つの別個のプロセスとして同じ場所で、一方が他方の子プロセスとして続行できるためです (これは、OS から要求しない限りほとんど気付かれません)。Linux では、これは特に適切に最適化されており、pthread を作成するのとほぼ同じくらい安価です。これがそれほど高速ではないシステムでも、非常に便利です (apache プロセスプール方法論で実証されているように) (Windows では利用できません/ UNIX ドキュメントへのリンク) 。

他のケース (Windows でも!) は、多くの場合、関数popenまたはexec関数ファミリーによって処理されます。 popenサブプロセスと、サブプロセスの stdin または stdout に接続する新しいパイプを作成します。親プロセスと子プロセスの両方が同時に実行され、非常に簡単に通信できます。( Windows ドキュメントへのリンク/ Unix ドキュメントへのリンク)

exec* 一方、一連の関数 (execl、execv などいくつかあります) は、現在のプログラムを新しいプログラムに置き換えます。元のプログラムは目に見えないまま終了し、新しいプロセスが引き継ぎます。その後、新しいプロセスが戻ると、そのプロセスが消滅するのではなく、その時点で戻ってきたかのように、元のプロセスと呼ばれるものに戻ります。これの利点はexit(system("command"))、新しいプロセスが作成されず、時間とメモリを節約できることです (ただし、常にそれほど多くはありません) ( Windows ドキュメントへのリンク/ UNIX ドキュメントへのリンク)

systemいくつかのスクリプト化されたツールによって、いくつかのレシピ アクションでいくつかのステップを呼び出すために使用される可能性があります。たとえば、ある時点で、プログラムは を使用systemしてテキスト エディターを呼び出し、構成ファイルを編集することができます。何が起こるかについてあまり気にする必要はありませんが、続行する前に、ユーザーがエディターを保存して閉じるまで待つ必要があります。次に、戻り値を使用して、エディターが要求されたファイルを実際に開いた (そしてエディター自体が存在した) という意味で、編集セッションが成功したかどうかを調べることができますが、セッションの実際の結果をサブプロセスと通信するのではなく、編集されたファイルを直接。( Windows ドキュメントへのリンク/ Unix ドキュメントへのリンク)

于 2009-05-23T02:12:50.803 に答える
3

ちなみに、system()呼び出しは、SUIDまたはSGIDビットが設定されたバイナリで使用しないでください。manページから引用します。

set-user-ID または set-group-ID 権限を持つプログラムから system() を使用しないでください。一部の環境変数の奇妙な値がシステムの整合性を破壊するために使用される可能性があるためです。代わりに exec(3) ファミリの関数を使用してください。ただし、execlp(3) または execvp(3) は使用しないでください。実際、system() は、/bin/sh が bash バージョン 2 であるシステムでは、set-user-ID または set-group-ID 権限を持つプログラムからは正しく機能しません。これは、bash 2 が起動時に権限を失うためです。

于 2012-11-06T09:09:49.673 に答える
3

システム コールは、OS のシェルまたはコマンド ライン インタープリター (dos、bash など) に送信され、シェルはこのコマンドで必要なことを実行します。

この種の呼び出しを使用すると、他のオペレーティング システムで動作するプログラムの移植性が低下するため、使用しないでください。コードが特定の OS を対象としていることが絶対に確実な場合にのみ、そのような呼び出しを使用する必要があると思います。

于 2009-05-23T02:14:53.467 に答える
3

しかし、私の質問は次のとおりです。いつ system() 呼び出しを使用するのが適切ですか? それらはどのように適用されるべきですか?

自分のコードやライブラリでやろうとしていることができない場合 (または、それを実装するためのコストが、そのための新しいプロセスを起動するためのコストを上回ります)。system() は、cin.get() と比較してシステム リソースの点でかなりコストがかかるため、絶対に必要な場合にのみ使用する必要があります。system() は通常、新しいシェル全体と実行するように要求したプログラムの両方を起動するため、2 つの新しい実行可能ファイルが起動されることに注意してください。

于 2009-05-23T02:15:10.923 に答える
2

system()オペレーティングシステムにプログラムの実行を要求するために使用されます。

なぜあなたのプログラムはオペレーティングシステムにプログラムを実行させたいのですか?さて、場合があります。外部プログラムまたはオペレーティングシステムコマンドが、独自のプログラムでは実行が難しいタスクを実行する場合があります。たとえば、外部プログラムは、昇格された特権で動作したり、適切なデータ形式にアクセスしたりする場合があります。

system()関数自体はかなり移植性がありますが、渡すコマンド文字列はプラットフォーム固有である可能性があります。ただし、コマンド文字列をローカル構成データから取得して、プラットフォームに依存しないようにすることができます。

、、などfork()の他の関数を使用すると、外部プログラムの実行方法をより細かく制御できますが、プラットフォーム固有であり、選択したプラットフォームでは使用できない場合があります。exec*()spawn*()CreateProcess()

system("PAUSE")は古いDOSトリックであり、最近では一般的にかなりざらざらしたスタイルと見なされています。

于 2009-05-23T08:18:59.590 に答える
1

私の知る限り、system("PAUSE") は Windows のみのものであり、それが眉をひそめている理由です。

于 2009-05-23T02:08:29.673 に答える