プロセスに関するプログラムの動きとプロセス生成数の判定方法

このQ&Aのポイント
  • UNIX系OSでのプロセスの動きを確認するプログラムの特徴として、プロセスの番号が順番どおりに並ばないことがあることについて説明します。
  • また、コマンドライン引数で与えられた整数の数によってプロセスを生成するプログラムの実装方法と、プロセスの最大生成数を判定する点について詳しく説明します。
  • プロセスの親子関係やプロセスIDなど、プロセスに関する基礎知識も合わせて紹介します。
回答を見る
  • ベストアンサー

プロセスに関するプログラム

UNIX系OSでのプロセスの動きを確認するプログラムを勉強しています。 コマンドライン引数で与えられた整数の数だけプロセスを作成するというもので、わからないことがありますので教えて頂けると幸いです。 質問の要点は 1.プロセスの番号がなぜ順番どおりに並ばないことがあるのか 2.どのような点からこのプログラムのプロセスの最大生成数を判定す  るのか という2点です。 parentIDが1のときはinitが親を引き継いでいることはわかっています。 どなたかご教授おねがいします。 下記にソースコードを載せておきます。 *** process.c *** #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { int np; int i; pid_t child_id; if(argc == 2) { fprintf(stderr, "<number of processes>\n"); exit(1); } np = atoi(argv[1]); for(i = 0; i < np; i++) if(child_id = fork()) break; printf("%d: process ID=%ld parent ID =%ld child ID=%ld\n", i , (long)getpid(), (long)getppid(), (long)child_id); return 0; }

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

  • ベストアンサー
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.2

>結果として私が提示したプログラムではプロセスの最大数を判定するのは不可能なのでしょうか? まず、csh系ならlimit、sh系ならulimit -aの結果を確認してください。そこにmaxprocとかあると思いますが、それが現ユーザの実行可能プロセス数となります。OSによってはもっと細かい制御も可能かも知れません。詳しくはman 2 getrlimit, man 2 setrlimitなど。 その上で、ある程度までlimitを下げれば、まあ可能かも知れませんが、いずれにしてもprintfしただけですぐ終了しては意味が薄いですから、sleep()でもはさめば効果はあるでしょう。 >あと実行結果で親IDが1にならないものはどういう状況が起こっているのかということも疑問としてあがってきました。 親が責任放棄して終了した場合、initのpid=1に設定されるのはご存知のとおりです。逆に親がまだ存命ならそのpidが子のppidです。元のプログラムだと親がbreakでループからぬけてすぐ終了してますので、ほとんどppidが1になっていたでしょうが、修正版は子の終了まで親がwait()してます。 もちろん目的があって親が先に終了してしまうことも良くあります。daemonなどがそうですが、この場合は動作状況の確認の意味で親は待ってます。 詳しくは、man 2 fork, man 2 waitなど。

tadayannh
質問者

お礼

なるほど、大変参考になりました。 教えていただいたコマンドを試してみた後、sleepを挟んでどのような結果になるのかを見てみたいと思います。 最後まで丁寧に教えていただいて助かりました。 本当にありがとうございました。

その他の回答 (1)

  • trapezium
  • ベストアンサー率62% (276/442)
回答No.1

質問1は簡単です。他のdaemonなどによってforkされたプロセスもあるし、すでに実行中のpidは飛ばされるだろうから。 それよりこのプログラムの動作として、親から子へ、子から孫へ、またその孫へとなっていて、親は子の終了を待たずに終了してます。ですからforkした方はforkしたそばから終了してる。 もしプロセステーブルをいっぱいにしたいのなら、forkしたあと子は動作を継続させ、親はwait()しないとならないでしょう。イメージとしては、 ----- for(i = 0; i < np; i++) if ((child_id = fork()) == -1) { perror("fork"); break; } else if (0 == child_id) { printf("child: %d: process ID=%ld parent ID =%ld\n", i, (long)getpid(), (long)getppid()); sleep(10); exit(0); } else { /* parent */ printf("%d: process ID=%ld child ID=%ld\n", i , (long)getpid(), (long)child_id); } while (i-- > 0) { int status; pid_t pid = wait(&status); printf("%d\n", pid); } ---- これで十分大きい値を与えればforkも失敗するように出来るでしょう。そういえば >if(argc == 2) { は if(argc < 2) { ね。 あとはwait()をシグナルハンドらで処理するとか、逆にwaitを親のループ内で行えば、ひとつずつ子をforkして終了を待つ動作になります。

tadayannh
質問者

お礼

質問の回答と問題点の指摘をしていただいてありがとうございます。 結果として私が提示したプログラムではプロセスの最大数を判定するのは不可能なのでしょうか? あと実行結果で親IDが1にならないものはどういう状況が起こっているのかということも疑問としてあがってきました。 不躾ではありますが、もしよろしければ参考意見でもいいので宜しくお願いします。

関連するQ&A

  • ソースプログラムのエラー

    自分で四則演算のプログラムを組んだのですが エラーが出てお手上げ状態です。 どこが間違っているのかどなたか教えていただけませんか?? ちなみに足し算の場合はいくつ足しても計算できるという プログラムです☆ #include<stdio.h> int main(int argc, char *argv[]){ int i,a=0,b=0,x=0; int m=0; if(argv[1]!="+"||argv[1]!="-"||argv[1]!="*"||argv[1]!="/"||){ printf("指定された文字ではありませんよ\n"); return -1; } a = atoi(argv[2]); b = atoi(argv[3]); if(argv[1]=="-"){ m=a-b; } if(argv[1]=="*"){ m=a*b; } if(argv[1]=="/"){ m=a/b; } if(argv[1]=="+"){ for(i=2;i<argc;i++){ x=atoi(argv[i]); m+=x; } printf("%d\n",m); return 0; }

  • C言語のシェルプログラミングの課題が分かりません。

    C言語のシェルプログラミングを作れという課題で、以下のように作ったんですが、実行して何度かコマンドを入力した後、exitによって一発で終わらせることができません。どのように書き換えればいいか教えて下さい。 また、他にも書き換えた方がよいと思えるところがあったら是非教えて下さいm(_ _)m #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h> #include <sys/types.h> #include MAX_ARGS 10 #include MAX_LEN 100 extern char **environ; void child(int argc, char *argv[MAX_ARGS]); int main(void){ int argc, n = 0; int status; char input[MAX_LEN], *argv[MAX_ARGS], *cp; const char *delim = "\t\n"; while (1){ ++n; printf("$ "); fflush(stdout); if(fgets(input, sizeof(input), stdin) == NULL){ break; } cp = input; for(argc = 0; argc < MAX_ARGS; argc++){ if((argv[argc] = strtok(cp, delim)) == NULL) break; cp = NULL; } if(strcmp(argv[0], "exit") == 0){ exit(0); } pid_t pid = fork(); if(pid == -1){ perror("fork"); exit(1); }else if(pid == 0){ child(argc, argv); }else{ wait(&status); } } return 0; } void child(int argc, char *argv[MAX_ARGS]{ execvp(argv[0], argv); }

  • ポインタのポインタ

    #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv){ int i; if(argc != 2) { fprintf(stderr, "Usage: %s vector\n\tEx: %s 11110000\n", argv[0], argv[0]); return 1; } for(i=0;i<8;i++){ if(**argv == '0'){ printf("%d\n",i); } else{ printf("A%d\n",i); } argv++; } return 0; } コンパイルして./a.exe 10010011などと入力しても A0 A1 Segmentation Faultとなります。 どうすれば、 A1 0 ・・・省略 for文で回した8回分、出力が可能になるのか教えてください。 初歩的な質問ですいません。

  • 子プロセスと親プロセス

    ある本を読んでいると、以下のような問いにぶち当たり、プログラムの仕方がよくわからないのです。 自分でもいろいろ調べたのですが、わからないので質問させていただきます。 自分のプロセスIDと親のプロセスIDのプロセスIDを表示するコマンドshowpidを作り、showpidを子プロセスとして10回実行するプログラムを作りなさい。ただし、execを用いてshowpidを10回実行すること。 というものなのですが、自分のプロセスIDと親のプロセスIDの表示方法はわかったのですが、それをコマンドとして作り、子プロセスとして10回実行する方法がわからなくて困っております。。。 言語はc言語を使ってもらいたいです。以下に自分のプロセスIDと親のプロセスIDを表示するプログラムを付けときます。 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(){ pid_t pid; int status; if((pid=fork())==0) printf("I am a child with pid=%d. My parent pid is %d.\n",getpid(),getppid()); else{ wait(&status); exit(EXIT_SUCCESS); }

  • プログラミング(argcとargv)

    入力された数の合計とその計算式を表示するプログラムをつくっています。惜しい(?)ところまでいったのですがその先がなかなか進みません。以下のプログラムのどこを修正したらよいでしょうか?教えてください。 #include <stdio.h> #include <stdlib.h> #define nMAX 10 int main(int argc, char **argv){ int sum = 0; if(argc < 2){ printf("Too few option!\n"); return 1; } int i, n; for(i = 1; i < argc; i++){ n = atoi(argv[i]); sum = sum + n; } printf("%d\n", sum); }

  • 二行目の*の意味を教えてください。

    #include <stdio.h> int main(int argc, char *argv[]) { int i; for ( i = 0; i < argc; i++ ){ printf("argv[%d]=%s\n", i, argv[i]); } return argc; }  以上プログラムで、二行目の*の意味を教えてくさい。  6行目のargvには*が付いていません!?  よろしくお願いします。

  • MPIプログラムの実行でエラーが出てしまいます

    エラストテネスのふるいのプログラムなんですが、どうもエラーが出て実行できません。 他の部分などを直して、なんとかエラーをひとつにしたんですが、どうも#include "MyMPI.h"に関連する部分でミスがあってできないようなのです。 エラーの内容は文字化けしているので読めません。 どなたかお教えしてもらえないでしょうか。 #include<mpi.h> #include<math.h> #include<stdio.h> #include "MyMPI.h" #define MIN(a,b) ((a)<(b)?(a):(b)) int main(int argc, char *argv[]) { int count; double elapsed_time; int first; int global_count; int high_value; int i; int id; int index; int low_value; char *marked; int n; int p; int proc0_size; int prime; int size; MPI_Init(&argc, &argv); MPI_Barrier(MPI_COMM_WORLD); elapsed_time = -MPI_Wtime(); MPI_Comm_rank (MPI_COMM_WORLD,&id); MPI_Comm_size (MPI_COMM_WORLD,&p); if (argc != 2) { if (!id) printf("Command line: %s <m>\n", argv[0]); MPI_Finalize(); exit(1); } n = atoi(argv[1]); low_value = 2 + BLOCK_LOW(id,p,n-1); high_value = 2 + BLOCK_HIGH(id,p,n-1); size = BLOCK_SIZE(id,p,n-1); proc0_size = (n-1)/p; if ((2 + proc0_size) < (int) sqrt((double) n)) { if (!id) printf("Too many processes\n"); MPI_Finalize(); exit (1); } marked = (char *) malloc (size); if (marked == NULL) { printf("Cannot allocate enough memory\n"); MPI_Finalize(); exit(1); } for (i = 0; i < size; i++) marked[i] = 0; if (!id) index = 0; prime = 2; do { if (prime * prime > low_value) first = prime * prime - low_value; else { if (!(low_value % prime)) first = 0; else first = prime - (low_value % prime); } for (i = first; i < size; i += prime) marked[i] = 1; if (!id) { while (marked[++index]); prime = index + 2; } MPI_Bcast (&prime, 1, MPI_INT, 0, MPI_COMM_WORLD); } while (prime * prime <= n); count = 0; for (i = 0; i < size; i++) if (!marked[i]) count++; MPI_Reduce (&count, &global_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); elapsed_time += MPI_Wtime(); if (!id) { printf("%d primes are less than or equal to %d\n",global_count, n); printf("Total elapsed time: %10.6f\n", elapsed_time); } MPI_Finalize(); return 0; }

  • プログラムの説明

    C++の初心者です。 ↓のプログラムの動作はさっぱりわかりませんが、それについての説明は具体的に教えていただきたいです。(できれば、詳しく) #include <iostream> #include <string> int getNinzu(int ARGC, char *ARGV[]) throw (char const *){ if(ARGC!=2){ throw "Needs only one argument."; } int ninzu=std::atoi(ARGV[1]); if(ninzu<=0){ throw "Value is too small."; } return ninzu; } #include <cstdlib> #include <ctime> int randfive(){ static bool firsttime=true; if(firsttime){ firsttime=false; std::srand(std::time(NULL)); } return static_cast<int>(static_cast<double>(std::rand())/RAND_MAX*(5+1)); } #include <iomanip> int main(int ARGC, char* ARGV[]){ std::string cmdname=ARGV[0]; int ninzu; try{ ninzu=getNinzu(ARGC,ARGV); std::cout << std::setfill('0'); for (int i = 1; i <= ninzu; ++i) { int score = 0; for (int k = 0; k < 20; ++k) score += randfive(); std::cout << "C" << std::setw(5) << i << " " << score << '\n'; } }catch(char const *str){ std::cerr << str << std::endl << "Usage: " << cmdname << " ninzu" << std::endl; return 1; } }

  • 構造体(超初心者です)

    学校の課題で4つの情報を引数とし、a.out 人数の数(a.out 5)の後に手入力でその5人の 情報を入力するコードを書けと言うものが出たのですが、色んな人の教えでここまで書いたのですが まだ良く分かりません、ifの中身とfor文の中身を教えてください。 後間違っている部分を直して頂けると嬉しいです!!! #include <stdio.h> #include <string.h> #include<ctype.h> #include<stdlib.h> struct student { intid; char login[16]; char first[16]; char family[16]; }; intmain(intargc, char *argv[]) { structstudent st, *sp; if (argc < 6) { / ??? / } int i, n = atoi(argv[1]) * 4; n = ((argc-2) / 4 < n) ? (argc-2) / 4 : n; for (i = 1; i < (n * 4) + 1; i+=4) { /*(各文の argv[1] を argv[i+1] のように直す) */ } sp=&st; printf("id=%d¥n", sp‐>id); printf("loginname=%s¥n", sp‐>login); printf("Name=%s%s¥n", sp‐>first, sp‐>family); }

  • 全くわかりません。

    C言語の課題が全くわかりません。 (1)~(5)には何が入りますか? 丸投げですいません。後でじっくり考えます。 お願いします。 コマンド行引数に整数と符号(+、ー)を指定し、 その和を表示するプログラム。 例%calc -5+10+100-10=95と表示するプログラム #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]) { int sum=0,i=1; if(argc(1)1) put("komanasi"); else if(argv[i],(2)=='+'){ i++; sum += atoi(argv[i(3)]); }else if (argv[i],(2)=='-'){ i++; sum-=atoi(argv[i(3)]); }else sum+=atoi(argv[i(3)]); while((4)<(5)){ if(argv[i],(2)=='+'){ i++; sum+=atoi(argv[i(3)]); }else{ i++; sum-=atoi(argv[i(3)]); } } printf("%d\n",sum); return(0); }

専門家に質問してみよう