- ベストアンサー
UNIX関数?(popen)について
Cプログラムでpopen関数?を使用しコマンド(rcp)を実行するプログ ラムを造ったのですが、当分が動作していたのですが、何のタイミングか分からないのですが、失敗する時が有ります。一度失敗するとそれ以降はずーと失敗します 。どのような原因が考えられるのでしょうか? ちなみにプログラムの一部をとりあえずのせておきます。(ファイル名及び相手先 のディレクトリ名は現状存在します) 又、system関数とpopen関数の大きな違いは何でしょうか? ご教示お願い致します。 (cプログラムの一部) char buff[256] ; char cmnd[256] ; /* コマンド文字列 */ int fp_rtc ; memset( buff, NULL, sizeof(buff) ) ; memset( cmnd, NULL, sizeof(cmnd) ) ; strcpy( buff, argv[1] ) ; sprintf(cmnd, RCP_FMT , buff, RCP_DIR, buff ) ; printf( "rcp cmnd ( %s )\n", cmnd ) ; fp = popen(cmnd, "r") ; fflush(stdout) ; fp_rtc = pclose(fp) ; if ( fp_rtc != 0 ){ printf( "pclose err [ rtc:%d ] \n", fp_rtc ) ; }
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
どうもどうも。 え~とですね。fflush()は出力バッファにたまっているデータを吐き出すための関数ですよね。 ところが、今回のケースでは、popen()を読みこみ用に使っています。ですからfflush()は関係ありません。 (ご質問のプログラムではfflush()の引数をstdoutとしていますが、なおのこと、これはpopen()の返した fpとは何の関係もありません。) 親プロセス側でfflush()が呼ばれても、子プロセス側でfflush()が実行されるものでもありません。
その他の回答 (4)
- ranx
- ベストアンサー率24% (357/1463)
まずお詫びをしなくてはいけません。 私の思い違いで、間違ったことを書いてしまいました。 pclose()は、子プロセスの終了ステータスを返します。 ですから、この扱い方については、hiropopさんの元の プログラムで良かったのだと思います。 というわけで、 > pcloseの戻り値と言うのは、変数fpを使用して何か実行した > 結果(ここでは関数fgetの結果)のことでしょうか? ということではありません。 > 何も実行せずpcloseを行うとpcloseの戻り値はエラーになる > (可能性がある)と言うことでしょうか? 一応その通りなのですが、誤解があるといけませんので、もう少し説明して おきます。実のところ、もし子プロセスが何も出力せずに終了しているのなら、 fpを使って何かを読み出すという処理は全く必要ありません。(もっとも、 その場合はpopen()を使う必然性がないことになりますが。)問題は、 親プロセスがpclose()を使ってパイプを閉じた後、子プロセスがその 閉じられたパイプに何かを出力しようとした時に起こります。その場合、 No.2でも書きましたが、「閉じたパイプに書き込んだ(SIGPIPE)」という エラーが起こり、子プロセスは強制終了されます。その情報がpclose()の 戻り値として返されるわけです。
補足
ありがとうごさいます。が、いまいち動きがつかめていないようで、悩んでいます。いろいろと教えて頂いて恐縮しています。 今回のpopen()-pclose()の間にffush()関数を使用したとしても、全然読まれないままpcloseされてしまうとゆうことでしょうか? お忙しいのに、覚えが悪く申し訳ございません。もうすこし教えて頂けないでしょうか?
- ranx
- ベストアンサー率24% (357/1463)
ご無沙汰しました。 > 「全然読まないままpclose()している」と有りますが、どうゆうことでしょうか? fp = popen(cmnd, "r") ; として、popen()の戻り値を変数fpに入れていますよね。この値は子プロセスの標準 出力を親プロセスで読み取るために使われます。 例えばこんな感じです。 char buff2[256]; fp = popen(cmnd, "r"); while (fgets(buff2, 256, fp) != NULL) { /* buff2 を使う処理 */ } if (pclose(fp) < 0) { printf("pclose err [errno:%d]\n", errno); }
補足
いろいろとありがとうございます。 確認ですが、pcloseの戻り値と言うのは、変数fpを使用して何か実行した 結果(ここでは関数fgetの結果)のことでしょうか? 又、何も実行せずpcloseを行うとpcloseの戻り値はエラーになる (可能性がある)と言うことでしょうか? すみませんが教えて下さい。宜しくお願い致します。
- ranx
- ベストアンサー率24% (357/1463)
pclose()が子プロセスをkill()するというterra5さんの回答は、必ずしも すべてのシステムでの仕様ではありません。少なくとも、私の手元にある Vine Linux ではpclose()は子プロセスをwait4()することになっています。 (むしろ、私はterra5さんの仰るようなシステムに心当たりがありません。) で、ご質問のプログラムでは、子プロセスの出力を親プロセスが読み取れる ようにして起動しているわけですが、全然読まないままpclose()しています。 この場合、子プロセス側は「閉じたパイプに書き込んだ」というエラーに なる可能性があります。 pclose()はエラーの場合、常に-1を返します。エラーの内容を知りたい時は #include <errno.h> とした上で、extern宣言されているint型変数errnoの値を読み取りましょう。 余談ですが、system()およびpclose()はシェルを起動して、コマンド列を 渡します。従って、コマンド列の最後に'&'をつけておけば、system()でも コンカレントな実行が可能です。
お礼
ありがとうございました。 又、下記質問が有ります。宜しくお願い致します。 >全然読まないままpclose()しています。 この場合、子プロセス側は「閉じたパイプに書き込んだ」というエラーに なる可能性があります。 「全然読まないままpclose()している」と有りますが、どうゆうことでしょうか? 御教示お願い致します。
補足
ありがとうございました。 又、下記質問が有ります。宜しくお願い致します。 >全然読まないままpclose()しています。 この場合、子プロセス側は「閉じたパイプに書き込んだ」というエラーに なる可能性があります。 「全然読まないままpclose()している」と有りますが、どうゆうことでしょうか? 御教示お願い致します
- terra5
- ベストアンサー率34% (574/1662)
>system関数とpopen関数の大きな違いは何でしょうか? systemは指定されたコマンドを実行するプロセスを生成し、完了するまで呼び出したほうはwait状態になります。 popenはどちらのプロセスも動作状態になります。 また、popenされた場合標準入出力がpopenの戻り値である FILE *にリダイレクトされていますが、systemは元と同じものを使用します。 また、pclose()でプロセスがまだ実行中の場合はkillされます。 質問のプログラムだと、systemを使うべきで, popenを使うのは変に思えますが。 popenは本来プロセス間でファイルi/oによる同期処理が必要な場合に使うものですから。 systemだとwaitするから嫌だと言う話なら,forkしてexecするべきでしょう。 不調の原因はプロセスが完了する前にpcloseしているかららも知れません。
お礼
ありがとうございました
お礼
いろいろとアリガトウございました。また、なにか有った時は宜しくお願い致します。