BLOGTIMES
2018/04/26

POSIX Message Queue を使ってプロセス間通信をする

  c  posix 
このエントリーをはてなブックマークに追加

C 言語から簡単に使える MQ がないかと思って調べてみたら、POSIX Message Queue が恐ろしく便利だったのでメモ。

動作については Java のBlockingQueueをプロセスを跨いで使えるようなイメージです。

サンプルプログラム

今回のプログラムは送信側 qsend と受信側 qrecv の2つに分かれています。

qsend は 0, 1, 2・・・ というように文字表示しながら、その文字を /testq という Queue に書き込み続けるプログラムになっています。
対になる qrecv は /testq という Queue から文字を取り出して表示を行います。

今回は Queue のサイズを 10 に設定しているので、溜まっているメッセージの数が 10 個になると qsend は mq_send() 部分でブロックし、Queue が空くのを待ちます。qrecv は溜まっているメッセージの数が 0 個になると、mq_receive() 部分でブロックし、新しいメッセージの到着を待ちます。

一見、機能はパイプと大差ない感じに見えるかもしれませんが、このプログラムはどちらから起動しても大丈夫です。
また、qsend, qrecv 共に複数個起動しても問題なく動作します。

qsend.c

#include <mqueue.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #define QNAME "/testq" int main(){ int cnt = 0; int ret; char str[100]; char *buff; mqd_t q; struct mq_attr attr; attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = 1024; attr.mq_curmsgs = 0; mode_t omask; omask = umask(0); q = mq_open(QNAME, (O_WRONLY | O_CREAT), 0777, &attr); umask(omask); if ( q == -1 ){ printf("[ERROR]%d: %s\n", errno, strerror(errno)); return 1; } while(1){ sprintf(str ,"%d", cnt++); buff = (char *)calloc(strlen(str) + 1, sizeof(char)); strcpy( buff, str ); printf("%s\n", buff); ret = mq_send( q, buff , strlen(buff) , 0); if ( ret == -1 ) { printf("[ERROR]%d: %s\n", errno, strerror(errno)); return 1; } free(buff); sleep(1); } }

qrecv.c

#include <mqueue.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #define QNAME "/testq" int main(){ mqd_t q; struct mq_attr attr; char *buff; ssize_t n; int i; q = mq_open(QNAME, O_RDONLY); if ( q == -1 ){ printf("[ERROR]%d: %s\n", errno, strerror(errno)); return 1; } while(1){ mq_getattr( q ,&attr ); buff = (char *)malloc(attr.mq_msgsize); n = mq_receive( q, buff, attr.mq_msgsize, NULL); if ( n == -1 ) { printf("[ERROR]%d: %s\n", errno, strerror(errno)); return 1; } for (i = 0; i < n; i++) putchar(buff[i]); putchar('\n'); fflush(stdout); free(buff); } }

コンパイルと実行

以下のオプションでコンパイルし、./qsend と ./qrecv を好きなだけ起動すれば動作がわかります。

gcc qrecv.c -lrt -o qrecv gcc qsend.c -lrt -o qsend

参考


    トラックバックについて
    Trackback URL:
    お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
    このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/10135
    Trackbacks
    このエントリにトラックバックはありません
    Comments
    愛のあるツッコミをお気軽にどうぞ。[policy]
    古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
    コメントはありません
    Comments Form

    コメントは承認後の表示となります。
    OpenIDでログインすると、即時に公開されます。

    OpenID を使ってログインすることができます。

    Identity URL: Yahoo! JAPAN IDでログイン