• 締切済み

OSのコマンドを呼び出すとき、CPUを最大限に使いたい

OS(ディストリビューション)はUbuntu、言語はC++を用いています。 以下のプログラム: int main(void) { unsigned long int cnt_max=ULONG_MAX; for(unsigned long int i=2;i<=cnt_max;i++){ string str =":"; char c[1024]; strcpy( c, str.c_str() ); FILE *fp = popen(c, "r");・・・※ pclose(fp);・・・※ } } では、確かに実行したいこと(ここでは何もしませんが)が行われます。 ところが、topコマンドで見るとCPUを数%しか用いていません。 ※の部分を消すと、100%使いますので、 どうやらOSのコマンド(ここでは「:」)を実行するときには100%使ってくれないようです。 では、100%使ってくれるようにするにはどうしたらよいでしょうか?

noname#108554
noname#108554

みんなの回答

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.5

setpriorityとgetpriorityを使用すると、プログラムの優先順位を変更することが出来ます。従って、そのプログラムで、setpriorityを呼び出し、そのプログラムの優先順位を上げることが出来ます。但し、優先順をあげる事が出来るのは、スーパーユーザのみですので、スーパーユーザになって、そのプログラムを実行する必要があります。詳しくは、 setpriorityについて調べて下さい。man setpriorityで参照可能です。

noname#108554
質問者

お礼

ありがとうございます。 priorityはもともと最優先になっています。 念のため、プログラム内でsetpriorityも記述してみましたが、 状況は変わりませんでした。

  • 6yemon
  • ベストアンサー率69% (25/36)
回答No.4

":"コマンドって何?という事はさておき、 popen()関数は子プロセスを起動します。ということは当たり前のことですが、関数内部でfork()システムコールを呼びます。fork()はカーネルの処理の中でも、比較的重い(時間のかかる)処理だと思います。さらに、起動された子プロセスがexitするまでpclose()関数はリターンしません(ブロックされる、と言います)。つまり、子プロセスにCPUが与えられないと全体の処理が進まないという事を意味します。 おそらくpopen()で子プロセスを起動することが要件としてあるのだと思いますが、ここでご理解いただきたいのは、子プロセスが速く処理を終了する事と、このプロセスが100%CPUを使う事は、決して両立しない、という事です。 文字列操作などは自分のメモリ上だけで処理できるのでCPUを100%使えますが、入出力処理があったり、マルチタスクやネットワークが関係する処理は、相手となるプロセスや周囲のプロセスの進行状況によって、自分の処理の進み具合が変わってしまいます。ですから、CPUを100%使えるほうが少ないと思います。 むしろ、自分が100%CPUを使おうとすれば、周りのプロセスが動けなくなり、かえって全体の処理が進まない、という結果になりかねません。物事がスムーズに進むためには譲り合いの精神が大切なんですね(笑)。 さて、このプログラムの処理が速く進むためには、子プロセスの実行が速やかに終了することが一つの条件のように思われます。そこで試しに、このプロセスのnice値(プロセスの優先度)を上げて起動してみたらいかがでしょうか。 このプロセスのnice値は子プロセスに引き継がれますので、子プロセスがいざ実行しようという時、有利になる(早くCPUが回ってくる)可能性があります。 ただし念のため繰り返しますが、何でもかんでもnice値を上げればよい、という「強欲」な姿勢ではいけません。この点、ご注意を。

noname#108554
質問者

お礼

ありがとうございます。 priorityはもともと最優先になっています。 念のため、プログラム内でsetpriorityも記述してみましたが、 状況は変わりませんでした。

noname#108554
質問者

補足

:コマンドは「何もしない」コマンドです。 http://flex.ee.uec.ac.jp/texi/sh/node49.html お礼等は後ほど書きますので、よろしくお願いします。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.3

その数%というのは、popen,pclose込みの使用率なのでしょうか? どうも、osのシステムコールを除いた分の使用率なんじゃないかと思うのですが、どうなんでしょう。

noname#108554
質問者

お礼

ありがとうございます。 ためしにforループ中で cout << i <<endl; で出力させてみましたが、 やはり※があるのとないのとでは全然速さが違います。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

>100%使ってくれないとプログラムが遅くて全然進まないからです。 CPUの使用率を上げるよりも、そのプログラムのアルゴリズムを見直す、 といった方が、他のタスクを実行している人たちに迷惑がかからないと思います。 マルチタスキングOSで、特定のタスクがCPUをフルに使ってしまうと どうなるかはご存じですね?

noname#108554
質問者

お礼

私が用いようとしているサーバはほぼ私しか用いず、 さらに旧式なのでさほど問題とはなりません。 絶対に他の人がログインしないとは言い切れませんが、 私ほど重いタスクはしません。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

100%「も」CPUを使いたい理由は何ですか? そのループの中で無限ループを構成すれば、 ほぼ100%に近いCPU使用率を記録できるかもしれません。

noname#108554
質問者

お礼

ご回答ありがとうございます。 >100%「も」CPUを使いたい理由は何ですか? 100%使ってくれないとプログラムが遅くて全然進まないからです。 ちなみに、質問文のプログラムはサンプルプログラムで、 別に:コマンドを早く終了させたいわけではありません。 >そのループの中で無限ループを構成すれば、 >ほぼ100%に近いCPU使用率を記録できるかもしれません。 それはそうかもしれません。 ですが、ここではそうではなくて、 OSのコマンド実行時のことを考えております。 つまり、OSのコマンドをなるべく早く終了させたいということです。 以上、よろしくお願いいたします。

関連するQ&A

  • _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・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 が未解決です。 色々と試してみたのですが解決に至りませんでしたのでよろしければ、 教えて頂けませんでしょうか?

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

  • 明解C言語 入門編 P219 について

    以下のプログラムの理解について、質問です。 入力した文字列に、0 ~ 9 の数字がそれぞれ何度含まれていたかをカウントするプログラムです。 (明解C言語 入門編 P219) ========== プログラム ========== #include <stdio.h> void str_dcount(const char str[], int cnt[]) { unsigned i = 0; while(str[i]) { // str に '\0' が現れるまで繰り返し if(str[i] >= '0' && str[i] <= '9') cnt[str[i] - '0']++; // !!!! ココです !!!! i++; } } int main(void) { int i; int dcnt[10] = {0}; char str[100]; printf("文字列を入力してください : " ); scanf("%s", str); // 文字列を str へ str_dcount(str, dcnt); // 引数  str = 入力した文字列, dcnt = すべて '0' puts("数字文字の出現回数 "); for(i = 0; i < 10; i++) printf("'%d' : %d\n", i, dcnt[i]); return 0; } ========= 実行結果 ========= 文字列を入力してください : 3.14159 数字文字の出現回数 '0' : 0 '1' : 2 '2' : 0 '3' : 1 '4' : 1 '5' : 1 '6' : 0 '7' : 0 '8' : 0 '9' : 1 ========== 質問内容 ========== 関数 str_dcount 内の 『 cnt[str[i] - '0']++; 』 がどのような処理を行っているのか、理解ができません。 以下のように考えたのですが、それでは上手く動かないとの結論に至りました。 たとえば、i = 0 で、str[100] = 3.14159 であるとき、 /* ループ1回目 */ cnt[0] = str[0] - 0; /* 3 - 0 で cnt[0] には 3 が入る。 */ cnt[0++]; /* ループ2回目 */ cnt[1] = str[1] - 1; /* "." - 1 となる。 数字ではないので減算できずエラーになるのでは? */ cnt[1++]; /* ループ3回目 */ cnt[2] = str[2] - 2; /* 1 - 2 なので、なぜか負の数になってしまう。。 */ cnt[2++]; 配列の添え字が、配列になっている cnt[str[i]] までは理解できますが、 以下の2点が解っていないために理解ができていないようです。 1) cnt[str[i] - '0']++ ; の - '0' が何を行っているのか 配列には数字が入っており、そこから文字 '0' を減算しているのでしょうか? 数字から文字を減算できるのでしょうか? 2)  ++  はどの値を増加させているのでしょうか? 宜しくお願いします。

  • 加算、減算、乗算、除算について

    // 加算、減算、乗算、除算について // 記号と数値にそれぞれ別の配列に分けました。 // そこから、どうすれば計算ができるのか // 悩んでいます。よろしくお願いします。 #include<iostream> using namespace std; char **tokei(char *str1,char *str2,int *count,char *kigouX); int main() { int count; int *num; char **www; char kigo[12]; char str1[30],str2[]="+-*/"; strcpy(str1,"123+45-6*789/"); www=tokei(str1,str2,&count,kigo); num=new int[count]; for(int n=0;n<count;n++) { num[n]=atoi(www[n]); } // 数値に変換num[]、記号を順番に抽出kigo[] -->OK // 記号に沿って、数値を演算すればよい。 // ここがやり方(理屈)がわからない。 getchar();{}return 0; } char **tokei(char *str1,char *str2,int *count,char *kigouX) { int cnt=0; int m=0; for(int a=0;*(str1+a)!='\0';a++){} for(int b=0;*(str2+b)!='\0';b++){} for(int i=0;i<a;i++) { for(int j=0;j<b;j++) { if(*(str1+i)==*(str2+j)) { *(kigouX+m)=*(str1+i);m++; *(str1+i)='\0'; cnt++; } } } *(kigouX+m)='\0'; char **c; c=new char*[cnt]; *count=cnt; for(int m=0;m<cnt;m++) { c[m]=str1; while(*str1!='\0'){str1++;}str1++; } return c; }

  • 配列で最大・最小値を求める

    import java.io.*; class Prog10_2 { public static void main(String args[])throws IOException { System.out.println("10個の整数を入力してください。"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int num[] = new int[10]; for(int i=0; i<num.length; i++){ String str = br.readLine(); int tmp = Integer.parseInt(str); num[i] = tmp; } int max = 0; int min = 0; for(int i=0; i<num.length; i++){ if(max < num[i]){ max = num[i]; } if(min > num[i]){ min = num[i]; } } System.out.println("最大値は"+max+"で、最小値は"+min+"です。"); } }   というコマンドを実行すると、最大値はちゃんと表示されるのですが、 最小値はいつも"0"しか表示されません。どこを修正すればいいのでしょうか? どなたか分かる方いらっしゃいましたら、よろしくお願いします。

    • ベストアンサー
    • Java
  • 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
  • C言語のファイル操作についての質問です

    #include <stdio.h> #include<process.h> int main(void) { FILE *fp; int a[200], i, j, cnt, max, max_i; fp = fopen("data.txt", "r"); if (fp == NULL) { printf("file cannot open.\n"); exit(1); } for(i = 0; i < 200 && fscanf(fp, "%d", &a[i]) == 1; ++ i) ; fclose(fp); for(max = max_i = j = 0; j < i; ++ j){ int k; for(cnt = 0, k = j + 1; k < i; ++ k) cnt += (a[j] == a[k]); if(cnt > max) max = cnt; max_i = j; } printf("%d\n", a[max_i]); return 0; } これは「data.txt」というファイルから最頻値を探し出し、その値を表示するプログラムです。 しかし、このプログラムだと最頻値が1つしか表示できないので、 最頻値が複数ある場合でも、すべての最頻値の値を表示させるようなプログラムに書き換えてほしいです。 よろしくお願いします。 例)data.txt 30000 100 150 30000 30000 100 4320 100 出力↓ 30000 100

  • コマンドプロンプトからのEOFの入力方法について

    #include <stdio.h> main(){ int cnt[10]; int c; int i; for(i=0; i<10; i++){ cnt[i] = 0; } while((c=getchar())!=EOF){ if(c>='0' && c<='9'){ cnt[c-'0']++; } } for(i=0; i<10; i++){ printf("%d : %d", i, cnt[i]); } } という、キーボードから入力した数値の個数を 表示するプログラムを、VisualC++で、Win32consoleアプリケーションで作ったのですが、 コマンドプロンプトから何個かの数値を入力したあと、Enterキーを押しても 何の反応もありません。 キーボードから「EOF」を入力するにはどうすればよいのでしょうか。 または、どういう状態をEOFと言うのでしょうか。

  • バッファオーバーランの危険性検出について

    下に示すmsg_file.txtの内容を読み込んで表示するプログラムを使ってバッファオーバーランの危険性を検出するプログラムを作りたいのですが、どのように書き換えたら良いでしょうか。 プログラムソース 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define FILEPATH "msg_file.txt" 6 7 int main(); 8 void vuln(const char* line); 9 void stack_dump(void* ptr, int counts); 10 void hello(); 11 12 int main() 13 { 14 char linebuf[1024]; 15 FILE *fp; 16 long mark1 = 0x11111111; 17 memset(linebuf, 0, sizeof(linebuf)); 18 19 fp = fopen(FILEPATH, "r"); 20 fgets(linebuf, sizeof(linebuf)-1, fp); 21 fclose(fp); 22 23 vuln(linebuf); 24 25 printf("------------- end of main() -------------\n"); 26 } 27 28 void vuln(const char* line) 29 { 30 char msg[20]; 31 long mark2 = 0x22222222; 32 memset(msg, 0, sizeof(msg)); 33 34 strcpy(msg, line); 35 36 stack_dump(&mark2, 13); 37 38 printf("INPUT[%s]\n", msg); 39 } 40 41 void stack_dump(void* ptr, int counts) 42 { 43 int i; 44 unsigned long *ulong_ptr = (unsigned long *)ptr; 45 unsigned char uchar_buf[4]; 46 47 printf("-----------------------------------------\n"); 48 printf(" address | long var | +0 +1 +2 +3 | 0123\n"); 49 printf("-----------------------------------------\n"); 50 for(i=0; i<counts; i++) { 51 printf(" %08x| %08x", &ulong_ptr[i], ulong_ptr[i]); 52 memcpy(uchar_buf, &ulong_ptr[i], sizeof(uchar_buf)); 53 printf(" | %02x %02x %02x %02x", 54 uchar_buf[0], uchar_buf[1], uchar_buf[2], uchar_buf[3]); 55 if(uchar_buf[0]<32 || uchar_buf[0]>126) uchar_buf[0] = '.'; 56 if(uchar_buf[1]<32 || uchar_buf[1]>126) uchar_buf[1] = '.'; 57 if(uchar_buf[2]<32 || uchar_buf[2]>126) uchar_buf[2] = '.'; 58 if(uchar_buf[3]<32 || uchar_buf[3]>126) uchar_buf[3] = '.'; 59 printf(" | %c%c%c%c\n", 60 uchar_buf[0], uchar_buf[1], uchar_buf[2], uchar_buf[3]); 61 } 62 printf("-----------------------------------------\n"); 63 } 64 65 void hello() 66 { 67 printf("+----------+\n"); 68 printf("| HELLO! |\n"); 69 printf("+----------+\n"); 70 exit(0); 71 }

専門家に質問してみよう