Linux下訊息佇列學習筆記

來源:互聯網
上載者:User

訊息佇列是進程間通訊的一種方法,一開始我以為訊息佇列是類似一個管道,一頭串連一個進程、一頭串連另一個進程,只能由這兩個進程來進行互相的讀寫。其實這是錯的,訊息佇列是系統層面的,它不屬於某兩個進程,它是由系統維護的一個鏈表結構。對訊息佇列的讀寫就是一個對鏈表的操作,預設是在鏈表的一端寫資料,另一端讀資料(先進先出),進程也可以取指定某種訊息類型的訊息。

在一個進程裡建立了訊息佇列,且是可讀可寫的,那麼系統中的所有進程都可以對它進行讀寫操作。

1、開啟或建立一個訊息佇列

原型:int msgget(key_t key, int msgflg);
參數:
1)key :訊息佇列的key值。
2)msgflg:
IPC_CREAT:如果key對應的訊息佇列對象不存在,則建立;否則則進行開啟操作,返回0。
IPC_EXCL:如果key對應的訊息佇列對象不存在,則返回-1;否則則進行開啟操作,返回0。
許可權控制:0666表示可讀可寫,和上面的IPC_CREAT做邏輯或操作。
傳回值:
成功返回,建立的或開啟的訊息佇列的id。
失敗返回-1。

例子程式:test1.c

 代碼如下 複製代碼

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>

int main(void)
{
 int msgid;
 printf("this is test1!\n");
 
 msgid = msgget(1001, 0666|IPC_CREAT);
 printf("msgid = %d\n", msgid);
 
 return 0;
}

 

執行結果:

[root@server ~]# gcc -o test1 test1.c
[root@server ~]# ./test1
this is test1!
msgid = 32768
[root@server ~]# ipcs

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

------ Semaphore Arrays --------
key        semid      owner      perms      nsems    
0x00000000 0          root       600        1        

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages   
0x000003e9 32768      root       666        0            0        

  
從ipcs命令的結果可以知道,訊息佇列在建立它的進程退出後,還存在於系統中,說明訊息佇列是系統一層的,並不是屬於某個進程的。

2、設定訊息佇列屬性(包括刪除)

原型:int msgctl(int msqid, int cmd, struct msqid_ds *buf);
參數:
1)msqid:訊息佇列的id。
2)cmd:執行的控制命令。
IPC_STAT:讀取訊息佇列屬性。取得此隊列的msqid_ds 結構,並將其存放在buf指向的結構中。
IPC_SET :設定訊息佇列屬性。
IPC_RMID:刪除訊息佇列。
IPC_INFO:讀取訊息佇列基本情況。此命令等同於 ipcs 命令。

例子程式:test2.c

 代碼如下 複製代碼

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>

int main(void)
{
 int i;
 printf("this is test2!\n");
 i = msgctl(32768, IPC_RMID, NULL);//這裡已經知道訊息id等於32768
 if (0 == i)
 {
  printf("msq deleted!\n");
 }
 return 0;
}

執行結果:

[root@server ~]# gcc -o test2 test2.c
[root@server ~]# ./test2
this is test2!
msq deleted!
[root@server ~]# ipcs

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

------ Semaphore Arrays --------
key        semid      owner      perms      nsems    
0x00000000 0          root       600        1        

------ Message Queues --------

key        msqid      owner      perms      used-bytes   messages
原有的訊息佇列被刪除了。

3、向訊息佇列寫/讀訊息

原型: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);

參數:
1)msqid:訊息佇列的id。
2)msgp:指向訊息緩衝區的指標,該指標指向如下的一個使用者可定義的通用結構。

struct mymsg {
  long mtype;
  char mbuf[1024];
};
3)msgsz:訊息的大小。
4)msgflg:可以為IPC_NOWAIT或0,表示操作是阻塞式的還是非阻塞式的。
設定為IPC_NOWAIT,在msgsnd()中,如果訊息佇列已經滿了,則不會阻塞,立即返回-1(EAGAIN)。
在msgrcv()中,如果訊息佇列為空白,則不做等待,立即返回-1(ENOMSG)。
設定為0,在msgsnd()中,進程阻塞直到(a)有空間可以容納要發送的訊息;或(b)從系統中刪除了此隊列(返回EIDRM);或(c)捕捉到一個訊號,並從訊號處理常式返回(返回EINTR)。
在msgrcv()中,進程阻塞直到(a)有了指定類型的訊息;或(b)從系統中刪除了此隊列(返回EIDRM);或(c)捕捉到一個訊號並從訊號處理常式返回(返回EINTR)。
5)msgtype:用於msgrcv()函數,指定訊息的類型。相當於區分訊息類別的標誌位。
msgtype = 0,返回訊息佇列中的第一個訊息。

傳回值:
msgsnd(),成功返回0,出錯返回-1。
msgrcv(),成功返回訊息資料部分的長度,出錯返回-1。

例子程式:test3.c

 代碼如下 複製代碼

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <errno.h>

typedef struct
{
 long mtype;
 char mbuf[1024];
}mymsg;

int main(void)
{
 int i;
 int msgid1, msgid2;
 mymsg message1, message2, message3;
 
 printf("this is test3!\n");
 
 msgid1 = msgget(1002, 0666|IPC_CREAT);//key 1002
 if (msgid1 < 0)
 {
  printf("create key=1002 error, errno=%d\n", errno);
  exit(-1);
 }
 msgid2 = msgget(1003, 0666|IPC_CREAT);//key 1003
 if (msgid2 < 0)
 {
  printf("create key=1003 error, errno=%d\n", errno);
  exit(-1);
 }

 //初始化
 message1.mtype = 1;//設定一個訊息類型
 memcpy(message1.mbuf, "first message", 13);
 message3.mtype = 1;
 memcpy(message3.mbuf, "hello test4.", 12);
 
 //test3進程在msgid1上發訊息
 i = msgsnd(msgid1, (void *)&message1, strlen(message1.mbuf)+1, 0);
 if (i < 0)
 {
  printf("send message1 error, errno=%d\n", errno);
  exit(-1);
 }
 
 //test3進程從msgid1取訊息,存到message2中
 i = msgrcv(msgid1, (void *)&message2, 1024, 0, 0);
 if (i < 0)
 {
  printf("rev error, errno=%d\n", errno);
  exit(-1);
 }
 else
 {
  //顯示取出的訊息
  printf("%s\n", message2.mbuf);
 }

 //test3進程在msgid2上發訊息
 i = msgsnd(msgid2, (void *)&message3, strlen(message3.mbuf)+1, 0);
 if (i < 0)
 {
  printf("send message3 error, errno=%d\n", errno);
  exit(-1);
 }
 
 return 0;
}

例子程式:test4.c

 代碼如下 複製代碼

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <errno.h>

typedef struct
{
 long mtype;
 char mbuf[1024];
}mymsg;

int main(void)
{
 int i, j;
 mymsg message;
 
 printf("this is test4!\n");
 
 i = msgget(1003, 0666|IPC_CREAT);
 if (i < 0)
 {
  printf("create key=1003 error, errno=%d\n", errno);
  exit(-1);
 }
 
 //test4進程在key=1003的訊息佇列上取訊息
 j = msgrcv(i, (void *)&message, 1024, 0, 0);
 if (j < 0)
 {
  printf("rev error, errno=%d\n", errno);
  exit(-1);
 }
 else
 {
  //顯示取出的訊息
  printf("%s\n", message.mbuf);
 }
 
 return 0;
}

開兩個終端,一個執行test3,另一個執行test4。
test3執行結果:

 代碼如下 複製代碼
[root@server ~]# ./test3
this is test3!
first message

ipcs命令能看到key=1003的訊息佇列中有一條訊息,使用了13位元組長度。

 代碼如下 複製代碼

key        msqid      owner      perms      used-bytes   messages
0x000003ea 98305      root       666        0            0      
0x000003eb 131074     root       666        13           1      
test4執行結果:

[root@server ~]# ./test4
this is test4!
hello test4.

以上。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.