1.消息隊列簡介
實現linux進程通信的方式有5種:
--信號(Singal)
--管道(Pipe)
linux提權,--消息隊列(Message)
--信號量(Semaphore)
每種進程通信方式實現方式和功能不一樣,帶來適用的場景也有所不同,消息隊列是鏈表隊列,它通過內核提供一個struct msqid_ds *msgque[MSGMNI]向量維護內核的一個消息隊列列表,因此linux系統支持的最大消息隊列數由msgque數組大小來決定,每一個msqid_ds表示一個消息隊列,并通過msqid_ds.msg_first、msg_last維護一個先進先出的msg鏈表隊列,當發送一個消息到該消息隊列時,把發送的消息構造成一個msg結構對象,并添加到msqid_ds.msg_first、msg_last維護的鏈表隊列,同樣,接收消息的時候也是從msg鏈表隊列尾部查找到一個msg_type匹配的msg節點,從鏈表隊列中刪除該msg節點,并修改msqid_ds結構對象的數據。
2.消息隊列的數據結構
kafka消息隊列、--1.struct msqid_ds *msgque[MSGMNI]向量:
msgque[MSGMNI]是一個msqid_ds結構的指針數組,每個msqid_ds結構指針代表一個系統消息隊列,msgque[MSGMNI]的大小為MSGMNI=128,也就是說系統最多有MSGMNI=128個消息隊列
--2.struct msqid_ds
一個消息隊列結構
struct msqid_ds 中主要數據成員介紹如下:
redis消息隊列原理。struct msqid_ds
{
struct ipc_perm msg_perm;
struct msg *msg_first; /*消息隊列頭指針*/
struct msg *msg_last; /*消息隊列尾指針*/
Redis消息隊列, __kernel_time_t msg_stime; /*最后一次插入消息隊列消息的時間*/
__kernel_time_t msg_rtime; /*最后一次接收消息即刪除隊列中一個消息的時間*/
__kernel_time_t msg_ctime;
struct wait_queue *wwait; /*發送消息等待進程隊列*/
struct wait_queue *rwait;
多線程消息隊列、 unsigned short msg_cbytes;
unsigned short msg_qnum; /*消息隊列中的消息個數*/
unsigned short msg_qbytes;
__kernel_ipc_pid_t msg_lspid; /*最后一次消息發送進程的pid*/
__kernel_ipc_pid_t msg_lrpid; /*最后一次消息發送進程的pid*/
linux有什么用?};
--3.struct msg 消息節點結構:
msqid_ds.msg_first,msg_last維護的鏈表隊列中的一個鏈表節點
struct msg
{
linux、msg *msg_next; /*下一個msg*/
long msg_type; /*消息類型*/
*msg_spot; /*消息體開始位置指針*/
msg_ts; /*消息體長度*/
message; /*消息體*/
linux實驗總結?}
--4.msgbuf消息內容結構:
msg 消息節點中的消息體,也是消息隊列使用進程(消息隊列發送接收進程)發送或者接收的消息
struct msgbuf
{
linux消息隊列自動銷毀? long mtype; --消息類型
char mtext[n];--消息內容
}
3.消息隊列的使用
--1.消息隊列Key的獲取:
redis消息隊列實現思路、 在程序中若要使用消息隊列,必須要能知道消息隊列key,因為應用進程無法直接訪問內核消息隊列中的數據結構,因此需要一個消息隊列的標識,讓應用進程知道當前操作的是哪個消息隊列,同時也要保證每個消息隊列key值的唯一性
----a.通過ftok函數獲取
key_t key;
key=ftok(".","a")
該函數通過一個路徑名稱映射出一個消息隊列key(我的理解是使用路徑映射的方式比較容易獲取一個唯一的消息隊列key)
關于linux基礎的個人總結、----b.直接定義key:
#define MSG_KEY 123456
自定義key的方式要注意避免消息隊列的重復。
--2.獲取或者打開一個消息隊列
----a.使用說明
redis消息隊列實現高并發、qid=msgget(key_t key, int msgflag)
--key: 消息隊列key
--msgflag:
IPC_PRIVATE:創建一個該進程獨占的消息隊列,其它進程不能訪問該消息隊列
IPC_CREAT:若消息隊列不存在,創建一個新的消息隊列,若消息隊列存在,返回存在的消息隊列
java 消息隊列、IPC_CREAT | IPC_EXCL: IPC_EXCL標志本身沒有多大意義,與IPC_CREAT一起使用,保證只創建新的消息隊列,若對應key的消息隊列已經存在,則返回錯誤
IPC_NOWAIT:小隊列以非阻塞的方式獲取(若不能獲取,立即返回錯誤)
----b.函數原因
------1)如果key==IPC_PRIVATE,則申請一塊內存,創建一個新的消息隊列(數據結構msqid_ds),將其初始化后加入到msgque向量表中的某個空位置處,返回標示符。
------2)在msgque向量表中找鍵值為key的消息隊列,如果沒有找到,結果有二:
msgflag表示不創建新的隊列,則錯誤返回。
msgflag表示要創建新的隊列(IPC_CREAT),則創建新消息隊列,創建過程如1)。
-------3)如果在msgque向量表中找到了鍵值為key的消息隊列,則有以下情況:
如果msgflg表示一定要創建新的消息隊列而且不允許有相同鍵值的隊列存在,則錯誤返回。
如果找到的隊列是不能用的或已經損壞的隊列,則錯誤返回。
認證和存取權限檢查,如果該隊列不允許msgflg要求的存取,則錯誤返回。
正常,返回隊列的標識符。
--3.發送一個消息到消息對列
----a.使用說明:
int msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
------msqid為消息隊列的qid
------msgp對應消息內容結構體指針
------msgsz消息的大小即msgp指針指向的消息結構體的大小
------msgflg消息標志
0:忽略該標志位,以阻塞的方式發送消息到消息隊列
IPC_NOWAIT:以非阻塞的方式發送消息,若消息隊列滿,函數立即返回。
------返回:
0: 成功
-1:非阻塞方式訪問滿消息隊列返回
EACCES:沒有該消息隊列寫權限
EFAULT:消息隊列地址無法獲取
EIDRM:消息隊列已經被刪除
EINTR:消息隊列等待寫入的時候被中斷
ENOMEM:內存不夠
----b.函數原理:
1)計算id = (unsigned int) msqid % MSGMNI,然后根據id在linux系統消息隊列向量msgque[MSGMNI]中查找對應的消息隊列,并進行認證檢查,合法性檢查
2)如果隊列已滿,以可中斷等待狀態(TASK_INTERRUPTIBLE)將當前進程掛起在wwait等待隊列(發送消息等待隊列)上(msgflag==0)。
3)否則 根據msgbuf的大小申請一塊空間,并在其上創建一個消息數據結構struct msg(內核空間),將消息緩沖區中的消息內容拷貝到該內存塊中消息頭的后面(從用戶空間拷貝到內核空間)。
4)將消息數據結構加入到消息隊列的隊尾,修改隊列msqid_ds的相應參數。
5)喚醒在該消息隊列的rwait進程隊列(讀等待進程隊列)上等待讀的進程,并返回。
--4.從消息隊列接收一個消息到msgbuf*
----a.使用說明
int msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,long msgtyp, int msgflg)
----msqid為消息隊列的qid
----msgp是接收到的消息將要存放的緩沖區
----msgsz是消息的大小
----msgtyp是期望接收的消息類型
----msgflg是標志
0:表示忽略
IPC_NOWAIT:如果消息隊列為空,不阻塞等待,返回一個ENOMSG
----返回
0:成功
-1:消息長度大于msgsz
EACCES:沒有該消息隊列讀權限
EFAULT:消息隊列地址無法獲取
EIDRM:消息隊列已經被刪除
EINTR:消息隊列等待寫入的時候被中斷
ENOMEM:內存不夠
----b.函數原理:
1)計算id = (unsigned int) msqid % MSGMNI,然后根據id在msgque[MSGMNI]中查找對應的消息隊列,并進行認證檢查,合法性檢查
2)根據msgtyp搜索消息隊列,情況有二:
----如果找不到所要的消息,則以可中斷等待狀態(TASK_INTERRUPTIBLE)將當前進程掛起在rwait等待隊列上
----如果找到所要的消息,則將消息從隊列中摘下,調整隊列msqid_ds參數,喚醒該消息隊列的wwait進程隊列上等待寫的進程,將消息內容拷貝到用戶空間的消息緩沖區msgp中,釋放內核中該消息所占用的空間,返回
--5.消息的控制
----a.使用說明:
int msgctl (int msqid, int cmd, struct msqid_ds *buf)
------msqid:為消息隊列的qid
------cmd:為該函數要對消息隊列執行的操作
IPC_STAT:取出消息隊列的msqid_ds結構體并將參數存入buf所指向的msqid_ds結構對象中
IPC_SET:設定消息隊列的msqid_ds 數據中的msg_perm 成員。設定的值由buf 指向的msqid_ds
結構給出。
IPC_EMID:將隊列從系統內核中刪除。
----buf:消息隊列msqid_ds結構體指針
----b.函數作用
對消息隊列進行設置以及相關操作,具體操作由cmd指定。
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态