⑴ 請教一個關於linux消息隊列的問題
一般使用步驟:
1. 用ftok產生一個key。
2. 調用msgget(使用key作為參數)產生一個隊列
3. 進程可以用msgsnd發送消息到這個隊列,相應的別的進程用msgrcv讀取。
這里需要注意msgsnd可能會失敗的兩個情況:
a) 可能被中斷打斷(包括msgsnd和msgrcv). 尤其是大流量應用中更容易出現. 比較安全的用法是判斷操作是否被中斷打斷,如果被打斷, 則需要繼續嘗試。
b) 消息隊列滿。產生這個錯誤,則需要考慮提高系統消息隊列規格,或者查看消息接收處是否有問題
4. msgctl函數可以用來刪除消息隊列
消息隊列產生之後,除非明確的刪除(可以用),產生的隊列會一直保留在系統中。linux下消息隊列的個數是有限的,注意不要泄露。如果 使用已經達到上限,msgget調用會失敗,產生的錯誤碼對應的提示信息為no space left on device.
注意點:
1.消息的類型 mtype 不需為非0值。如果使用0,則msgsnd會失敗,並得到」Invalid argument「錯誤。
2.msgflg為0表示阻塞等待,如果msgflg為IPC_NOWAIT表示非阻塞。
3.最好使用root許可權執行消息隊列,否則msgrcv 提示 "Permission denied"。
⑵ linux內核工作隊列怎麼工作的
Linux 2.6內核使用了不少工作隊列來處理任務,他在使用上和 tasklet最大的不同是工作隊列的函數可以使用休眠,而tasklet的函數是不允許使用休眠的。
工作隊列的使用又分兩種情況,一種是利用系統共享的工作隊列來添加自己的工作,這種情況處理函數不能消耗太多時間,這樣會影響共享隊列中其他任務的處理;另外一種是創建自己的工作隊列並添加工作。
(一)利用系統共享的工作隊列添加工作:
第一步:聲明或編寫一個工作處理函數
void my_func();
第二步:創建一個工作結構體變數,並將處理函數和參數的入口地址賦給這個工作結構體變數
DECLARE_WORK(my_work,my_func,&data); //編譯時創建名為my_work的結構體變數並把函數入口地址和參數地址賦給它;
如果不想要在編譯時就用DECLARE_WORK()創建並初始化工作結構體變數,也可以在程序運行時再用INIT_WORK()創建
struct work_struct my_work; //創建一個名為my_work的結構體變數,創建後才能使用INIT_WORK()
INIT_WORK(&my_work,my_func,&data); //初始化已經創建的my_work,其實就是往這個結構體變數中添加處理函數的入口地址和data的地址,通常在驅動的open函數中完成
第三步:將工作結構體變數添加入系統的共享工作隊列
schele_work(&my_work); //添加入隊列的工作完成後會自動從隊列中刪除
或schele_delayed_work(&my_work,tick); //延時tick個滴答後再提交工作
(二)創建自己的工作隊列來添加工作
第一步:聲明工作處理函數和一個指向工作隊列的指針
void my_func();
struct workqueue_struct *p_queue;
第二步:創建自己的工作隊列和工作結構體變數(通常在open函數中完成)
p_queu=create_workqueue("my_queue"); //創建一個名為my_queue的工作隊列並把工作隊列的入口地址賦給聲明的指針
struct work_struct my_work;
INIT_WORK(&my_work, my_func, &data); //創建一個工作結構體變數並初始化,和第一種情況的方法一樣
第三步:將工作添加入自己創建的工作隊列等待執行
queue_work(p_queue, &my_work);
//作用與schele_work()類似,不同的是將工作添加入p_queue指針指向的工作隊列而不是系統共享的工作隊列
第四步:刪除自己的工作隊列
destroy_workqueue(p_queue); //一般是在close函數中刪除
⑶ 如何用JAVA實現Linux上的消息隊列功能
下面來說說如何用不用消息隊列來進行進程間的通信,消息隊列與命名管回道有很多相似之處。有關命答名管道的更多內容可以參閱我的另一篇文章:Linux進程間通信——使用命名管道 一、什麼是消息隊列 消息隊列提供了一種從一個進程向另一個進程發送一個數
⑷ linux 進程通信方式 pipe無名管道 fifo有名管道 共享內存映射 socket 消息隊列
在Linux系統中,進程間的通信(IPC, Inter-Process Communication)主要通過四種機制實現:管道(pipe)、有名管道(fifo)、共享內存映射以及Unix域socket。這些方法各自適用於不同的場景,讓進程能夠有效地交換數據。
1. 管道(pipe):無名管道,由`pipe()`函數創建,適合於有血緣關系的進程間通信,如父子進程。它在內核中創建一個緩沖區,通過`filedes`參數傳遞給用戶進程,用於單向通信,數據寫滿後會阻塞。
2. 有名管道(fifo):解決無血緣關系進程間的通信,使用`mkfifo`創建,相當於磁碟上的一個文件,通過文件名訪問。它實質上是基於管道的,只是給管道起了個名字,讀寫需要進程都打開文件。
3. 共享內存映射(mmap):通過`mmap`函數將磁碟文件的一部分映射到內存,支持同步修改(share映射)和獨立修改(private映射)。這常用於進程間的數據傳遞,特別是許可權受限的情況下。
4. Unix域socket(socket):利用網路通信技術,適用於遠程進程間的通信,常用於伺服器-客戶端模型,數據按照協議解析。
消息隊列,雖然視頻中未提及,但它是另一種間接通信方式,類似於郵箱系統,接收方根據消息類型從中間體獲取信息。消息隊列提供了一種獨立於進程運行狀態的通信方式,寫入者無需關心接收者是否在讀取。
每種方法都有其優缺點,選擇哪種取決於具體的應用場景和性能需求。理解這些通信方式有助於編寫高效、可靠的多進程應用程序。