Message queueの一般的な操作と例

6739 ワード

Message queueはSystem V IPCの三剣客の一人(それぞれmessage queue,semaphore,shared memory)であり、主に以下の4つの関数呼び出しから構成されている:(msgget,msgctl,msngsnd,msgrcv)
 
(1) msgsend.cxx(メッセージqueueを作成し、メッセージをカーネルのメッセージキューに送信)
 
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#include<stdio.h>

#include<iostream>

using namespace std;

#define BUF_SIZE 100

typedef struct {
    long mtype;
    char mtext[BUF_SIZE];
} msg_info;

key_t getkey()
{
    key_t key = ftok("/home/kingoal",1);
    if(key == -1)
    {
        perror("Error on create key");
        exit(-1);
    }

    return key;
}

int create_msg_queue()
{
    int msg_id;

    key_t key = getkey();
    msg_id = msgget(key, IPC_CREAT|0660);

    if(msg_id == -1)
    {
        perror("msgget error");
        exit(-1);
    }

    return msg_id;
}

int send_message(int msg_id,char* message)
{
    int result;
    msg_info MsgInfo;

		memset(&MsgInfo,0,sizeof(msg_info));
    MsgInfo.mtype = 10;
    strcpy(MsgInfo.mtext, message);
    
    result = msgsnd(msg_id,&MsgInfo,strlen(message)+1,0);
    if(result == -1)
    {
        perror("Failed to send message");
    }

    return result;
}

int show_msg_queue_stat(int msg_id)
{
    struct msqid_ds MsgQueueInfo;
    int result;

    result = msgctl(msg_id,IPC_STAT, &MsgQueueInfo);
    if(result == -1)
    {
        perror("Error on message control");
        exit(-1);
    }

    cout<<"============= Message Queue Info ============="<<endl;
    cout<<"Effective user id: "<<MsgQueueInfo.msg_perm.uid<<endl;
    cout<<"Effective user group id: "<<MsgQueueInfo.msg_perm.gid<<endl;
    cout<<"Current numbers of bytes in message queue(non-standard): "<<MsgQueueInfo.msg_cbytes<<endl;
    cout<<"Current numbers of message in the queue: "<<MsgQueueInfo.msg_qnum<<endl;
    cout<<"=============================================="<<endl;

    return result;
}

int main(int argc,char* argv[])
{
    int msg_id = create_msg_queue();
    send_message(msg_id,"Hello message queue");
    show_msg_queue_stat(msg_id);

    return 0;
}


 (2) msgrcv.cxx(カーネルからメッセージを読み出し、最後にカーネルのmessage queueを削除)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define BUF_SIZE 100

typedef struct {
    long mtype;
    char mtext[BUF_SIZE];
}msg_info;

int rcv_msg(int msg_id,int msg_type,char* msg)
{
    int result;
    msg_info MsgInfo;

    result = msgrcv(msg_id,&MsgInfo,BUF_SIZE,msg_type,IPC_NOWAIT);
    if(result == -1)
    {
        if( errno == ENOMSG)
            return errno;

        perror("Error on message receive");
        exit(-1);
    }

    strcpy(msg,MsgInfo.mtext);

    return result;
}

int main(int argc,char* argv[])
{
    int result;
    char message[BUF_SIZE];
    int msg_type;
    int msg_id;

    if(argc != 3)
    {
        printf("Usage: %s msgid msg_type
", argv[0]); return -1; } msg_type = atoi(argv[2]); msg_id = atoi(argv[1]); while(1) { result = rcv_msg(msg_id,msg_type,message); if(result == ENOMSG) break; printf("Message: %s
",message); memset(message,0,BUF_SIZE); } msgctl(msg_id,IPC_RMID,NULL); return 0; }

(3)実行結果
[kingoal@sunrise ~/dev/cxx]$ ./msgsend 
============= Message Queue Info =============
Effective user id: 1001
Effective user group id: 1001
Current numbers of bytes in message queue(non-standard): 20
Current numbers of message in the queue: 1
==============================================
[kingoal@sunrise ~/dev/cxx]$ ./msgsend 
============= Message Queue Info =============
Effective user id: 1001
Effective user group id: 1001
Current numbers of bytes in message queue(non-standard): 40
Current numbers of message in the queue: 2
==============================================
[kingoal@sunrise ~/dev/cxx]$ ./msgsend 
============= Message Queue Info =============
Effective user id: 1001
Effective user group id: 1001
Current numbers of bytes in message queue(non-standard): 60
Current numbers of message in the queue: 3
==============================================
[kingoal@sunrise ~/dev/cxx]$ ./msgsend 
============= Message Queue Info =============
Effective user id: 1001
Effective user group id: 1001
Current numbers of bytes in message queue(non-standard): 80
Current numbers of message in the queue: 4
==============================================
[kingoal@sunrise ~/dev/cxx]$ ./msgsend 
============= Message Queue Info =============
Effective user id: 1001
Effective user group id: 1001
Current numbers of bytes in message queue(non-standard): 100
Current numbers of message in the queue: 5
==============================================
[kingoal@sunrise ~/dev/cxx]$ ipcs
Message Queues:
T           ID          KEY MODE        OWNER    GROUP   
q       786432     22754234 --rw-rw---- kingoal  kingoal 

Shared Memory:
T           ID          KEY MODE        OWNER    GROUP   

Semaphores:
T           ID          KEY MODE        OWNER    GROUP   

[kingoal@sunrise ~/dev/cxx]$ main 786432 10
Message: Hello message queue
Message: Hello message queue
Message: Hello message queue
Message: Hello message queue
Message: Hello message queue
[kingoal@sunrise ~/dev/cxx]$