linuxメッセージキューインスタンス
3802 ワード
前言:
メッセージキューは、メッセージのチェーンテーブルです.メッセージは、特定のフォーマットと特定の優先度を持つレコードと見なすことができます.メッセージキューに書き込み権限を持つプロセスは、一定のルールに従って新しいメッセージを追加できます.メッセージ・キューに読み取り権限があるプロセスは、メッセージ・キューからメッセージを読み出すことができます.
関数:
1.新しいメッセージキューの作成または既存のメッセージキューの取得
プロトタイプ:int msgget(key_t key,int msgflg);
パラメータ:
key:ポート番号と考えてもいいし、関数ftokで生成してもいいです.
msgflg:IPC_CREAT値は、キューがない場合は新しい識別子を作成して返します.既に存在する場合は、元の識別子が返されます. IPC_EXCL値は、キューがない場合は-1を返します.既に存在する場合は0を返します.
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:メッセージバッファへのポインタ.この位置は、送信および受信されたメッセージを一時的に格納するために使用され、ユーザー定義可能な汎用構造であり、形態は以下の通りである.
msgsz:メッセージのサイズ.
msgtyp:メッセージキュー内から読み込まれたメッセージ形態.値がゼロの場合、メッセージキュー内のすべてのメッセージが読み出されます.msgflg:コアプログラムがキューにデータがない場合に取るべき行動を示すために使用されます.msgflgと定数IPC_の場合NOWAITが併用されると、msgsnd()実行時にメッセージキューがいっぱいになると、msgsnd()はブロックされず、すぐに-1に戻り、msgrcv()が実行されると、メッセージキューが空の場合、待機せずにすぐに-1に戻り、エラーコードをENOMSGに設定する.msgflgが0の場合、msgsnd()およびmsgrcv()は、キューがいっぱいまたは空の場合、ブロック待機の処理モードをとる.
3.メッセージキューのプロパティの設定
プロトタイプ:int msgctl(int msgqid,int cmd,struct msqid_ds*buf);
パラメータ:msgctlシステムはmsgqidに識別されたメッセージキューに対してcmd操作を実行するように呼び出し、システムは3種類のcmd操作を定義した:IPC_STAT , IPC_SET , IPC_RMID IPC_STAT:メッセージキューに対応するmsqid_を取得するコマンドdsデータ構造をbufで指定したアドレス空間に保存します. IPC_SET:このコマンドはメッセージキューのプロパティを設定するために使用され、設定するプロパティはbufに格納されます.
IPC_RMID:msqid識別メッセージキューをカーネルから削除します.
例:
メッセージキューは、メッセージのチェーンテーブルです.メッセージは、特定のフォーマットと特定の優先度を持つレコードと見なすことができます.メッセージキューに書き込み権限を持つプロセスは、一定のルールに従って新しいメッセージを追加できます.メッセージ・キューに読み取り権限があるプロセスは、メッセージ・キューからメッセージを読み出すことができます.
関数:
1.新しいメッセージキューの作成または既存のメッセージキューの取得
プロトタイプ:int msgget(key_t key,int msgflg);
パラメータ:
key:ポート番号と考えてもいいし、関数ftokで生成してもいいです.
msgflg:IPC_CREAT値は、キューがない場合は新しい識別子を作成して返します.既に存在する場合は、元の識別子が返されます. IPC_EXCL値は、キューがない場合は-1を返します.既に存在する場合は0を返します.
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[1]; /* */
};
msgsz:メッセージのサイズ.
msgtyp:メッセージキュー内から読み込まれたメッセージ形態.値がゼロの場合、メッセージキュー内のすべてのメッセージが読み出されます.msgflg:コアプログラムがキューにデータがない場合に取るべき行動を示すために使用されます.msgflgと定数IPC_の場合NOWAITが併用されると、msgsnd()実行時にメッセージキューがいっぱいになると、msgsnd()はブロックされず、すぐに-1に戻り、msgrcv()が実行されると、メッセージキューが空の場合、待機せずにすぐに-1に戻り、エラーコードをENOMSGに設定する.msgflgが0の場合、msgsnd()およびmsgrcv()は、キューがいっぱいまたは空の場合、ブロック待機の処理モードをとる.
3.メッセージキューのプロパティの設定
プロトタイプ:int msgctl(int msgqid,int cmd,struct msqid_ds*buf);
パラメータ:msgctlシステムはmsgqidに識別されたメッセージキューに対してcmd操作を実行するように呼び出し、システムは3種類のcmd操作を定義した:IPC_STAT , IPC_SET , IPC_RMID IPC_STAT:メッセージキューに対応するmsqid_を取得するコマンドdsデータ構造をbufで指定したアドレス空間に保存します. IPC_SET:このコマンドはメッセージキューのプロパティを設定するために使用され、設定するプロパティはbufに格納されます.
IPC_RMID:msqid識別メッセージキューをカーネルから削除します.
例:
/*receive.c */
#include
#include
#include
#include
#include
#define MSGKEY 1024
struct msgstru
{
long msgtype;
char msgtext[2048];
};
/* , */
void childproc(){
struct msgstru msgs;
int msgid,ret_value;
char str[512];
while(1){
msgid = msgget(MSGKEY,IPC_EXCL );/* */
if(msgid < 0){
printf("msq not existed! errno=%d [%s]
",errno,strerror(errno));
sleep(5);
continue;
}
/* */
ret_value = msgrcv(msgid,&msgs,sizeof(struct msgstru),0,0);
printf("text=[%s] pid=[%d]
",msgs.msgtext,getpid());
}
return;
}
void main()
{
int i,cpid;
/* create 5 child process */
for (i=0;i<5;i++){
cpid = fork();
if (cpid < 0)
printf("fork failed
");
else if (cpid ==0) /*child process*/
childproc();
}
}
/*send.c*/
#include
#include
#include
#include
#include
#define MSGKEY 1024
struct msgstru
{
long msgtype;
char msgtext[2048];
};
main()
{
struct msgstru msgs;
int msg_type;
char str[256];
int ret_value;
int msqid;
msqid=msgget(MSGKEY,IPC_EXCL ); /* */
if(msqid < 0){
msqid = msgget(MSGKEY,IPC_CREAT|0666);/* */
if(msqid <0){
printf("failed to create msq | errno=%d [%s]
",errno,strerror(errno));
exit(-1);
}
}
while (1){
printf("input message type[0=end process]:");
scanf("%d",&msg_type);
if (msg_type == 0)
break;
printf("input message to be sent:");
scanf ("%s",str);
msgs.msgtype = msg_type;
strcpy(msgs.msgtext, str);
/* */
ret_value = msgsnd(msqid,&msgs,sizeof(struct msgstru),IPC_NOWAIT);
if ( ret_value < 0 ) {
printf("msgsnd() write msg failed,errno=%d[%s]
",errno,strerror(errno));
exit(-1);
}
}
msgctl(msqid,IPC_RMID,0); //
}