昨日、Oracle データベースサーバの共有メモリ利用状況をipcsコマンドで確認
しました。実行画面の左から2列目(2カラム目)に 、
shmid
って表示されてマス 。
shmとは、SHared Memory=共有メモリ
shmidとIDがついて共有メモリのセグメント識別子
Oracle サーバのプロセスが使用しているデータセグメント(キョウユウメモリ)の位置を示しているんだろナ
このように、Oracleは共有メモリをつかっています 、
解る人は別にはるかに教わりたかぁないか(*゚.゚)ゞ
゚・*:.。..。.:*・゚゚・*:.。..。.:*・゚ ゚・*:.。..。.:*・゚゚・*:.。..。.:*・゚
さあ、お休みの今日のハルカわっ!! オラクルサーバちゃんがやっていることと同じようなことを、C言語でプログラミングしてみて、試しにやってみま~すっ!!
環境はLinux
実験内容は
*:..。o○☆゚・:,。*:..。o○☆
①1つのプロセス(=簡易サーバ)を作って、
そのプロセスで共有メモリ空間を獲得
②他のプロセスからそのメモリ空間の
データにアクセスして、空間のデータを更新する
*:..。o○☆゚・:,。*:..。o○☆
ってゆぅ簡易データベースサーバ&クライアントですっ
まず①の共有メモリを使用するサーバのソース
shm_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(void)
{
int id;
char *adr;
/* 新規shmを生成 */
if((id = shmget (IPC_PRIVATE,512,IPC_CREAT|0666))==-1){
perror ("shmget");
exit(-1);
}
/* データセグメントにアタッチ */
if((adr=(char *)shmat(id,NULL,0))==(void *)-1){
perror("shmat");
} else {
strcpy(adr,"データ未登録");
/* 1秒毎出力 */
while(1) {
printf("SHM_ID=%d::VALUE=%s\n",id,adr);
/* end 入力で終了 */
if (strcmp(adr,"end")==0) {
break;
}
sleep(1);
}
if (shmdt(adr)==-1) {
/* アンマップ */
perror("shmdt");
}
}
/* 共有メモリを削除 */
if (shmctl(id,IPC_RMID,0)==-1){
perror("shmctl");
exit(EXIT_FAILURE);
}
return 0;
}
|
共有メモリを使う方法は、
①shmget()システムコールで、共有メモリのデータセグメント識別子を取得する。
②shmat()システムコールで、自プロセスのデータセグメントにマップ(アタッチ)する。
③shmdt()システムコールで、データセグメントをアンマップ(デタッチ)する。
④shmctl()システムコールで、共有メモリを削除する
という流れ。前回用いたipcのヘッダファイルと、shm.hをincludeしてます~~
このプログラムは、
①で変数idにセグメント識別子を代入
②でデータセグメントにアタッチし
変数adsにデータ本体を格納、表示しますぅ。。
*:..。o○☆゚・:,。*:..。o○☆
おつぎは、クライアントを想定した、データ更新プログラム、
shm_writer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(int argc, char *argv[])
{
int id;
char *adr;
if ( argc <= 2 ) {
fprintf(stderr,"Usage:共有メモリID データ\n");
exit(EXIT_FAILURE);
}
id=atoi(argv[1]);
if((adr=(char *)shmat(id,0,0))==(void *)-1){
perror("shmat");
} else {
strcpy(adr, argv[2]);
fprintf(stderr,"written.\n");
if(shmdt(adr)==-1){
perror("shmdt");
}
}
}
|
このプログラムは引数として与えられたセグメント識別子を指定して、shmat()、つまりサーバと同じ共有メモリのアドレス空間を指す、メモリを操作(更新)できるようになるわけ
゚・*:.。..。.:*・゚゚・*:.。..。.:*・゚ ゚・*:.。..。.:*・゚゚・*:.。..。.:*・゚
あ~~んまり、はるかも、理解できていないと思うんだけど
……実際にタメシテミル
上の2つのプログラムをコンパイルしまぁす
> gcc shm_server.c -o shm_server
> gcc shm_writer.c -o shm_writer
>
|
簡易DBサーバを起動しまぁす~
> ./shm_server
SHM_ID=950285::VALUE=データ未登録
SHM_ID=950285::VALUE=データ未登録
SHM_ID=950285::VALUE=データ未登録
(後略)
|
この時点では、共有メモリの識別子950285のデータセグメントには何のデータも登録されていない状態。。
ここで、別のターミナルを立ち上げて、
クライアント側書き込みプログラムを実行し、同じ共有メモリ識別子(950285)の空間に書き込みを行います。
つまり、別プロセスから他のプロセスのアドレス空間を操作する、ってことです。さぁぁぁぁぁてっ!
> ./shm_writer 950285 ブラジャー
written.
>
|
こちら、サーバ側ターミナル。あ!データが変わった!!
SHM_ID=950285::VALUE=ブラジャー
SHM_ID=950285::VALUE=ブラジャー
SHM_ID=950285::VALUE=ブラジャー
SHM_ID=950285::VALUE=ブラジャー
SHM_ID=950285::VALUE=ブラジャー
|
データが更新されてます!
さらにクライアント側から更新をかけるとぉぉ
> ./shm_writer 950285 コルセット
written.
|
サーバ側
SHM_ID=950285::VALUE=コルセット
SHM_ID=950285::VALUE=コルセット
SHM_ID=950285::VALUE=コルセット
SHM_ID=950285::VALUE=コルセット
SHM_ID=950285::VALUE=コルセット
SHM_ID=950285::VALUE=コルセット
SHM_ID=950285::VALUE=コルセット
|
と、メモリ空間が共有されていること、よぉぉく、理解できましたぁっ!
゚・*:.。..。.:*・゚゚・*:.。..。.:*・゚ ゚・*:.。..。.:*・゚゚・*:.。..。.:*・゚
なるほど、ねぇ。。。はるかこれは先輩のススメで、初めてやってみたのですが、なぁんだかぁ、データベースの基本的な仕組みがよぉくわかった気がする
もっとlockとかセマフォとかが入ってきてややこしい仕組みだとは思うんだけどねっ、Oracleなんかは。。。(・ω・)/
ひっさびさに、チョー夢中になって実験しちゃいました
■関連記事:
共有メモリ☆そのいちっ★ipcsこまんど
|