• ベストアンサー

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 ) ; }

質問者が選んだベストアンサー

  • ベストアンサー
  • ranx
  • ベストアンサー率24% (357/1463)
回答No.5

どうもどうも。 え~とですね。fflush()は出力バッファにたまっているデータを吐き出すための関数ですよね。 ところが、今回のケースでは、popen()を読みこみ用に使っています。ですからfflush()は関係ありません。 (ご質問のプログラムではfflush()の引数をstdoutとしていますが、なおのこと、これはpopen()の返した fpとは何の関係もありません。) 親プロセス側でfflush()が呼ばれても、子プロセス側でfflush()が実行されるものでもありません。

hiropop
質問者

お礼

いろいろとアリガトウございました。また、なにか有った時は宜しくお願い致します。

その他の回答 (4)

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.4

まずお詫びをしなくてはいけません。 私の思い違いで、間違ったことを書いてしまいました。 pclose()は、子プロセスの終了ステータスを返します。 ですから、この扱い方については、hiropopさんの元の プログラムで良かったのだと思います。 というわけで、 > pcloseの戻り値と言うのは、変数fpを使用して何か実行した > 結果(ここでは関数fgetの結果)のことでしょうか? ということではありません。 > 何も実行せずpcloseを行うとpcloseの戻り値はエラーになる > (可能性がある)と言うことでしょうか? 一応その通りなのですが、誤解があるといけませんので、もう少し説明して おきます。実のところ、もし子プロセスが何も出力せずに終了しているのなら、 fpを使って何かを読み出すという処理は全く必要ありません。(もっとも、 その場合はpopen()を使う必然性がないことになりますが。)問題は、 親プロセスがpclose()を使ってパイプを閉じた後、子プロセスがその 閉じられたパイプに何かを出力しようとした時に起こります。その場合、 No.2でも書きましたが、「閉じたパイプに書き込んだ(SIGPIPE)」という エラーが起こり、子プロセスは強制終了されます。その情報がpclose()の 戻り値として返されるわけです。

hiropop
質問者

補足

ありがとうごさいます。が、いまいち動きがつかめていないようで、悩んでいます。いろいろと教えて頂いて恐縮しています。 今回のpopen()-pclose()の間にffush()関数を使用したとしても、全然読まれないままpcloseされてしまうとゆうことでしょうか? お忙しいのに、覚えが悪く申し訳ございません。もうすこし教えて頂けないでしょうか?

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.3

ご無沙汰しました。 > 「全然読まないまま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); }

hiropop
質問者

補足

いろいろとありがとうございます。 確認ですが、pcloseの戻り値と言うのは、変数fpを使用して何か実行した 結果(ここでは関数fgetの結果)のことでしょうか? 又、何も実行せずpcloseを行うとpcloseの戻り値はエラーになる (可能性がある)と言うことでしょうか? すみませんが教えて下さい。宜しくお願い致します。

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.2

pclose()が子プロセスをkill()するというterra5さんの回答は、必ずしも すべてのシステムでの仕様ではありません。少なくとも、私の手元にある Vine Linux ではpclose()は子プロセスをwait4()することになっています。 (むしろ、私はterra5さんの仰るようなシステムに心当たりがありません。) で、ご質問のプログラムでは、子プロセスの出力を親プロセスが読み取れる ようにして起動しているわけですが、全然読まないままpclose()しています。 この場合、子プロセス側は「閉じたパイプに書き込んだ」というエラーに なる可能性があります。 pclose()はエラーの場合、常に-1を返します。エラーの内容を知りたい時は #include <errno.h> とした上で、extern宣言されているint型変数errnoの値を読み取りましょう。 余談ですが、system()およびpclose()はシェルを起動して、コマンド列を 渡します。従って、コマンド列の最後に'&'をつけておけば、system()でも コンカレントな実行が可能です。

hiropop
質問者

お礼

ありがとうございました。 又、下記質問が有ります。宜しくお願い致します。 >全然読まないままpclose()しています。 この場合、子プロセス側は「閉じたパイプに書き込んだ」というエラーに なる可能性があります。 「全然読まないままpclose()している」と有りますが、どうゆうことでしょうか? 御教示お願い致します。

hiropop
質問者

補足

ありがとうございました。 又、下記質問が有ります。宜しくお願い致します。 >全然読まないままpclose()しています。 この場合、子プロセス側は「閉じたパイプに書き込んだ」というエラーに なる可能性があります。 「全然読まないままpclose()している」と有りますが、どうゆうことでしょうか? 御教示お願い致します

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.1

>system関数とpopen関数の大きな違いは何でしょうか? systemは指定されたコマンドを実行するプロセスを生成し、完了するまで呼び出したほうはwait状態になります。 popenはどちらのプロセスも動作状態になります。 また、popenされた場合標準入出力がpopenの戻り値である FILE *にリダイレクトされていますが、systemは元と同じものを使用します。 また、pclose()でプロセスがまだ実行中の場合はkillされます。 質問のプログラムだと、systemを使うべきで, popenを使うのは変に思えますが。 popenは本来プロセス間でファイルi/oによる同期処理が必要な場合に使うものですから。 systemだとwaitするから嫌だと言う話なら,forkしてexecするべきでしょう。 不調の原因はプロセスが完了する前にpcloseしているかららも知れません。

hiropop
質問者

お礼

ありがとうございました

関連するQ&A

  • popen・pcloseについて

    popen・pcloseについて 以下のようにpopenを使ってdirコマンドを打った時と同じようなプログラムを Microsoft Visual C++ 2008上で作ったのですが #include <stdio.h> int main(void) { FILE *fp; char buff[64]; fp=popen("dir","r"); while(fgets(buff,sizeof(buff),fp)!=NULL){ printf("%s",buff); } pclose(fp); return 0; } これをビルドした所、以下のようなエラーが出てしまいました。 c:\users\yamaomoto\documents\visual studio 2008\projects\popen\popen\popen.c(8) : warning C4013: 関数 'popen' は定義されていません。int 型の値を返す外部関数と見なします。 c:\users\yamaomoto\documents\visual studio 2008\projects\popen\popen\popen.c(8) : warning C4047: '=' : 間接参照のレベルが 'FILE *' と 'int' で異なっています。 c:\users\yamaomoto\documents\visual studio 2008\projects\popen\popen\popen.c(14) : warning C4013: 関数 'pclose' は定義されていません。int 型の値を返す外部関数と見なします。 popen.obj : error LNK2019: 未解決の外部シンボル _pclose が関数 _main で参照されました。 popen.obj : error LNK2019: 未解決の外部シンボル _popen が関数 _main で参照されました。 C:\Users\Yamaomoto\Documents\Visual Studio 2008\Projects\popen\Debug\popen.exe : fatal error LNK1120: 外部参照 2 が未解決です。 色々と試してみたのですが解決に至りませんでしたのでよろしければ、 教えて頂けませんでしょうか?

  • _popen() のエラー取得

    WindowsNT/2000で_popen()を利用してコマンドを実行しているのですが、その際のメッセージを取得したいのですが、通常のメッセージは取得出来るのですが、エラーメッセージが取得出来ません。どうすればよいのでしょうか? 現在のソースは下記のようです。 int main(int argc, char* argv[]) { char str[512],*ptr; FILE *fp; if((fp = _popen("dir b:","rt")) == NULL) { fprintf( stderr , "error!!!\n"); return -1; } while(1) { fgets(str,512,fp); if(feof(fp)) { break; } ptr = strchr(str,'\n'); if(ptr != NULL) { *ptr='\0'; } printf("%s\n",str); } _pclose(fp); return 0; }

  • popenについて

    現在、UNIX同士の通信で以下のような処理をしています。 fp = popen( "rsh -l user host /xxx/yyy/zzzzz > aaa.txt", "w" );      : ret = fprintf( fp, "%s\n", buff );      : ret = fprintf( fp, "%s\n", buff ); pclose( fp ); 今回、こちらをWindowsPC(XP,C/C++で開発)に変更しようとしています。 相手は変更せずに、同じことをするには、どういう方法があるのでしょうか?

  • popenについて質問です!!

    こんにちは!遺伝的アルゴリズムを用いた回路の最適化について研究をしているものですが…プログラムに問題がありまして質問させていただきました。 たぶん、popenの使い方の問題だと思いますが…下のプログラムを見るとこういう部分があります。↓↓ ----------------------------------------------- if(!(p_file=popen(command,"r"))){ printf(" cannot open a pipe!!"); exit(1); } ----------------------------------------------- プログラムを動かすと何世代かは回りますが、ある世代で急にifのループに入ってしまってプログラムが止まってしまうのですが…なぜでしょうか? これってpopenの使い方が間違ってるんでしょかね? でも、約20世代までは何の問題もなく動きます。で、急にifのループに入ってしまって止まるのです。 どなたかお分かりの方がいらっしゃれば是非教えてください。よろしくお願いいたします。 ------------------------------------------- . . . . char command[100],field[81]; for(rua=0; rua<N; rua++){ for(rub=0; rub<N; rub++){ char *bp; FILE *p_file,*net_fp,*fp_outfile; net_fp=fopen("bpf.net","w"); . . . . fclose (net_fp); sprintf(command,"%s",COMMAND); if(!(p_file=popen(command,"r"))){ printf(" cannot open a pipe!!"); exit(1); } if(!(fp_outfile=fopen("bpf.out","r"))){ printf(" cannot open a output file!!"); exit(1); } . . . . pclose(p_file); . . . .

  • Perlでpopen()的なものを使って・・

    今Perlでちょっとしたアプリを作っています。 サーバはunix系でアプリの内容はコマンドの結果値をHTMLで表示させるというものです。 一度Cで作って成功しました。 簡単に書きます。(HTMLの表示部分は簡略します) int main() { char *token; char str[1024]; FILE *fp = popen("ls -la","r"); while(fgets(str,1024,fp)!=NULL){ token = strtok(str,NULL); printf("結果:%s\n",token); } exit(0); } とコマンド(例:ls -la)を実行してファイルハンドルを返してコマンドの結果値を読み取って表示させるというものなのですが、これをPerlに移行したいと考えています。 Perlをさわるのが初めてでしてネットで調べてみても なかなか参考になるものはありません。 Perlの関数にpopen()が存在するのかまたfgets()、strtok()に類似する関数がありましたらアドバイスいただけないでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • reallocについて

    現在、領域を拡張しながら、 ファイルを読み込んで呼び元に返却するPGを作成しています。 reallocがうまくいかないので、試しに小さいのを作って みましたが、これだとreallocの2度目で落ちます。 100文字ずつ呼んでいるので、拡張も100文字ずつ行っています。 メモリ確保に失敗なら、まだ分かるのですが、 ちょっと理由がわかりません。 reallocを複数繰り返していることも問題だと思いますが、 まずは正常に処理を流したいと考えています。 よろしくお願いします。 ~~~~~~ソース~~~~~~~~ //ファイルを読み込んでから領域を確保する #include <stdio.h> #include <string.h> #include <stdlib.h> #define BUFF 100 int main() { FILE *fp; char tmp[BUFF+1]; char *str; int len = 0; fp = fopen( "c:/test.txt" , "rb" ); if(fp ==0){ printf("ファイルがありません\n"); return -1; } //領域を初期化 str = (char *)malloc(1); memset(str,'\0',sizeof(str)); while(feof(fp)==0){ memset(tmp,'\0',sizeof(tmp)); fgets(tmp,BUFF,fp); //領域を再確保 len += BUFF+1; if(NULL == ((char *)realloc(str,len))){ printf("メモリ確保エラー"); } //読み込んだ値を変数に追加 strcat(str,tmp); } printf("文字列\n\n%s\n",str); printf("長さ:%d\n",len); fclose(fp); return 0; }

  • if文で…

    いつもお世話になっております。 ------------------------ typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; douken dou [100]; char buff [18 /* douken */ + 2 /* CrLf(\n\r) */ + 1 /* \0 */]; int i; i = 0; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } memset (dou , '\0' , sizeof dou); memset (buff, '\0' , sizeof buff); 問題はここから----------------- while (fgets(buff,sizeof buff,fp) != NULL){ memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); if (&dou[i].tiku == &dou[i-1].tiku){ printf("%s %s",&dou[i-1].tiku,&dou[i].tiku,&dou[i].ken);} else{ printf("-----------------------"); } ------------------------ 上記のプログラムでは ファイルから読み込んだデータを 構造体に格納して if文で現データと全データを 比較するという処理をしています。(つもり) 構造体に格納するところまでは 出来たのですが if文のところが上手く行きません。 例えば 現データ(tiku)関東地区 前データ(tiku)関東地区 と、同じ場合は 関東地区 東京 と、表示したいのに ----------- と、elseの処理をしてしまいます。 対処方法をご存じでしたら、 ご教授して頂けたら幸いです。

  • popen使用時の実行速度

    お世話になります。1000以上のファイルがあるディレクトリを再帰的に走査するのに、 fp = _popen("dir /s /b *.jpg", "r"); while (fgets(fn, sizeof(fn), fp) != NULL) { //処理内容 } _pclose(fp); のようにしました。ここでint型の変数をインクリメントして100毎に表示させて実行速度を確認すると、明らかに後になるほど速度が低下していました。 タスクマネージャーで確認しましたが、メモリも一定でメモリリークを起こしているわけでも無いようです。 原因は何でしょうか?

  • セグメンテーションエラーの原因がわからず困っています

    以下のプログラムで”セグメンテーションエラーです”の文字が表示され上手いこと動きません。 何がダメなのか、ご助言を頂けないでしょうか。どうぞよろしくお願いします。環境はCentosです。 #include<stdlib.h> #include<string.h> main(){ char s[11]; FILE *fp; fp = popen("netstat -s |grep total","r"); if(fp = NULL){ printf("reading error"); exit(-2); } FILE *fp2; fp2 = fopen("file.txt","r"); fscanf(fp,"%9s",s); int a; printf("%s\n",s); a = atol(s); printf("%ld",a); pclose(fp); fclose(fp2); }

  • popen について

    popen() を使いこなせるようになろうとしているのですが、少し難しくてつまづいています。この関数は基本的に、指定したスクリプトをバックグラウンドで実行させるためのもの、と考えてよろしいでしょうか? マニュアルを読んでわからなかった言葉があります。「パイプ」「片方向ストリーム」 なのですが、検索して、パイプはなんとなく出入力先のポートだということが書いてあったのですが、いまいちピンときません。パイプを経由することで生まれるメリットのようなものはあるのでしょうか? 次に、ファイルポインタなのですが、スクリプトを実行させるのになぜこれが必要になるのでしょうか?おそらくほとんどのスクリプトがファイルの先頭にポインタを置く必要があると思うのですが、例えば'a'などとして、最後に置くとスクリプトが実行されなくなったりしませんでしょうか? 現在の理解度では popen("php -f $script", "r"); exec("php -f $script > /dev/null &"); の違いがわかりません。どちらも$sriptをバックグラウンドで実行してくれますが、マニュアルに記載されているファイルポインタの指定とパイプのオープンがもたらす決定的な違いなどどのようなものになるのでしょうか? また、popen()使用後に、pclose() で閉じないでいるとどのようなことが起こるのでしょうか? たくさんありますが、ひとつでもお分かりになるかたおられましたらどうぞよろしくお願いいたします。

    • 締切済み
    • PHP