コンピューター:C言語講座:メッセージについて
概要
IPC関連の最後として、メッセージを取り上げます。メッセージはプロセス間でデータをストリーム的にやりとりすることが可能で、FIFOやパイプに似ていますが、メモリ上で行なわれるのでより高速です。しかし、それ以外にはあまりメリットが無く、参考文献によると「可能なかぎりメッセージは使わないべき」とまで書かれています。
実際に使ってみた感触でも、多少便利なことが出来るのですが、マニュアルが少なく、結局完全には理解できませんでした。
サンプル
とりあえず、簡単に送信プログラムと受信プログラムを作成し、標準入力からのデータを受信プログラムが標準出力に表示するものにしました。
<送信プログラム>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
void main()
{
int qid;
struct {
long mtype;
char mtext[512];
}buf;
if((qid=msgget(123,0666|IPC_CREAT))==-1){
perror("msgget");
exit(-1);
}
while(1){
gets(buf.mtext);
buf.mtype=1L;
if(msgsnd(qid,&buf,sizeof(buf.mtext)-sizeof(buf.mtype),0)==-1){
perror("msgsnd");
break;
}
if(strcmp(buf.mtext,"end")==0){
break;
}
}
}<受信プログラム>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
void main()
{
int qid;
struct {
long mtype;
char mtext[512];
}buf;
if((qid=msgget(123,0666|IPC_CREAT))==-1){
perror("msgget");
exit(-1);
}
while(1){
if(msgrcv(qid,&buf,512,0L,0)==-1){
perror("msgrcv");
break;
}
printf("%s\n",buf.mtext);
if(strcmp(buf.mtext,"end")==0){
break;
}
}
if(msgctl(qid,IPC_RMID,NULL)==-1){
perror("msgctl");
exit(-1);
}
}
msgget()でキー(123)を指定してメッセージを確保します。サンプルではIPC_CREATを指定しているので、無ければ作成して、そのIDが得られます。
送信はmsgsnd()で行ないます。メッセージのIDに対してデータのバッファとサイズ、メッセージフラグを指定して送信します。バッファはstruct
msgbufを使用するのですが、とりあえず、longのメッセージタイプと何らかのバッファを入れた構造体を状況によって指定するのではないかと思います。マニュアルなどを見てもよくわかりませんでしたが、これで正しく動きました。メッセージフラグによって送信動作が細かく指定できますが、これも難解です。
メッセージタイプは受信時に選択的に受け取りたいメッセージだけを識別するのに使用するのですが、これも簡単にテストした感じでは問題がありました。
受信はmsgrcv()で行ないます。メッセージのIDに対してバッファと最大サイズとメッセージタイプ、メッセージフラグを指定して受信します。メッセージタイプを0以外にすると選択的にメッセージを受信できるのですが、実験した結果、バッファに多少データがたまるとブロックしてしまいました。正しく使用すれば使えるのでしょうけれど、詳しい説明がありませんでした。
結局IPC関連で有効な機能としては共有メモリくらいで、セマフォとメッセージはどうもピンと来ません。詳しい方は是非教えてください。
なお、共有メモリ、セマフォと同様に不要のセマフォはmsgctl()にIPC_RMIDを指定して削除するか、ipcrmコマンドで削除する必要があります。