您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關如何分析Linux消息隊列編程,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
消息隊列,Unix的通信機制之一,可以理解為是一個存放消息(數據)容器。將消息寫入消息隊列,然后再從消息隊列中取消息,一般來說是先進先出的順序。可以解決兩個進程的讀寫速度不同(處理數據速度不同),系統耦合等問題,而且消息隊列里的消息哪怕進程崩潰了也不會消失。
最簡單的消息內存的使用流程
①ftok函數生成鍵值
②msgget函數創建消息隊列
③msgsnd函數往消息隊列發送消息
④msgrcv函數從消息隊列讀取消息
⑤msgctl函數進行刪除消息隊列
一個消息數據應該由以下一個結構體組成,舉個例子
struct mymesg{long int mtype; //類,消息隊列可以控制讀取相應類型的數據,這時就不一定是先進先出的順序了,文章后面會繼續介紹char mtext[size_t]; //數據,傳遞的數據存放在這里面};
每一個消息隊列都有一個對應的鍵值(key)相關聯(共享內存、信號量也同樣需要)。
所需頭文件#include
函數原型 key_t ftok(const char *path ,int id);
path為一個已存在的路徑名
id為0~255之間的一個數值,代表項目ID,自己取
返回值:成功返回鍵值(相當于32位的int)。出錯返回-1
例如:key_t key = ftok( “/tmp”, 66);
所需頭文件#include
函數原型 int msgget(key_t key,int flag);
key為ftok生成的鍵值
flag為所需要的操作和權限,可以用來控制創建一個消息隊列。
flag的值為IPC_CREAT:如果不存在key值的消息隊列,且權限不為0,則創建消息隊列,并返回一個消息隊列ID。如果存在,則直接返回消息隊列ID。
flag的值為 IPC_CREAT | IPC_EXCL:如果不存在key值的消息隊列,且權限不為0,則創建消息隊列,并返回一個消息隊列ID。如果存在,則產生錯誤。
返回值:成功返回消息隊列ID;出錯返回-1
例如:int id = msgget(key,IPC_CREAT|IPC_EXCL|0666);創建一個權限為0666(所有用戶可讀可寫,具體查詢linux權限相關內容)的消息隊列,并返回一個整形消息隊列ID,如果key值已經存在有消息隊列了,則出錯返回-1。
int id = msgget(key,IPC_CREAT|0666);創建一個權限為0666(所有用戶可讀可寫,具體查詢linux權限相關內容)的消息隊列,并返回一個消息隊列ID,如果key值已經存在有消息隊列了,則直接返回一個消息隊列ID。
所需頭文件#include
函數原型 int msgsnd(int msgid,const void *ptr,size_t nbytes,int flag);
msgid:為msgget返回的消息隊列ID值
ptr:為消息結構體mymesg指針
nbytes:為消息結構體mymesg里的字符數組mtext大小,sizeof(mtext)
flag:值可以為0、IPC_NOWAIT
為0時,當消息隊列滿時,msgsnd將會阻塞,直到消息能寫進消息隊列或者消息隊列被刪除。
為IPC_NOWAIT時,當消息隊列滿了,msgsnd函數將不會等待,會立即出錯返回EAGAIN
返回值:成功返回0;錯誤返回-1
例如:msgsnd(id,(void *)&ckxmsg,512,0);
所需頭文件#include
函數原型 ssize_t msgrcv(int msgid,void *ptr,size_t nbytes,long type,int flag);
msgid:為msgget返回的消息隊列ID值
ptr:為消息結構體mymesg指針
nbytes:為消息結構體mymesg里的字符數組mtext大小,sizeof(mtext)
type:在結構體mymesg里我們定義了一個long int mtype,用于分別消息的類型
type ==0 返回隊列中的第一個消息
type > 0 返回隊列中消息類型為type的第一個消息
type
flag:可以為0、IPC_NOWAIT、IPC_EXCEPT
為0時,阻塞式接收消息,沒有該類型的消息msgrcv函數一直阻塞等待
為IPC_NOWAIT時,如果沒有返回條件的消息調用立即返回,此時錯誤碼為ENOMSG
為IPC_EXCEPT時,與msgtype配合使用返回隊列中第一個類型不為msgtype的消息
返回值:成功返回消息數據部分的長度;錯誤返回-1
例如:msgrcv(id,(void *)&ckxmsg,512,1,0);
簡單的操作就是刪除消息隊列了,也可以獲取和改變消息隊列的狀態
所需頭文件#include
函數原型int msgctl(int msgid, int cmd, struct msqid_ds *buf);
msgid就是msgget函數返回的消息隊列ID
cmd有三個,常用刪除消息隊列的為IPC_RMID;IPC_STAT:取此隊列的msqid_ds結構,并將它存放在buf指向的結構中;IPC_SET:改變消息隊列的狀態,把buf所指的msqid_ds結構中的uid、gid、mode復制到消息隊列的msqid_ds結構內。(內核為每個消息隊列維護著一個結構,結構名為msqid_ds,這里就不講啦,里面存放著消息隊列的大小,pid,存放時間等一些參數)
buf就是結構體msqid_ds
返回值:成功返回0;錯誤返回-1
例如:msgctl(id,IPC_RMID,NULL);刪除id號的消息隊列
下面為一個簡單的程序,一個service和一個client,service往消息隊列里寫數據,client從消息隊列里讀數據,當service輸入QUIT時刪除消息隊列,并且倆程序都退出。
1.service.c
#include #include #include #include #include struct mymesg{ long int mtype; char mtext[512]; }; int main() { int id = 0; struct mymesg ckxmsg; key_t key = ftok("/tmp",66); id = msgget(key,IPC_CREAT | 0666); if(id == -1) { printf("create msg error \n"); return 0; } while(1) { char msg[512]; memset(msg,0,sizeof(msg)); ckxmsg.mtype = 1; printf("input message:"); fgets(msg,sizeof(msg),stdin); strcpy(ckxmsg.mtext,msg); if(msgsnd(id,(void *)&ckxmsg,512,0) { printf("send msg error \n"); return 0; } if(strncmp(msg,"QUIT",4) == 0) break; } if(msgctl(id,IPC_RMID,NULL) { printf("del msg error \n"); return 0; } return 0; }
2.client.c
#include #include #include #include #include struct mymesg{ long int mtype; char mtext[512]; }; int main() { int id = 0; struct mymesg ckxmsg; key_t key = ftok("/tmp",66); id = msgget(key,0666|IPC_CREAT); if(id == -1) { printf("open msg error \n"); return 0; } while(1) { if(msgrcv(id,(void *)&ckxmsg,512,1,0) { printf("receive msg error \n"); return 0; } printf("data:%s\n",ckxmsg.mtext); if(strncmp(ckxmsg.mtext,"QUIT",4) ==0) break; } return 0; }
上述就是小編為大家分享的如何分析Linux消息隊列編程了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。