2020年2月14日マルチプログラミング(並列処理)を実現するには様々な方法が存在します。その一つにマルチプロセス化があります。新たにプロセスを作成して、それぞれのプロセスが並列に処理を進めていく方法です。新たにプロセスを作成するには、fork()関数を使用します。作成した側は親プロセスと呼ばれます。ここでプロセスという単位はどのような役割を持つか確認です。保護単位(プロセス間で干渉をしない)資源割り当て単位(使用中は割り当てられたハードウェア資源を独占する)マルチプロセスにすると、main文での処理とは別にfork()で生成した子プロセスがプログラムされた処理を行います。ここで子プロセスについて確認します。子プロセスは親プロセスをそのまま継承します。生成後は別々のものとして扱います。別々のものになるのでこれらは、メモリ上に新たにセットされます。ややこしいのは、命令がセットされたメモリ領域(コードセグメント)は同一の領域を使用します。親プロセスでも子プロセスでも逆アセンブルすると同じ領域が指し示されます。※コード(テキスト)セグメントの話です。親プロセスからでも子プロセスからでも同じメモリ領域を指す、という意味です。実際にマルチプロセス化してみましょう。0;}fork()で子プロセスを作成します。並列処理が始まります。親プロセスには子プロセスのPIDを子プロセスにはPID=0を返します。ややこしいですが、fork()は通常の関数とは異なり、1コールで2回の返り値が戻ってきます。実用的なプログラムでは、fork後の処理を親プロセスと子プロセスの両方に分けて書きます。読んだら、その時点で終了となります。その際に親プロセスには、子プロセスが終了した連絡が届きます。これにはプロセス間通信で用いるシグナルのSIGCHLDが親プロセスに送信されます。子プロセスが終了したことを確信してから親プロセスもreturnで終了します。上のコードを実行すると以下になります。本来はグローバル変数として宣言したvarAが共有されるイメージですが、マルチプロセスではメモリ空間が異なるので、別物として扱います。そのためvarAに値を代入しても他プロセスのvarAには影響を与えません。それではgdbでデバッグしてみましょう。スポンサーリンク子プロセスをgdbでデバッグしてみるgccコンパイルするときに-qオプションを付けます。親プロセスを追ってみます。親プロセスはmain文です。mainで逆アセンブルしてみます。子プロセスを作成した次の段階で、breakポイントを置きます。listでコードを表示します。数字でブレイクポイントを置く場所を設定します。今回は30行目に置きました。30行目でプログラムが止まります。この段階でスタック領域を見てみます。rbpをタイプします。物理アドレスが表示されます。main(親プロセス)のスタック領域は0x7fffffffe190から0x7fffffffe1a0の領域に確保しています。varAグローバル変数がセットされたアドレスと中身の値を見ます。これは、mainの命令がセットされたコードセグメントに近い値を示していることが分かります。※varAは実際には、bssセグメントに格納されています。タイプして、varBローカル変数を表示します。スタック領域にしっかりと格納されいることが分かりますね。それでは子プロセスのスタック領域、varAとvarBについて同様に表示してみましょう。このままでは親プロセスしか見えないので、子プロセスに変更します。childとタイプします。子プロセスを逆アセンブルします。processFuncで子プロセスの命令がセットされた領域を覗けます。(コードセグメント)すると親プロセス(main)の命令にほぼ連続で下位アドレス側に格納されていますね。続いて肝心のvar変数たちを見てみましょう。子プロセスが終了する直前の14行目に指定して実行しています。値は確かに0x32=50なので良いのですが、なぜでしょうか。コピーオンライト機能がまだ継続しているのでしょうか。子プロセスを作成しても実際に、メモリアドレスに書き込みが行われるまでは親プロセスとアドレス空間を共有する機能です。子プロセスのみが保有する物理メモリ領域が新たに作成されます。アドレス空間の勉強を深める必要があるようですね。varBを見てみましょう。子プロセス(processFunc)のスタック領域の中にちゃんとありました。中の値も0x64=100で正しいです。rbpレジスタが保持しているアドレスも出力しました。下位アドレス側に向かってスタックされていることが分かります。最後まで読んでいただきありがとうございました。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。date*日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)関連記事CのRawSocketでARPスプーフィングしてみた!今回はARPスプーフィングをC言語で実際に体感してみたいと思います。VirtualBoxを用いて、ホストOS一台とゲストOS二台で行いました。対象AはホストOSなので、MACアドレスは伏せました。SocketでARPパケットをキャプチャするARPパケットにターゲットを絞って、パケットキャプチャしていこうと思います。ARPパケットを扱うには、linuxで定義されているether_arp構造体とarphdr構造体を使用します。...【DHCP】Cでdiscoverを送信してみた今回はDHCPのdiscoverパケットを送信してみました。してもbindエラーになってしまう。SocketでICMPパケットを扱ってみた!今回はICMPパケットに絞ってみていこうと思います。ICMPはタイプとコードの値を持っています。タイプによっては複数のコードを持つものもあります。...PREV微生物燃料電池の種類と原理についてのまとめNEXTpHが微生物燃料電池の発電能力に与える影響を実験してみたプロフィール某名門大の大学院生です。IoT、人口知能、ネットワークインフラ系まで幅広く興味があります。いう方のために簡単にまとめてみました。IPv6を取得して標準出力させてみます。自分の目で調査したのでまとめます。変更までする方法をご紹介します。ioctlシステムコールを使います。フラグを引数に指定します。一度まとめておこうと思います。以下が思いつくかと思います。全て"stdio.h"に定義されています。