首页 > 代码库 > System V的消息队列(1)

System V的消息队列(1)

消息队列:

消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法
每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)


IPC对象数据结构
内核为每个IPC对象维护一个数据结构
struct ipc_perm {
key_t          __key;       /* Key supplied to xxxget(2) */
uid_t          uid;         /* Effective UID of owner */
gid_t          gid;         /* Effective GID of owner */
uid_t          cuid;        /* Effective UID of creator */
gid_t          cgid;        /* Effective GID of creator */
unsigned short mode;        /* Permissions */
unsigned short __seq;       /* Sequence number */
};


消息队列结构
struct msqid_ds {
struct ipc_perm msg_perm;     /* Ownership and permissions */
time_t      msg_stime;    /* Time of last msgsnd(2) */
  time_t      msg_rtime;    /* Time of last msgrcv(2) */
time_t      msg_ctime;    /* Time of last change */
unsigned long    __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */
msgqnum_t      msg_qnum;     /* Current number of messages
                                                in queue */
msglen_t      msg_qbytes;   /* Maximum number of bytes
                                                allowed in queue */
pid_t                   msg_lspid;      /* PID of last msgsnd(2) */
pid_t                  msg_lrpid;      /* PID of last msgrcv(2) */
};


消息队列函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msgget函数
功能:用来创建和访问一个消息队列
原型
int msgget(key_t key, int msgflg);
参数
key: 某个消息队列的名字
msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该消息队列的标识码;失败返回-1

msgctl函数
功能:消息队列的控制函数
原型
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数
msqid: 由msgget函数返回的消息队列标识码
cmd:是将要采取的动作,(有三个可取值)
返回值:成功返回0,失败返回-1

msg_rmid.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)


int main(void)
{
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
        ERR_EXIT("msgget");

    printf("msgget succ\n");
    printf("msgid=%d\n", msgid);
    
    msgctl(msgid, IPC_RMID, NULL);
    return 0;
}

msgset.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)


int main(void)
{
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
        ERR_EXIT("msgget");

    printf("msgget succ\n");
    printf("msgid=%d\n", msgid);
    
    struct msqid_ds buf;
    msgctl(msgid, IPC_STAT, &buf);
    sscanf("600", "%o", (unsigned int*)&buf.msg_perm.mode);
    msgctl(msgid, IPC_SET, &buf);
    
    return 0;
}

msgget.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)


int main(void)
{
    int msgid;
    msgid = msgget(1234, 0666 | IPC_CREAT);
    //msgid = msgget(1234, 0666 | IPC_CREAT | IPC_EXCL);
    //msgid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT | IPC_EXCL);
    //msgid = msgget(IPC_PRIVATE, 0666);
    //msgid = msgget(1234, 0666 | IPC_CREAT);
    //msgid = msgget(1234, 0);
    if (msgid == -1)
        ERR_EXIT("msgget");

    printf("msgget succ\n");
    printf("msgid=%d\n", msgid);
    return 0;
}

msgstat.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)


int main(void)
{
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
        ERR_EXIT("msgget");

    printf("msgget succ\n");
    printf("msgid=%d\n", msgid);
    
    struct msqid_ds buf;
    msgctl(msgid, IPC_STAT, &buf);
    printf("mode=%o\n", buf.msg_perm.mode);
    printf("bytes=%ld\n", buf.__msg_cbytes);
    printf("number=%d\n", (int)buf.msg_qnum);
    printf("msgmnb=%d\n", (int)buf.msg_qbytes);
    
    return 0;
}

makefile:
.PHONY:clean all
CC=gcc
CFLAGS=-Wall -g
BIN=msg_get msg_rmid msg_stat msg_set
all:$(BIN)
%.o:%.c
    $(CC) $(CFLAGS) -c $< -o $@
clean:
    rm -f *.o $(BIN)