Mimic

大学編入や、英語学習、プログラミングなど様々な記事を取り扱うブログ。お金を稼ぎたい

親/子プロセスでパイプを使ってプロセス間通信をする

f:id:michinoins:20180512101331j:plain

 

記事のカテゴリに「プログラム」を増やそうと思います。

大学の講義で習った事をメインに自分が後で見直すためというのも含めて.

 

今回紹介するプログラムの動作は

 

引数に数字をもらうとその長さの分だけ

子プロセスは01234...

親プロセスはABCD....

 を表示します。

 

これを相互にやってほしいので

出力結果としては

0

A

1

B

2

C

 

 

 

と親・子プロセスが相互に動作するプログラムとなっています。

 

プログラムを載せます。

 

 

 

 

 

以下に説明を載せるのですが、スクロールして戻るのは面倒なので

別ウィンドウに同じページを開いてプログラムを見つつこちらの説明を読んでいただければと思います。

親プロセスと子プロセス間でパイプを使ってプロセス間通信するプログラム - ちのログ

 

 

16,17行目

c_length=atoi(argv[1])/2;

p_length=atoi(argv[1])/2;

 

 で入力した数字をint型のlengthに入れていますが、

 

初めはc_length=argv[1]/2

とやっていて全然コンパイルが通らず苦労しました。

 

文字列をint型に変えるatoiの存在をすっかり忘れていました。

使い方はこちらがとても分かりやすいです。↓

 

【C言語入門】atoiの使い方(文字列から数値への変換) | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト

 

 

22,27行目でパイプを2つ作っています。

この時点ではまだ1つのプロセスに2つのパイプ、つまり

4箇所パイプの出入り口があるだけです。

 

31行目でfork()をして親プロセス、子プロセスができて

それぞれにパイプが4本ずつ繋がっている状態になります

親、子それぞれに

 

・ppパイプ入口

・ppパイプ出口

・qqパイプ入口

・qqパイプ出口

 

がつながっている状態になります。

 

そして45,46行目,do_child内で

ppの入口,qqの出口をcloseします。

 

こうすることで子プロセスはppは出口のみ、qqは入口のみから

データを得ることが出来るようになります。

 

同様に70,71行目のdo_parent内でもcloseしています。

 

ここからが本題ですね。

 

31行目forkによってできた2つのプロセスは平行してプログラムを読んでいきます。

 

そうして子プロセスが52行目のreadまでたどり着いたとき

pp[0]から文字を読み出したいのに、親プロセスがwriteまでたどり着いていない場合、待機状態になります。

 

親プロセスがpp[1]にwriteをすると、子プロセスはそれを読みだして

また進んでいきます。

次は親プロセスがqq[0]をreadしようとして、子プロセスがqq[1]をwriteするまで待ちます。

 

while(1)でif(length--==0)でbreakとしているので

入力した文字数の分だけ期待している文字を出力してくれます。(偶数なら)

 

 

このままでは、ひとたび奇数が入力されるとそれより1少ない数しか出力されません。

なぜなら初めの

c_length=atoi(argv[1])/2;

p_length=atoi(argv[1])/2;

 

が偶数しか求めれない仕様になっているからです。

「合計で」6文字なら、親プロセス3,子プロセス3であればいいのですが

5文字だと子プロセスが3,親プロセスが2である必要があります。

(今回は子プロセスが先に来る前提でプログラムを書いています)

 

 

そこで付け加えたのが18行目、81行目です。

引数が2で割り切れない数字だった場合、c_length++して

親プロセスよりも1回多くループをするようにします。

 

そして81行目、waitpid(pid,&status,0)を入れることで

親プロセスが先にbreakしないようにしています。

 

 

 

 

といった感じで、期待通りの動作をしてくれました。

後々リライトでもっと見やすく、分かりやすくできるようがんばりやす。