システムコマンドを実行するプロセスを生成しようとしていますが、自分のプログラムはまだ進行中で、2つのプロセスが並行して実行されます。私はLinuxに取り組んでいます。
オンラインで調べたところ、exec()ファミリーを使用する必要があるようです。しかし、それは私が期待したほどには機能しません。たとえば、次のコードでは、「before」のみが表示され、「done」は表示されません。
私が何かを投げているかどうか知りたいのですが?
#include <unistd.h>
#include <iostream>
using namespace std;
main()
{
cout << "before" << endl;
execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);
cout << "done" << endl;
}
[更新]
皆さんコメントありがとうございます。今の私のプログラムはこのようになります。最後以外はすべて正常に機能します。プログラムを終了するにはEnterキーを押す必要があります。なぜ最後のエンターを押さなければならないのか分かりません。
#include <unistd.h>
#include <iostream>
using namespace std;
main()
{
cout << "before" << endl;
int pid = fork();
cout << pid << endl;
if (pid==0) {
execl("/bin/ls", "ls", "-r", "-t", "-l", (char *) 0);
}
cout << "done" << endl;
}
fork
への呼び出しがありません。 exec
が行うことは現在のプロセスイメージを置き換えるを新しいプログラムのイメージで置き換えることだけです。 fork
を使用して、現在のプロセスのコピーを生成します。その戻り値は、実行されているのが子か元の親かを示します。子の場合は、exec
を呼び出します。
変更を加えたら、プログラムが完了するためにEnterキーを押す必要があるのは表示だけです。実際に起こっているのはこれです:親プロセスは子プロセスをforkして実行します。両方のプロセスが実行され、両方のプロセスが同時にstdoutに出力します。それらの出力は文字化けします。親プロセスは子プロセスよりも処理が少ないため、最初に終了します。終了すると、それを待っていたシェルが起動し、通常のプロンプトを表示します。その間、子プロセスはまだ実行中です。より多くのファイルエントリを出力します。最後に、それは終了します。シェルは子プロセス(その孫)に注意を払っていないため、シェルにプロンプトを再印刷する理由はありません。得られた出力をより注意深く見てください。そうすれば、上記のls
出力に埋め込まれた通常のコマンドプロンプトを見つけることができるはずです。
カーソル表示は、ユーザーがキーを押すのを待機しています。これを行うと、シェルはプロンプトを出力し、すべて正常に見えます。しかし、シェルに関する限り、すべてはすでに正常でした。以前に別のコマンドを入力した可能性があります。少し奇妙に見えたでしょうが、シェルはキーボードからの入力のみを受け取り、子プロセスが画面に追加の文字を出力するのではなく、シェルが正常に実行したはずです。
別のコンソールウィンドウでtop
のようなプログラムを使用している場合は、Enterキーを押す前に、両方のプログラムの実行が完了していることを確認して確認できます。
Exec
ファミリーの関数は、現在のプロセスを新しい実行可能ファイルに置き換えます。
必要なことを行うには、fork()
関数のいずれかを使用し、子プロセスに新しいイメージexec
を持たせます。
【更新への対応】
それはあなたが言ったことを正確に実行しています:プログラムを終了するために「Enter」を押す必要はありません:プログラムはすでに終了しています。シェルはすでにプロンプトを出しました:
_[wally@zenetfedora ~]$ ./z
before
22397
done
[wally@zenetfedora ~]$ 0 << here is the Prompt (as well as the pid)
total 5102364
drwxr-xr-x. 2 wally wally 4096 2011-01-31 16:22 Templates
...
_
ls
からの出力にはしばらく時間がかかるため、プロンプトが埋め込まれます。より論理的な順序で出力を表示したい場合は、「完了」の前にsleep(1)
(またはそれ以上)を追加します。
Execl()がメモリ内の現在のプログラムを_/bin/ls
_に置き換える部分がありません。
新しいプロセスをforkして実行するpopen()
を確認し、パイプ経由で読み取りまたは書き込みできるようにすることをお勧めします。 (または、読み書きが必要な場合は、fork()
自分で、次にexec()
)