那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

簡單了解一下進(jìn)程間通信的幾種實(shí)現(xiàn)方式

strongerHuang ? 來源:嵌入式藝術(shù) ? 作者:DonGe ? 2022-10-28 09:01 ? 次閱讀

在系統(tǒng)中,隨著我們的進(jìn)程越來越多,難免不同進(jìn)程之間要互相傳輸一些數(shù)據(jù),那么這個時候該怎么辦呢?

下面主要簡單了解一下,進(jìn)程間通信(InterProcess Communication,IPC)的幾種實(shí)現(xiàn)方式!

1、管道模型

管道模型與軟件生命周期模型——瀑布模型(Waterfall Model)很相似。 所謂的瀑布模型,其實(shí)就是將整個軟件開發(fā)過程分成多個階段,往往是上一個階段完全做完,才將輸出結(jié)果交給下一個階段。 74e3f84a-565b-11ed-a3b6-dac502259ad0.png

還記得咱們最初學(xué) Linux 命令的時候,有下面這樣一行命令:

ps -ef | grep 關(guān)鍵字 | awk '{print $2}' | xargs kill -9

這里面的豎線“|”就是一個管道。它會將前一個命令的輸出,作為后一個命令的輸入。

從管道的這個名稱可以看出來,管道是一種單向傳輸數(shù)據(jù)的機(jī)制,它其實(shí)是一段緩存,里面的數(shù)據(jù)只能從一端寫入,從另一端讀出。如果想互相通信,我們需要創(chuàng)建兩個管道才行。 管道又可以分為匿名管道和命名管道!

1.1 匿名管道

如上命令:

ps -ef | grep 關(guān)鍵字 | awk '{print $2}' | xargs kill -9
匿名管道:用"|” 表示的管道,意思就是這個類型的管道沒有名字,用完了就銷毀了。豎線代表的管道隨著命令的執(zhí)行自動創(chuàng)建、自動銷毀。用戶甚至都不知道自己在用管道這種技術(shù),就已經(jīng)解決了問題。

1.2 命名管道

命名管道,這個類型的管道需要通過 mkfifo 命令顯式地創(chuàng)建。

mkfifo donge#建立一個管道
donge就是這個管道的名稱。管道以文件的形式存在,這也符合 Linux 里面一切皆文件的原則。

下面我們看一下文件類型
ls -l
prw-rw-r-- 1 dong dong     0 Sep 28 17:09 donge
可以看到,這個文件的類型是 p,就是 pipe 的意思。

往管道中寫入數(shù)據(jù)
echo "hello world" > donge
這個時候,管道里面的內(nèi)容沒有被讀出,這個命令就是停在這里的,即進(jìn)程被堵塞。

這說明當(dāng)一個項(xiàng)目組要把它的輸出交接給另一個項(xiàng)目組做輸入,當(dāng)沒有交接完畢的時候,前一個項(xiàng)目組是不能撒手不管的。

重新打開一個終端,讀出管道數(shù)據(jù)

cat < hello 
hello world
一方面,我們能夠看到,管道里面的內(nèi)容被讀取出來,打印到了終端上; 另一方面,echo 那個命令正常退出了,也即交接完畢,前一個項(xiàng)目組就完成了使命,可以解散了。

管道通信,我們可以看出,瀑布模型的開發(fā)流程效率比較低下,因?yàn)閳F(tuán)隊(duì)之間無法頻繁地溝通。而且,管道的使用模式,也不適合進(jìn)程間頻繁的交換數(shù)據(jù)

2、消息隊(duì)列

7502a07e-565b-11ed-a3b6-dac502259ad0.png

消息隊(duì)列可以理解為發(fā)郵件,每一封郵件都視為一個獨(dú)立的數(shù)據(jù)單元,也就是消息體,每個消息體都是固定大小的存儲塊,在字節(jié)流上不連續(xù)。

這個消息結(jié)構(gòu)的定義我寫在下面了。這里面的類型 type 和正文 text 沒有強(qiáng)制規(guī)定,只要消息的發(fā)送方和接收方約定好即可。

struct msg_buffer {
    long mtype;
    char mtext[1024];
};

2.1 創(chuàng)建消息隊(duì)列

消息隊(duì)列的創(chuàng)建,需要用到msgget函數(shù)

int msgget(key_t key, int msgflg);

key:該參數(shù)是消息隊(duì)列的唯一標(biāo)識,由ftok生成。

msgflg:取值有以下幾個選擇:IPC_CREAT、IPC_EXCL ,這兩個參數(shù)詳細(xì)的作用可以man msgflg看詳細(xì)介紹。

返回值:返回一個近乎唯一的Message queue id

那么,key是如何由ftok生成的呢?

我們可以指定一個文件,調(diào)用ftok ,它會根據(jù)這個文件的 inode,生成一個近乎唯一的 key。

key_t ftok(const char *pathname, int proj_id);

pathname:文件信息,必須指定在一個存在的,可訪問的文件

proj_id:8bit的數(shù)據(jù),0-255隨意設(shè)定

這樣就可以獲得一個近乎唯一的key了!

只要在這個消息隊(duì)列的生命周期內(nèi),這個文件不要被刪除就可以了。只要不刪除,無論什么時刻,再調(diào)用 ftok,也會得到同樣的 key。

綜上,創(chuàng)建一個消息隊(duì)列只需兩步:

①:ftok生成一個key

②:msgget生成一個消息隊(duì)列的ID

如下:

#include 
#include 
#include 
 
 
int main() {
  int messagequeueid;
  key_t key;
 
 
  if((key = ftok("/root/messagequeue/messagequeuekey", 1)) < 0)
  {
      perror("ftok error");
      exit(1);
  }
 
 
  printf("Message Queue key: %d.
", key);
 
 
  if ((messagequeueid = msgget(key, IPC_CREAT|0777)) == -1)
  {
      perror("msgget error");
      exit(1);
  }
 
 
  printf("Message queue id: %d.
", messagequeueid);
}

ftok要指定一個存在的文件,所以我們在執(zhí)行之前,需要創(chuàng)建該文件。

查看消息隊(duì)列

System V IPC 體系有一個統(tǒng)一的命令行工具:ipcmk,ipcs 和 ipcrm 用于創(chuàng)建、查看和刪除 IPC 對象。

查看創(chuàng)建的IPC對象:ipcs -q

dong@ubuntu:~//Interprocess_Communication$ ipcs 

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x01110005 0          dong       777        0            0           

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

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

2.2 發(fā)送消息

消息隊(duì)列發(fā)送消息,主要調(diào)用msgsnd 函數(shù)

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

msqid:該參數(shù)是msgget所得到的message queue 的 id

msgp:消息結(jié)構(gòu)體

struct msg_buffer {
    long mtype;
    char mtext[1024];
};

msgsz:表示消息結(jié)構(gòu)體中,mtext最大長度

msgflg:一位掩碼,可取值有:IPC_NOWAIT、MSG_COPY、MSG_EXCEPT、MSG_NOERROR,取值說明可見man msgsnd

2.3 接收消息

消息隊(duì)列接收消息,主要調(diào)用msgrcv 函數(shù)

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);

msqid:該參數(shù)是msgget所得到的message queue 的 id

msgp:消息結(jié)構(gòu)體

msgsz:可接收數(shù)據(jù)最大長度

msgflg:一位掩碼,可取值有:IPC_NOWAIT、MSG_COPY、MSG_EXCEPT、MSG_NOERROR,取值說明可見man msgsnd

有了消息這種模型,兩個進(jìn)程之間的通信就像咱們平時發(fā)郵件一樣,你來一封,我回一封,可以頻繁溝通了。

3、共享內(nèi)存

7514d0aa-565b-11ed-a3b6-dac502259ad0.png

怎么理解共享內(nèi)存呢?

我們知道每個進(jìn)程都有自己獨(dú)立的虛擬內(nèi)存空間,不同的進(jìn)程的虛擬內(nèi)存空間映射到不同的物理內(nèi)存中去。這個進(jìn)程訪問 A 地址和另一個進(jìn)程訪問 A 地址,其實(shí)訪問的是不同的物理內(nèi)存地址,對于數(shù)據(jù)的增刪查改互不影響。

但是,咱們是不是可以變通一下,拿出一塊虛擬地址空間來,映射到相同的物理內(nèi)存中。這樣這個進(jìn)程寫入的東西,另外一個進(jìn)程馬上就能看到了,都不需要拷貝來拷貝去,傳來傳去。

相比于消息隊(duì)列,共享內(nèi)存的優(yōu)勢在哪里呢?

大數(shù)據(jù)傳輸:如果批量的大數(shù)據(jù)進(jìn)行傳輸,使用郵件的方式,來去發(fā)送不及時,并且大小也有限制

實(shí)時性:用共享內(nèi)存,其可以大大節(jié)省通信時間

3.1 創(chuàng)建共享內(nèi)存

我們可以創(chuàng)建一個共享內(nèi)存,調(diào)用 shmget。

int shmget(key_t key, size_t size, int shmflg);

key:和 msgget 里面的 key 一樣,都是唯一定位一個共享內(nèi)存的對象

size:共享內(nèi)存的大小

shmflg:其值可以取:IPC_CREAT、IPC_EXCL、SHM_HUGETLB、SHM_HUGE_2MB等

返回值:共享內(nèi)存的唯一ID

創(chuàng)建完畢之后,我們可以通過 ipcs 命令查看這個共享內(nèi)存。

#ipcs --shmems
 
------ Shared Memory Segments ------ --------
key        shmid    owner perms    bytes nattch status
0x00000000 19398656 marc  600    1048576 2      dest

3.2 訪問共享內(nèi)存

接下來,如果一個進(jìn)程想要訪問這一段共享內(nèi)存,需要將這個內(nèi)存加載到自己的虛擬地址空間的某個位置,通過 shmat 函數(shù),就是 attach 的意思。

void *shmat(int shmid, const void *shmaddr, int shmflg);

shmid:標(biāo)識一個共享內(nèi)存段的唯一ID

shmaddr:就是要指定 attach 到這個地方。但是這個地址的設(shè)定難度比較大,除非對于內(nèi)存布局非常熟悉,否則可能會 attach到一個非法地址。所以,通常的做法是將 shmaddr設(shè)為 NULL,讓內(nèi)核選一個合適的地址。

shmflg:一位掩碼,可取值:SHM_EXEC、SHM_RDONLY、SHM_REMAP。

返回值:為所連接的實(shí)際地址

3.3 關(guān)閉共享內(nèi)存

如果共享內(nèi)存使用完畢,可以通過 shmdt 解除綁定,然后通過 shmctl,將 cmd 設(shè)置為 IPC_RMID,從而刪除這個共享內(nèi)存對象。

int shmdt(void *addr); 
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmdt的參數(shù)addr:為shmat的返回值,表示卸載一片共享內(nèi)存

shmctl的參數(shù):

shm_id:shmget的返回值,為共享內(nèi)存的唯一ID

cmd:取值有:IPC_STAT、IPC_RMID等,見:man shmctl

buf:共享內(nèi)存管理結(jié)構(gòu)體。

3.4 信號

這里你是不是有一個疑問,如果兩個進(jìn)程 attach 同一個共享內(nèi)存,大家都往里面寫東西,很有可能就沖突了。例如兩個進(jìn)程都同時寫一個地址,那先寫的那個進(jìn)程會發(fā)現(xiàn)內(nèi)容被別人覆蓋了。

所以,這里就需要一種保護(hù)機(jī)制,使得同一個共享的資源,同時只能被一個進(jìn)程訪問。在 System V IPC 進(jìn)程間通信機(jī)制體系中,早就想好了應(yīng)對辦法,就是信號量(Semaphore)。因此,信號量和共享內(nèi)存往往要配合使用。

信號量和共享內(nèi)存都比較復(fù)雜,兩者還要結(jié)合起來用,就更加復(fù)雜,它們內(nèi)核的機(jī)制就更加復(fù)雜。這一節(jié)我們先不講。

4、信號

上面講的進(jìn)程間通信的方式,都是常規(guī)狀態(tài)下的工作模式,對應(yīng)到咱們平時的工作交接,收發(fā)郵件、聯(lián)合開發(fā)等,其實(shí)還有一種異常情況下的工作模式。

例如出現(xiàn)線上系統(tǒng)故障,這個時候,什么流程都來不及了,不可能發(fā)郵件,也來不及開會,所有的架構(gòu)師、開發(fā)、運(yùn)維都要被通知緊急出動。所以,7 乘 24 小時不間斷執(zhí)行的系統(tǒng)都需要有告警系統(tǒng),一旦出事情,就要通知到人,哪怕是半夜,也要電話叫起來,處理故障。

信號可以在任何時候發(fā)送給某一進(jìn)程,進(jìn)程需要為這個信號配置信號處理函數(shù)。

Linux所支持的異常信號如下:

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

當(dāng)某個信號發(fā)生的時候,就默認(rèn)執(zhí)行這個函數(shù)就可以了。這就相當(dāng)于咱們運(yùn)維一個系統(tǒng)應(yīng)急手冊,當(dāng)遇到什么情況,做什么事情,都事先準(zhǔn)備好,出了事情照著做就可以了。

有點(diǎn)類似于異常中斷……






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • IPC
    IPC
    +關(guān)注

    關(guān)注

    3

    文章

    352

    瀏覽量

    52068
  • 信號量
    +關(guān)注

    關(guān)注

    0

    文章

    53

    瀏覽量

    8373
  • 虛擬內(nèi)存
    +關(guān)注

    關(guān)注

    0

    文章

    77

    瀏覽量

    8084

原文標(biāo)題:進(jìn)程間通信的幾種實(shí)現(xiàn)方式

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Linux進(jìn)程如何實(shí)現(xiàn)共享內(nèi)存通信

    這次我們來講一下Linux進(jìn)程通信中重要的通信方式:共享內(nèi)存作為Linux軟件開發(fā)攻城獅,進(jìn)程
    發(fā)表于 04-26 17:14 ?711次閱讀

    Linux進(jìn)程通信方式-管道

    Linux進(jìn)程通信方式-管道分享到: 本文關(guān)鍵字: linux 管道通信,linux
    發(fā)表于 08-29 15:29

    Linux進(jìn)程通信

    華清遠(yuǎn)見嵌入式linux學(xué)習(xí)資料《Linux進(jìn)程通信》,通過前面的學(xué)習(xí),讀者已經(jīng)知道了進(jìn)程
    發(fā)表于 09-04 10:07

    常用的進(jìn)程通信主要有哪幾種方式

    ;常用的進(jìn)程通信主要有以下幾種方式:1.消息隊(duì)列;2. socket(本地socket和INETsocket)3.管道(有名管道和無名管道
    發(fā)表于 11-08 07:38

    進(jìn)程通信方式有哪些?

    進(jìn)程通信方式有哪些?
    發(fā)表于 12-24 06:46

    哪些方式可以實(shí)現(xiàn)Linux系統(tǒng)進(jìn)程通信

    哪些方式可以實(shí)現(xiàn)Linux系統(tǒng)進(jìn)程通信?進(jìn)程
    發(fā)表于 12-24 06:38

    進(jìn)程幾種狀態(tài)?

    文章目錄操作系統(tǒng)進(jìn)程和線程什么是進(jìn)程?什么是線程?進(jìn)程和線程有什么區(qū)別?何時使用多進(jìn)程,何時使用多線程?進(jìn)程
    發(fā)表于 12-24 07:16

    請問一下plc可以實(shí)現(xiàn)無線通信嗎?有幾種方式?

    請問一下plc可以實(shí)現(xiàn)無線通信嗎?有幾種方式?
    發(fā)表于 05-09 17:23

    進(jìn)程通信之Linux進(jìn)程通信概述

    人們現(xiàn)在廣泛使用的手機(jī)等方式。本章就是講述如何建立這些不同的通話方式,就像人們有多種通信方式樣。 Linux
    發(fā)表于 10-18 16:21 ?0次下載

    進(jìn)程與線程通信方式

    進(jìn)程通信則不同,它的數(shù)據(jù)空間的獨(dú)立性決定了它的通信相對比較復(fù)雜,需要通過操作系統(tǒng)。以前進(jìn)程
    的頭像 發(fā)表于 04-09 15:58 ?8970次閱讀
    <b class='flag-5'>進(jìn)程</b><b class='flag-5'>間</b>與線程<b class='flag-5'>間</b>的<b class='flag-5'>通信</b><b class='flag-5'>方式</b>

    使用MQTT作為進(jìn)程通信方式

    小編對Linux這塊的實(shí)際開發(fā)經(jīng)驗(yàn)雖然還不是很足,但也知道進(jìn)程通信有那么幾種方式:管道、消息
    的頭像 發(fā)表于 10-22 12:09 ?6255次閱讀
    使用MQTT作為<b class='flag-5'>進(jìn)程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b>的<b class='flag-5'>方式</b>

    進(jìn)程通信的機(jī)制有哪些

    比較難,Linux內(nèi)核提供了多種進(jìn)程通信的機(jī)制。 同進(jìn)程的不同模塊(譬如不同的函數(shù))之間進(jìn)行通信
    的頭像 發(fā)表于 07-21 11:23 ?993次閱讀
    <b class='flag-5'>進(jìn)程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b>的機(jī)制有哪些

    常見的進(jìn)程通信方式

    進(jìn)程通信 如果兩個進(jìn)程,想要知道對方在干嘛,或者進(jìn)行協(xié)調(diào)運(yùn)行,就需要進(jìn)程
    的頭像 發(fā)表于 10-08 15:48 ?1393次閱讀
    常見的<b class='flag-5'>進(jìn)程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b><b class='flag-5'>方式</b>

    進(jìn)程通信方式總結(jié)

    進(jìn)程通信(IPC): 進(jìn)程通信方式有很多,這里
    的頭像 發(fā)表于 11-09 09:25 ?812次閱讀
    <b class='flag-5'>進(jìn)程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b><b class='flag-5'>方式</b>總結(jié)

    如何實(shí)現(xiàn)套linux進(jìn)程通信的機(jī)制

    我們知道linux的進(jìn)程通信的組件有管道,消息隊(duì)列,socket, 信號量,共享內(nèi)存等。但是我們?nèi)绻约?b class='flag-5'>實(shí)現(xiàn)一套進(jìn)程
    的頭像 發(fā)表于 11-10 14:56 ?682次閱讀
    如何<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>一</b>套linux<b class='flag-5'>進(jìn)程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b>的機(jī)制
    真人百家乐视频赌博| 网上百家乐官网娱乐场| 百家乐天天赢钱| 皇冠娱乐场| 沙巴百家乐现金网| 东乌珠穆沁旗| 上海百家乐的玩法技巧和规则| 永利博百家乐官网现金网| 爱拼百家乐的玩法技巧和规则| 百家乐官网槛| 娱网棋牌| 百家乐AG| 水晶百家乐官网筹码| 自贡百家乐赌场| 百家乐官网电脑游戏机投注法实例| 大发888下载专区| 百家乐最佳公式| 百家乐官网游戏解密| 威尼斯人娱乐场 五星| 澳门百家乐官网赌场娱乐网规则| 总统娱乐城返水| 太阳城百家乐主页| 澳门百家乐官网现场真人版| 大发888可靠吗| 博狗百家乐开户| 百家乐官网游戏机博彩正网| 大发888出纳柜台 在线| 百家乐在线怎么玩| 百家乐官网21点| bet365合作计划| 百家乐庄闲符号记| 鼎龙百家乐官网的玩法技巧和规则 | 百家乐官网长t恤| 开阳县| 正品百家乐玩法| 百家乐官网加牌规| 百家乐官网模拟投注器| 大发888官网官方下载| 太阳城百家乐官网赌博害人| a8娱乐城开户| 最好百家乐的玩法技巧和规则 |