Linux 消息队列 msgsnd msgrcv 使用

// 编写一个demo用于测试消息队列函数的使用方法。
// demo的参考来源,使用man msgsnd,查看man文档,里面就有使用的方式,进行更改调试。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

/* 这个结构体的内容是自定义的,可以是任何类型的结构体
 * 第一个成员必须是long类型。
 * 后面的成员变量自己定义
 */
struct msgbuf {
    long mtype;
    char mtext[80];
};

static void
usage(char *prog_name, char *msg)
{
    if (msg != NULL)
        fputs(msg, stderr);

    fprintf(stderr, "Usage: %s [options]\n", prog_name);
    fprintf(stderr, "Options are:\n");
    fprintf(stderr, "-s        send message using msgsnd()\n");
    fprintf(stderr, "-r        read message using msgrcv()\n");
    fprintf(stderr, "-t        message type (default is 1)\n");
    fprintf(stderr, "-k        message queue key (default is 1234)\n");
    fprintf(stderr, "-q        remove message queue by key\n");
    exit(EXIT_FAILURE);
}

static void
send_msg(int qid, int msgtype)
{
    struct msgbuf msg;
    time_t t;

    msg.mtype = msgtype;

    time(&t);
    snprintf(msg.mtext, sizeof(msg.mtext), "a message at %s\nnice to meet you! Tao",
            ctime(&t));
	/* 发送数据,数据长度不包括第一个成员变量
	 * IPC_NOWAIT:当队列满时,不阻塞
	 */
    if (msgsnd(qid, &msg, sizeof(msg.mtext),
                IPC_NOWAIT) == -1) {
        perror("msgsnd error");
        exit(EXIT_FAILURE);
    }
    printf("sent: %s\n", msg.mtext);
}

static void
get_msg(int qid, int msgtype)
{
    struct msgbuf msg;
	/*
	 * 接收数据,数据长度不包括定义结构体的第一个变量
	 * MSG_NOERROR: 发送的消息超过size,把消息截断,截断部分被丢弃,且不同之发送进程
	 * IPC_NOWAIT: 队列没有消息时,不阻塞
	 * msgtype: 0 :  接收第一个消息
	 *          >0:  接收类型等于msgtype的第一个消息
	 *          <0:  接收类型等于或者小于msgtype绝对之的第一个消息
         * 发送和接收的msgtype不一样的话,也接收不到数据。
	 */
    if (msgrcv(qid, &msg, sizeof(msg.mtext), msgtype,
               MSG_NOERROR | IPC_NOWAIT) == -1) {
        if (errno != ENOMSG) {
            perror("msgrcv");
            exit(EXIT_FAILURE);
        }
        printf("No message available for msgrcv()\n");
    } else
        printf("message received: %s\n", msg.mtext);
}

static void
remove_msg(int qid)
{
    if (msgctl(qid, IPC_RMID, 0)) {
        if (errno != ENOMSG) {
            perror("msgctl");
            exit(EXIT_FAILURE);
        }
        printf("rm message fail\n");
    } else
        printf("rm message success\n");
}

int
main(int argc, char *argv[])
{
    int qid, opt;
    int mode = 0;               /* 1 = send, 2 = receive */
    int msgtype = 1;
    int msgkey = 0x1234;
	int rm_qid;

    while ((opt = getopt(argc, argv, "srt:k:q:")) != -1) {
        switch (opt) {
        case 's':
			// 发送
            mode = 1;
            break;
        case 'r':
			// 接收
            mode = 2;
            break;
        case 't':
			// 更改类型
            msgtype = atoi(optarg);
            if (msgtype <= 0)
                usage(argv[0], "-t option must be greater than 0\n");
            break;
        case 'k':
			// 更改key值
            msgkey = atoi(optarg);
            break;
	case 'q':      // 删除
	    rm_qid = atoi(optarg);
	    mode = 3;
	    break;
        default:
            usage(argv[0], "Unrecognized option\n");
        }
    }

    if (mode == 0)
        usage(argv[0], "must use either -s or -r option\n");
	// 获取或者创建一个key,并设置权限
    qid = msgget(msgkey, IPC_CREAT | 0666);

    if (qid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
	else {
		printf("msgget success, id = %d\n", qid);
	}
	
    if (mode == 1)
        send_msg(qid, msgtype); // 接收
	else if (mode == 2)
        get_msg(qid, msgtype);  // 发送
	else if (mode == 3)
		remove_msg(rm_qid);     // 根据id进行删除

    exit(EXIT_SUCCESS);
}
ipcs进行查看

ipcrm -q id进行删除

消息队列为空
tao@T:~$ ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

#发送消息队列
tao@T:~$ ./a.out -s
msgget success, id = 7
sent: a message at Sun Sep 18 15:41:09 2022

nice to meet you! Tao
tao@T:~$ ipcs
# 已经创建了消息队列,分配了key,msqid,已经权限,还有使用的used-bytes,使用了80字节
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x00001234 7          tao        666        80           1
# 共享内存是空
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
# 信号量是空
------ Semaphore Arrays --------
key        semid      owner      perms      nsems

tao@T:~$ ./a.out -r
msgget success, id = 7
message received: a message at Sun Sep 18 15:41:09 2022

nice to meet you! Tao
tao@T:~$ ipcs
# 读取之后,used-bytes的字数为空
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x00001234 7          tao        666        0            0

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
# 根据id值,删除队列
tao@T:~$ ./a.out -q 7
msgget success, id = 7
rm message success
tao@T:~$ ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
posted @ 2022-09-18 15:53  SuperTao1024  阅读(896)  评论(0编辑  收藏  举报