1. 程式人生 > >System V 訊息佇列

System V 訊息佇列

一、System V 訊息佇列

有一個佇列,佇列存放各種訊息。每個程序可以把資料封存在訊息中,再放入佇列。每個程序都可以拿到訊息佇列,再從中取出/放入訊息。

訊息佇列也有管道一樣的不足,就是每個訊息的最大長度是有上限的(MSGMAX),每個訊息佇列的總的位元組數是有上限的(MSGMNB),系統上訊息佇列的總數也有一個上限(MSGMNI)。

 

二、msgget函式

. msgget函式原型:用於建立一個新的訊息佇列或訪問一個已存在的訊息佇列

#include <sys/msg.h>
int msgget(key_t key, int msgflg);

注意:

msgid = msgget(1234, 0);  //按照原有許可權開啟該訊息佇列

1. 測試程式碼:

#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int msgid;
    msgid = msgget(1234, 0666 | IPC_CREAT);
    if(msgid == -1)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
    printf("msgget succ\n");
    printf("msgget = %d\n", msgid);
    return 0;
}

輸出結果:


2. 測試程式碼:

#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int msgid;
    msgid = msgget(IPC_PRIVATE, 0666);
    if (msgid == -1)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
    printf("msgget succ\n");
    printf("msgget = %d\n", msgid);
    return 0;
}

 輸出結果:


3. 測試程式碼:

#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int msgid;
    msgid = msgget(1234, 0400 | IPC_CREAT);
    if (msgid == -1)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
    printf("msgget succ\n");
    printf("msgget = %d\n", msgid);
    msgid = msgget(1234, 0600 | IPC_CREAT);
    if (msgid == -1)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }    
    return 0;
}

 輸出結果:

 

三、msgsnd函式 

#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

int main(int argc, const char *argv[])
{
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
    printf("msggget succ\n");
    printf("msgid = %d\n", msgget);
    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("msg_qnum = %d\n", (int)buf.msg_qnum);
    printf("msg_qbytes = %d\n", (int)buf.msg_qbytes);
    return 0;    
}

 輸出結果:


#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

int main(int argc, const char *argv[])
{
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
    {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
    printf("msggget succ\n");
    printf("msgid = %d\n", msgget);
    struct msqid_ds buf;
    sscanf("666", "%o", (unsigned int *)&buf.msg_perm.mode);
    msgctl(msgid, IPC_SET, &buf);
    return 0;    
}

 輸出結果:

四、msgsnd函式

msgsnd函式原型:把一條訊息新增到訊息佇列中

#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

引數:

  • msgid:有msgget函式返回的訊息佇列標識碼
  • msgp:是一個指標,指標指向準備傳送的訊息
  • msgsz:是msgp指向的訊息長度,這個長度不含儲存訊息型別的那個long int長整型
  • msgflg:控制著當前訊息佇列滿或到達系統上限時將要發生的事情

1. 測試程式碼:

程式1:

//msg_stat.c
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

int main(int argc, const char *argv[])
{
	int msgid;
	msgid = msgget(1234, 0);
	if (msgid == -1)
	{
		perror("msgget");
		exit(EXIT_FAILURE);
	}
	printf("msggget succ\n");
	printf("msgid = %d\n", msgget);
	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("msg_qnum = %d\n", (int)buf.msg_qnum);
	printf("msg_qbytes = %d\n", (int)buf.msg_qbytes);
	return 0;	
}

程式2:

#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

int main(int argc, char *argv[])
{
	if (argc != 3)
	{
		fprintf(stderr, "Usage:%s<bytes> <type>\n", argv[0], argv[1]);
		exit(EXIT_FAILURE);
	}
	int len = atoi(argv[1]);
	int type = atoi(argv[2]);
	int msgid;
	msgid = msgget(1234, 0);
	if (msgid == -1)
	{
		perrro("msgget");
		exit(EXIT_FAILURE);
	}
	struct msgbuf *ptr;
	ptr(struct msgbuf*) malloc(sizeof(long) + len);
	ptr->mtype = type;
	if (msgsnd(msgid, ptr, len, 0) < 0) //阻塞方式
	{
		perrro("msgsnd");
		exit(EXIT_FAILURE);
	}
	return 0;	
}

輸出結果: