Operating Systems. Exercise 07
I. プロセス間でのメモリ共有 (準備課題, 配点無し)
演習問題を解くために必要なプロセス間メモリ共有のためのC言語インターフェースを説明します。
Cプログラム内で変数を宣言すると, それを格納するためのメモリ領域が確保されます。 今までは以下のような確保のされかたでした。
静的領域確保の場合
int nVariable; //変数1つ
int naStaticArray[2]; //変数配列
動的領域確保の場合
int *nVariable; //ポインタ変数
nVariable = (int*)malloc(1*sizeof(int)); //領域割り当て(変数1つ)
int *naDynamicArray; //ポインタ変数
naDynamicArray = (int*)malloc(2*sizeof(int)); //領域割り当て(変数配列)
これらの確保の仕方の場合, ある"プロセス1"から他の"プロセス2"にデータを渡すには
パイプによって標準入出力を経由したり,
C言語では共有メモリ確保や領域割り当てなどの操作を, shm*系システムコールによって実現できます。
以下のプログラムで、確保の仕方など確認しプログラムの意味を理解して演習問題に備えてください。
ステップ1. 共有メモリ領域を確保し, 領域を変数に割り当てる
//共有メモリ領域の確保先変数nVar1とnVar2
int *nVar1;
int *nVar2;
//共有メモリ領域のサイズはnVar1とnVar2の分で型はint
int nShareMemSize = 2*sizeof(int);
ShareMemTest1.c
#include "ShareMemTest.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int nShareMemID;
int main() {
//共有メモリ領域確保を要求し IDを覚えておく
nShareMemID = shmget(IPC_PRIVATE, nShareMemSize, SHM_R|SHM_W);
printf("nShareMemID = %d\n", nShareMemID);
//ポインタ変数nVar1にshmatで共有メモリ領域を割り当てる
nVar1 = shmat(nShareMemID, 0, SHM_R|SHM_W);
//ポインタ変数nVar2のための領域は, nVar1のアドレスから1つ先にあるのでそこを指す
nVar2 = nVar1 + 1;
//nVar1とnVar2に共有メモリ領域を割り当てたので 使えるようになる
*nVar1 = 1;
*nVar2 = 2;
printf("process1 : nVar1 = %d\nnVar2 = %d\n", *nVar1, *nVar2);
//別ターミナルからipcsを実行し共有メモリ領域が確保されたのを確認するために 終わるのを遅らせる
sleep(20);
printf("process1 : nVar1 = %d\nnVar2 = %d\n", *nVar1, *nVar2);
//共有メモリ領域開放
shmctl(nShareMemID, IPC_RMID, 0);
return 0;
}
ターミナル1 (ShareMemTest1実行)
|
ターミナル2 (ipcs実行)
|
ステップ2. 別プロセス間で共有メモリを読み書きする
別プロセスを実行するためのプログラムを用意します (ShareMemTest2.c)
#include "ShareMemTest.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int nShareMemID;
int main(int argc, char *argv[]) {
if (argc != 2) return 0;
//共有メモリIDを引数から取る
nShareMemID = atoi(argv[1]);
printf("nShareMemID = %d\n", nShareMemID);
//共有メモリIDから共有メモリ領域を得る
nVar1 = shmat(nShareMemID, 0, SHM_R|SHM_W);
nVar2 = nVar1 + 1;
printf("process2 : nVar1 = %d, nVar2 = %d\n", *nVar1, *nVar2);
//nVar1の中身を2に書き換えてみる
*nVar1 = 2;
printf("process2 : nVar1 = %d, nVar2 = %d\n", *nVar1, *nVar2);
return 0;
}
ターミナル1 (ShareMemTest1実行)
|
ターミナル2 (ShareMemTest2実行)
|
II. プロセス間メモリ共有(配点100%)
課題1
課題:
棒の状態(naA,naB,naC)と円盤数(nDisks)と総移動回数(nMoves)を格納する変数を共有メモリ領域に確保し,
独立したプロセス1(ハノイの塔を解く)とプロセス2(塔の内容を表示)で役割分担する
プログラムを作成してください。
共通ヘッダ : HanoiShareMem.h
ヘッダ
プロセス1 : ハノイの塔の円盤移動(Solve側)
テンプレート
プロセス2 : ハノイの塔の状態を出力する(Display側)
テンプレート
ターミナル1 (プロセス1実行)
|
ターミナル2 (プロセス2実行)
|
解答の結果出力される途中経過について
途中経過を出力すると以下のように, 同じ円盤が複数存在するなど何かおかしなものになります。
(一部略)
| 0| | 0| | 0|
| 0| | 0| | 0|
| 0| | 0| | 0|
| 0| | 0| | 1|
| 0| | 3| | 2|
| 0| | 2| | 0|
| 3| | 0| | 0|
| 0| | 8| | 3|
| 7| | 9| | 8|
|10| |12| |13|
|11| |15| |18|
|14| |16| |21|
|17| |19| |22|
|24| |20| |25|
|27| |23| |26|
|28| |30| |29|
---- ---- ----
A B C
これは, Solve側のプロセスから共有メモリに書き込む処理を完全に終えないうちに, 次回の演習で, これへの対処方法(排他的共有メモリアクセス制御)の実験をします。