• ベストアンサー

親子プロセス間でのデータの受け渡しについて

子プロセスを複数生成して、それぞれの子プロセスからデータを渡すにはどうしたらよいのでしょう? また、子プロセスでは親プロセスの値を参照できるのでしょうか? char str[] = "hoge"; int dec[10]; dec[0] = 0; . . . dec[9] = 0; for(i = 0; i < 10; i++) { if((gid = fork()) == 0) { printf("%s\n", str);/* 危険でないか? */ dec[i] = i;/* 親プロセスで有効になるか */ exit(EXIT_SUCCESS); } else if(gid == -1) { perror("fork"); exit(EXIT_FAILURE); } } また、もしこのコードが不正であればよい方法をご教授お願いします。

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

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

fork()はunix系のOSのシステムコールですから、unix系のOSとして話します。 プロセス毎にメモリ空間は独立しているため、 全く同じデータを使うなら共有メモリを使いますし、 それ以外はソケット、パイプ、メッセージ等によりプロセス間通信を行いデータをやり取りすることになります。 >http://www.ncad.co.jp/~komata/c-kouza10.htm それはプロセス間通信のソケットの話ではありません。 子プロセスがTCP/IPで通信しているだけです。 >fork()が呼び出された時点からプロセスが分かれ、それ以前の変数などの値は受け継いでいるのでしょうか? はい。fork以前の値の参照は問題ありません。 fork()の変数の値が全てコピーされます。 >strcpy(str, "abcd1234"); これはfork以前にバッファオーバーフローのバグですが。 strは5バイトです。 > dec[i] = i;/* 親プロセスで有効になるか */ なりません。親プロセスでは値は変化しません。 このような書き方で使いたい場合は共有メモリを使います。 char *dec;の形で宣言し、decに共有メモリから確保した領域のアドレスを入れて使います。 詳しくはshmat(2), shmctl(2), shmget(2), shmdt(2)あたりを調べてください。 ただし、共有メモリは同期の問題が出ますからご注意を。

negi-bozu
質問者

お礼

ご回答ありがとうございます。 fork()以前の値の参照は問題ない、親からの子の値の参照は無効ということが理解できました。勉強になりました。共有メモリについても勉強したいと思います。

その他の回答 (2)

  • kmb01
  • ベストアンサー率45% (63/138)
回答No.2

上記のstrのような変数はプロセス毎に作成されるはずです。 読み書きは自プロセスのものに対して行われるので危険ではありませんが、親プロセスの変数に書きこむことはできません。 環境で用意されたプロセス間通信の方法を使うことになると思います。

negi-bozu
質問者

補足

ご回答ありがとうございます。 ということは子プロセス内からstrを参照したときに値は"hoge"が取得されるのでしょうか?また、仮にfork処理前にstrcpy(str, "abcd1234");とした場合にも"abcd1234"が取得されるのでしょうか? fork()が呼び出された時点からプロセスが分かれ、それ以前の変数などの値は受け継いでいるのでしょうか?

  • abayama
  • ベストアンサー率48% (38/79)
回答No.1

違うプロセスの間でデータを共有するには、共有メモリを使ってデータを共有するか、ソケットで通信するしかありません。

negi-bozu
質問者

補足

早速のご回答ありがとうございます。共有メモリかソケットで通信するとのことですが、以下のサイトでは http://www.ncad.co.jp/~komata/c-kouza10.htm 親プロセスで生成したソケットを子プロセスでクローズしたり、また親プロセスで生成した他のソケットを使って通信をしているようです。子プロセスで親プロセスからのソケットを参照していますが、このソケットは共有メモリを使用していたり、ソケット通信で参照していませんがどのようになっているのでしょう?

関連するQ&A

  • プロセスの生成

    #include<stdio.h> #include <unistd.h> main(){ int i; printf("\t(%s)プロセスID.....%d\n","元",getpid()); printf("\t(%s)親プロセスID...%d\n","元",getppid()); if((i=fork())==0) { //子プロセスで実行する部分 printf("\t子プロセスでのfork()の値 : %d\n",i); printf("\t(%s)プロセスID.............%d\n","子",getpid()); printf("\t(%s)親プロセスID...........%d\n","子",getppid()); printf("子プロセスを終了します\n"); } else{//親プロセスで実行する部分 printf("\t親プロセスでのfork()の値 : %d\n",i); printf("\t(%s)プロセスID.............%d\n","親",getpid()); printf("\t(%s)親プロセスID...........%d\n","親",getppid()); printf("親プロセスを終了します\n"); } } fork関数の振る舞いについてです。 上記のプログラムをgccでコンパイルして実行した場合出力結果が /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ (元)プロセスID.....375 (元)親プロセスID...246 親プロセスでのfork()の値 : 376 子プロセスでのfork()の値 : 0 (子)プロセスID.............376 (子)親プロセスID...........375 子プロセスを終了します (親)プロセスID.............375 (親)親プロセスID...........246 親プロセスを終了します _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ という感じで出力されました。 fork関数がプロセスの複製を行っていることと、戻り値が0と376の2つであることはわかりました。 また子プロセスには0を親プロセスには376を返すこともわかりました。 感覚的にはif文の真である子プロセス側の記述文と偽である親プロセス側 の記述文が同時に実行されているのではないかと考えましたが 同時に実行されているのに printf("\t子プロセスでのfork()の値 : %d\n",i); printf("\t親プロセスでのfork()の値 : %d\n",i); で表示される値が違うのはなぜでしょうか。 i=fork()によって代入されているのはわかるのですが、 同時に実行されつつ何故2つの違う値をiは出力できるのかがわかりません。 また出力結果が _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ (元)プロセスID.....377 (元)親プロセスID...246 親プロセスでのfork()の値 : 378 (親)プロセスID.............377 (親)親プロセスID...........246 親プロセスを終了します 子プロセスでのfork()の値 : 0 (子)プロセスID.............378 (子)親プロセスID...........1 子プロセスを終了します _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 子プロセスから見たときの親プロセスが1となっているのは何故でしょうか? 本来ならば377ではないでしょうか? わかりにくい説明ですいません。 よろしくお願いします。

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

    ある本を読んでいると、以下のような問いにぶち当たり、プログラムの仕方がよくわからないのです。 自分でもいろいろ調べたのですが、わからないので質問させていただきます。 自分のプロセス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); }

  • fork()のpidとppid

    システムコールのfork()の勉強をしています。 fork()によって作られたプロセスのそれぞれのpidとppidを知りたいのですが頭がこんがらがってしまいました。 「forkシステムコールは親プロセスには作成された子プロセスのプロセスIDが、子プロセスには0が返る」とあったので以下のコードの場合 pid = fork(); if(pid == 0) printf("%s, child process\n", msg); else printf("%s, parent process\n", msg); 子のpidが0のためifが実行され、親はelseが実行される というところまで理解できたのですが このとき親のpidは子のID、子のpidは0なのでしょうか? 教科書の図(添付)を見ると親のpidは0で子、孫になるにつれてpidが大きくなっていてよくわからなくなってしまいました。 例えば以下のようなコードがあった場合、 pid_t pid; // メインプロセスのPIDは42 pid = fork(); // プロセスをPID=11で作成 if (pid == 0) { pid_t pid2 = fork(); // プロセスをPID=25で作成 if (pid2 == 0) { sleep(20); exit(0); } waitpid(pid2,NULL,0); exit(0); } else { pid_t pid3 = fork(); // プロセスをPID=89で作成 if (pid3 == 0) { sleep(10); printf("** ONE **\n"); exit(0); } pid_t pid4 = fork(); // プロセスをPID=123で作成 if (pid4 == 0) { sleep(30); printf("** TWO **\n"); exit(0); } } sleep(20); exit(0); それぞれのプロセスのpidとppidはどうなるのでしょうか? 説明がうまくできないのですが、 分かる方いましたら回答よろしくお願いします。

  • C言語のfork()とpipe()の使用方法についてのサンプルを作成し

    C言語のfork()とpipe()の使用方法についてのサンプルを作成していますが、 期待通りの動作をさせる事ができないため、質問させて頂きます。 現在は、aaa.txtの1行目(てすとだよ。)のみ出力されて2行目が出力されません。 (1)実行方法:a.out aaa.txt (2)期待動作:aaa.txt の内容を出力 <aaa.txt> てすとだよ。 pipeだよ。 <ソース> #include <stdio.h> #include <unistd.h> #include <sys/wait.h> #include <stdlib.h> #include <string.h> #define BUFF_SIZE 1024 /* バッファのサイズ1M */ int main(int argc, char **argv) { int pipefd[2]; int p_id; int ret; /* 関数の戻り値 */ int status; FILE *fp; char buff[BUFF_SIZE]; ret = pipe(pipefd) ; /* パイプ生成失敗 */ if(ret == -1) { perror("main"); exit(EXIT_FAILURE); } /* 子プロセス生成 */ p_id = fork(); /* 子プロ生成失敗 */ if(p_id == -1) { perror("main"); exit(EXIT_FAILURE); } if(p_id == 0) { /* 子プロセス側処理 */ printf("子プロ処理開始!!!\n"); /* 使用しないwrite側はクローズ */ close(pipefd[1]); /* パイプから読込む */ while(read(pipefd[0], &buff, BUFF_SIZE) > 0) { fputs(buff, stdout); } close(pipefd[0]); printf("子プロ処理終了!!!\n"); } else { /* 親プロセス側処理 */ printf("親プロ処理開始!!!\n"); /* 使用しないread側はクローズ */ close(pipefd[0]); printf("親プロ:読込ファイル名[%s]\n",*(argv + 1) ); if( (fp = fopen( *(argv + 1), "r" ) ) != NULL) { while(fgets(buff, BUFF_SIZE, fp) != NULL) { printf("パイプに書込む値:%s\n",&buff[0]); /* パイプに書き込む */ write(pipefd[1], buff, strlen(buff) + 1); } fclose(fp); } else { perror("親プロセス "); } close(pipefd[1]); wait(&status); } return EXIT_SUCCESS; }

  • forkについて

    fork文を使った問題について質問です。 #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { pid_t pid1,pid2; if((pid1 = fork()) == 0) printf("I am a first child with pid = %d,My parent pid is %d.\n",getpid(),getppid()); else if(( pid2 = fork()) == 0) printf("I am a second child with pid = %d,My parent pid is %d.\n",getpid(),getppid()); else printf("I am a parent with pid = %d.\nMy first and second children are %d and %d.\n",getpid(),pid1,pid2); exit(EXIT_SUCCESS); } このようなプログラムが与えられました。 問題は 1.このプログラムを改造して、1つの親プロセスから100の子プロセスを順に生成するプログラムをつくるというものと 2.1つの親から子プロセスを生成し、その子プロセスの孫プロセスを生成するプログラムをつくれというものです。 1はfor文を使えばできそうなのですが、forkの基礎が出来ていないのでどうループを回せばよいか分かりません。 2もfork内でforkを実行すればできそうだと思ったのですがうまく動かず・・・。 どうか正しく動くようなプログラムを教えてください!お願いします。

  • sscanfでフォーマットに合っているかを調べるには。

    今,Cの関数で0-9,A-Zの4文字以内の文字列かどうか を調べたいのですが, int main() { int i; char str[] = "ABCD" /* 調べたい文字列1 */ char str1[]= "ABC@" /* 調べたい文字列1 */ char str2[]= "ABCDE" /* 調べたい文字列1 */ char *p; p = str; /* ここをstr1,str2に変える */ if (strlen(p) != 4) printf("エラーです\n"); for (i = 0; i < 4; i++) { if (!isupper(p[i]) && !isdigit(p[i])) { printf("えらーです\n"); return EXIT_FAILURE; } } printf("すべてOKです\n"); return EXIT_SUCCESS; } というようにすれば,strとstr1とstr2がフォーマットに合うかわかるのですが,これをsscanfの正規表現を使用して実装したいのですが,可能でしょうか。 int main() { int ret; char str[] = "ABCD" /* 調べたい文字列1 */ char str1[]= "ABC@" /* 調べたい文字列1 */ char str2[]= "ABCDE" /* 調べたい文字列1 */ char *p; chat tmp[30]; p = str; ret = sscanf(p, "%4[0-9A-Z]", tmp); if (ret != 1) { printf("エラーです\n"); return EXIT_FAILURE; } printf("すべてOKです\n"); return EXIT_SUCCESS; } といしょうとするならば,str1のときは,@までのABCの文字列がとれて,retには1が帰ってきてしまいます。 なにか4文字以内ということを実装できる正規表現の使い方はあるのでしょうか? ちなみに sscanf(str, "%1[0-9A-Z]%1[0-9A-Z]%1[0-9A-Z]%1[0-9A-Z]", tmp1, tmp2, tmp3, tmp4) という以外でわかる方,よろしくおねがいします。

  • sys/types.hの必要性について

    #include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> int main (int argc,char *argv[]) { struct stat buf[2],*p;     if(argc!=3) { fprintf(stderr,"Usage:newer file1 file2\n"); exit(EXIT_FAILURE); } p=buf; if(stat(argv[1],p)<0) { perror("stat"); exit(EXIT_FAILURE); } p++; if(stat(argv[2],p)<0) { perror("stat"); exit(EXIT_FAILURE); } if(buf[0].st_mtime>buf[1].st_mtime) { printf("%s\n",argv[1]); } else { printf("%s\n",argv[2]); } return EXIT_SUCCESS; } 上記のプログラムでは<sys/types.h>を使っていますが、 どこの部分で必要になるのでしょうか? プログラム貼り付けて非常に見づらくてすいません

  • 子プロセスのデータを親プロセスに渡す方法ってありますか。

    こんにちは。 C言語内でfork()関数を使い親と子を分け、子プロセス間で生成されたデータを親プロセス側に渡して処理したいと考えています。要は、プロセス間でデータのやり取りをpipe()関数かなにかで行いたいと思っています。 子プロセスがデータをテキストファイルでどこかに出力して、それを親プロセスが参照する、というテキストファイルを橋渡しにする原始的な方法があるにはあるのですがこれは最終手段にしたいと考えています。他に良いやり方があればご教授いただけないでしょうか。 以下はサンプルコードです。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<signal.h> #include<sys/types.h> int main(){ FILE *fp,*fp2; int fd[2],a,i = 0; pid_t pid; pipe(fd); char buff[1024]; pid = fork(); sigignore(SIGCLD); //ちゃんと子が死ぬようにする if(pid == 0){ close(STDOUT_FILENO); //画面に出力されないようにする dup2(fd[1],STDOUT_FILENO); close(fd[0]); fp = popen("tcpdump","tcpdump","tcp[13] & 255 == 2",NULL); } else{ sleep(1); //一秒だけ子プロセスを起動 kill(pid,SIGTERM); wait(); //完全に子プロセスを殺す fp2 = popen("wc -l fpのファイルデータ","r"); for(i=0;i<3;i++){ a = fgetc(fp2); putc(a,stdout); }printf("\n"); return 0; } } プログラムの内容は、 tcpdumpで処理(子プロセス)した内容を、wc -l で「行数」のみ取得する(親プロセス)というものです。あくまで目標ですが・・。^^; お手数でしょうが、どうぞよろしくお願いします。

  • forkで作れる子プロセス数が限られている

    for($i=0;$i<1000;$i++) { if($p=fork) { next; } elsif(defined($p)) { sleep 10000; exit; } else { print("$i\n"); <STDIN>; } } 数十個で子プロセスが生成されなくなります メモリは十分あまってます デスクトップヒープ領域が足りなくなったわけじゃなさそうです どうすればメモリが足りる限り子プロセスを生成できるでしょうか? windows xp avtive perl 5.8.7です。

    • ベストアンサー
    • Perl
  • ls | sort を実行するプログラム

    以下のプログラムはls | sortを実行するプログラムなのですが、出力が2回ずつ出てしまい困っております。以下に実行結果も載せましたので参照ください。 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> main(int argc,char **argv){ int a[2],b[2]; int cint,status; char n; pid_t pid1,pid2; if(pipe(a)==-1){ perror("pipe"); exit(EXIT_FAILURE); } if(pipe(b)==-1){ perror("pipe"); exit(EXIT_FAILURE); } if((pid1 = fork())==-1){ perror("fork"); exit(EXIT_FAILURE); } if((pid2 = fork())==-1){ perror("fork"); exit(EXIT_FAILURE); } //子1 else if(pid1==0){ close(a[0]); close(b[0]); close(b[1]); dup2(a[1],1); close(a[1]); execlp(argv[1],argv[1],(char *)0); } //子2 else if(pid2==0){ close(a[1]); close(b[0]); dup2(a[0],0); dup2(b[1],1); close(a[0]); close(b[1]); execlp(argv[2],argv[2],(char *)0); } //親 else { close(a[0]); close(a[1]); close(b[1]); wait(&status); while((read(b[0],&n,1))==1){ putchar(n); } close(a[0]); } exit(EXIT_SUCCESS); } /*実行結果 $ ./pipesort ls sort 2^31-1.c~ 2^31-1.c~ a*b.c~ a*b.c~ a-z.c a-z.c a-z.c~ a-z.c~ a-z1.c a-z1.c a-z1.c~ a-z1.c~ a.c a.c a.c~ a.c~ a.out a.out a.sp~ a.sp~ a10 a10 */ というように同じファイル名が二度ずつ出力されるのです。これを出力は一度ずつにしたいのですがどのようにすればよいですか?