プロセス通信-メッセージキュー
4126 ワード
、メッセージキューメッセージキューとは、あるプロセスから別のプロセスにデータブロックを送信する方法を提供する.各データ・ブロックにはタイプがあり、受信者プロセスが受信するデータ・ブロックには異なるタイプの値があると考えられる.メッセージを送信することで、名前付きパイプの同期とブロックの問題を回避できます.メッセージキューは、パイプとは異なり、メッセージキューはメッセージベースであり、パイプはバイトストリームベースであり、メッセージキューの読み取りは必ずしも先入先出ではない.メッセージキューはネーミングパイプと同様に不足しているが,各メッセージの最大長には上限(MSGMAX)があり,各メッセージキューの総バイト数には上限(MSGMNB)があり,システム上のメッセージキューの総数にも上限(MSGMNI)がある.
注意:メッセージキュー、共有メモリ、信号量には共通のデータ構造があります.
二、関数
1.メッセージキューの作成または既存のメッセージキューの取得
パラメータ:
key:ポート番号と考えてもいいし、関数ftokで生成してもいいです. msgflg: (1)IPC_CREAT IPCが存在しない場合は、IPCリソースを作成します.そうでない場合は、アクションを開きます.(2)IPC_EXCL:共有メモリが存在しない場合にのみ、新しい共有メモリが確立されます.そうしないとエラーが発生します.
IPC_を単独で使用する場合CREAT、XXXXget()関数は、既存の共有メモリのオペレータを返すか、新しい共有メモリの識別子を返します.
(3)IPC_をCREATとIPC_EXCLフラグを一緒に使用すると、XXXget()は新しいIPC識別子を返します.IPCリソースが既に存在する場合、または-1を返します. IPC_EXELマーク自体はあまり意味はありませんが、IPC_とCREATフラグは、既存のオブジェクトを開くのではなく、結果として得られるオブジェクトが新規であることを保証するために一緒に使用されます.2.キューへのメッセージの読み取り/書き込み
メッセージ・キューからメッセージを取得
メッセージ・キューにデータを配置
パラメータ:
msqid:メッセージキューの識別コード
msgp:メッセージバッファへのポインタ.この位置は、送信および受信されたメッセージを一時的に保存するために使用され、ユーザが定義可能なデータ構造である.
msgsz:メッセージのサイズ
msgtype:メッセージキュー内からメッセージを読み出す形態で、値がゼロの場合、メッセージキュー内のすべての値が読み出されることを示します.
msgflg:キューにデータがない場合にコアプログラムが取るべき行動を示すために使用されます.
(1)msgflgと定数IPC_の場合NOWAITが併用されると、msgsnd()の実行時にメッセージキューがいっぱいになると、msgsnd()はブロックされず、すぐに-1に戻ります.
(2)msgrcv()が実行されている場合、メッセージキューが空の場合、待機せずにすぐに-1に戻る.
(3)msgflgが0の場合、msgsnd()およびmsgrcv()は、キューがいっぱいまたは空の場合、ブロック待ちの処理モードをとる.
3.メッセージキューのプロパティの設定
パラメータ:
msgctlシステムはmsgqidに識別されたメッセージキューに対してcmd操作を実行するように呼び出し、システムは3種類のcmd操作(1)IPC_を定義した.STAT:メッセージキューに対応するmsqid_を取得するコマンドdsデータ構造をbufで指定したアドレス空間に保存します. (2) IPC_SET:このコマンドはメッセージキューのプロパティを設定するために使用され、設定するプロパティはbufに格納されます. (3) IPC_RMID:msqid識別メッセージキューをカーネルから削除します.
例:
comm.h
comm.c
注意:メッセージキュー、共有メモリ、信号量には共通のデータ構造があります.
二、関数
1.メッセージキューの作成または既存のメッセージキューの取得
int msgget(key_t key, int msgflg);
パラメータ:
key:ポート番号と考えてもいいし、関数ftokで生成してもいいです. msgflg: (1)IPC_CREAT IPCが存在しない場合は、IPCリソースを作成します.そうでない場合は、アクションを開きます.(2)IPC_EXCL:共有メモリが存在しない場合にのみ、新しい共有メモリが確立されます.そうしないとエラーが発生します.
IPC_を単独で使用する場合CREAT、XXXXget()関数は、既存の共有メモリのオペレータを返すか、新しい共有メモリの識別子を返します.
(3)IPC_をCREATとIPC_EXCLフラグを一緒に使用すると、XXXget()は新しいIPC識別子を返します.IPCリソースが既に存在する場合、または-1を返します. IPC_EXELマーク自体はあまり意味はありませんが、IPC_とCREATフラグは、既存のオブジェクトを開くのではなく、結果として得られるオブジェクトが新規であることを保証するために一緒に使用されます.2.キューへのメッセージの読み取り/書き込み
メッセージ・キューからメッセージを取得
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int
msgflg);
メッセージ・キューにデータを配置
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
パラメータ:
msqid:メッセージキューの識別コード
msgp:メッセージバッファへのポインタ.この位置は、送信および受信されたメッセージを一時的に保存するために使用され、ユーザが定義可能なデータ構造である.
struct msgstru{
long mtype; // 0
char mtext[ ];
};
msgsz:メッセージのサイズ
msgtype:メッセージキュー内からメッセージを読み出す形態で、値がゼロの場合、メッセージキュー内のすべての値が読み出されることを示します.
msgflg:キューにデータがない場合にコアプログラムが取るべき行動を示すために使用されます.
(1)msgflgと定数IPC_の場合NOWAITが併用されると、msgsnd()の実行時にメッセージキューがいっぱいになると、msgsnd()はブロックされず、すぐに-1に戻ります.
(2)msgrcv()が実行されている場合、メッセージキューが空の場合、待機せずにすぐに-1に戻る.
(3)msgflgが0の場合、msgsnd()およびmsgrcv()は、キューがいっぱいまたは空の場合、ブロック待ちの処理モードをとる.
3.メッセージキューのプロパティの設定
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
パラメータ:
msgctlシステムはmsgqidに識別されたメッセージキューに対してcmd操作を実行するように呼び出し、システムは3種類のcmd操作(1)IPC_を定義した.STAT:メッセージキューに対応するmsqid_を取得するコマンドdsデータ構造をbufで指定したアドレス空間に保存します. (2) IPC_SET:このコマンドはメッセージキューのプロパティを設定するために使用され、設定するプロパティはbufに格納されます. (3) IPC_RMID:msqid識別メッセージキューをカーネルから削除します.
例:
comm.h
#pragma once
#include
#include
#include
#include
#include
#define _PATH_NAME_ "/tmp"
#define _PROJ_ID_ 0x6666
#define _SIZE_ 1024
extern int serve_type;
extern int client_type;
struct msgbuf
{
long mtype;
char mtext[_SIZE_];
};
int create_msg_queue();
int get_msg_queue();
void destory_msg_queue(int msg_id);
void recv_msg_queue(int msg_id,char* out,int _type);
int create_msg_queue();
void send_msg_queue(int msg_id,const char*msg,int _type);
comm.c
#include"comm.h"
#include
#include
#include
#include
#include"comm.h"
int serve_type=1;
int client_type=2;
static int comm_msg_queue(int flag)
{
key_t _key = ftok(_PATH_NAME_,_PROJ_ID_);
if(_key<0)
{
perror("ftok");
return -1;
}
int msg_id = msgget(_key,IPC_CREAT | IPC_EXCL);
if(msg_id
serve.c
#include"comm.h"
int main()
{
int msg_id = create_msg_queue();
if(msg_id 0)
{
buf[_s]='\0';//bug
}
send_msg_queue(msg_id,buf,serve_type);
}
destory_msg_queue(msg_id);
return 0;
}
client.c #include"comm.h"
int main()
{
int msg_id = get_msg_queue();
int done = 0;
char buf[_SIZE_];
while(!done)
{
printf("Please Enter#");
fflush(stdout);
ssize_t _s=read(0,buf,sizeof(buf)-1);
if(_s > 0)
{
buf[_s]='\0';//bug
}
send_msg_queue(msg_id,buf,client_type);
memset(buf,'\0',sizeof(buf));
recv_msg_queue(msg_id,buf,serve_type);
printf("serve#%s",buf);
}
destory_msg_queue(msg_id);
return 0;
}