進程間通信方式

01?概述

1.1 發(fā)展

??? Linux進程間通信(IPC)大致發(fā)展如下:

????早期UNIX進程間通信偿枕、基于System V進程間通信年局、基于Socket進程間通信和Posix進程間通信。

??? UNIX進程間通信方式包括:管道席楚、FIFO凭需、信號染乌。

??? System V進程間通信方式包括:System V消息隊列瘫辩、System V信號量伏嗜、System V共享內(nèi)存。

??? Posix進程間通信包括:Posix消息隊列伐厌、Posix信號量、Posix共享內(nèi)存弧械。

1.2 目的

????進程間通信(IPC)的目的:

??? 1空民、數(shù)據(jù)傳輸:一個進程向另一個進程傳輸數(shù)據(jù)羞迷。

? ? 2、共享數(shù)據(jù):多個進程想要操作共享數(shù)據(jù)画饥,一個進程對共享數(shù)據(jù)的修改,其他進程應(yīng)實時看到抖甘。

??? 3、通知事件:一個進程需要向另一個進程發(fā)送消息衔彻,通知它發(fā)生了某種事件(如進程終止時需要通知父進程)薇宠。

??? 4、資源共享:多個進程之間共享同樣的資源艰额。為了做到這一點,需要內(nèi)核提供鎖和同步機制回梧。

??? 5祖搓、進程控制:有些進程希望完全控制另一個進程的執(zhí)行(如Debug進程),此時控制進程希望能夠攔截另一個進程的所有陷入和異常详囤,并能夠及時知道它的狀態(tài)改變。

1.3?單機和跨主機通信

????同一主機進程間的通信方式:

??? 1纬纪、Unix進程間通信方式:PIPE滑肉、FIFO和信號

??? 2、SystemV進程間通信方式:信號量(Semaphore)问畅、消息隊列(Message Queue)和共享內(nèi)存(Shared Memory)

????3六荒、讀寫鎖、互斥鎖卵皂、條件變量

????4砚亭、文件殴玛、文件鎖

????網(wǎng)絡(luò)主機間的通信方式:

??? 1添祸、RPC:Remote Protocol Call遠程過程調(diào)用(Thrift刃泌、gRPC)

??? 2、Socket:基于TCP/IP協(xié)議

02?管道

2.1 概述

????管道是Linux系統(tǒng)最古老的IPC方法耙替,可以簡單地將管道理解為一個通道林艘,它允許數(shù)據(jù)從一個進程流向另外一個進程。

2.2 特點

????1狐援、管道傳輸?shù)氖菬o格式字節(jié)流

????讀者從管道中讀取任意大小的數(shù)據(jù)塊,而不管寫者寫入管道的數(shù)據(jù)塊大小爹凹,即使用管道時不存在消息邊界的概念镶殷。此外,通過管道傳遞的數(shù)據(jù)是順序的绘趋,從管道中讀取出來字節(jié)的順序與它們被寫入管道的順序是完全一樣的陷遮。

????2、從管道中讀取數(shù)據(jù)

????試圖從一個當(dāng)前為空的管道中讀取數(shù)據(jù)將會被阻塞直到至少有一個字節(jié)被寫入到管道為止帽馋。如果管道的寫入端被關(guān)閉了绽族,那么從管道中讀取數(shù)據(jù)的進程在讀完管道中剩余的所有數(shù)據(jù)之后將會看到文件結(jié)束。

??? 3涛漂、管道是半雙工(單工)的(有的系統(tǒng)可能支持全雙工)检诗,數(shù)據(jù)只能向一個方向流動底哗;需要雙方通信時锚沸,需要建立起兩個管道哗蜈。

??? 4坠韩、管道的容量是有限的。管道其實是一個在內(nèi)核內(nèi)存中紅維護的緩沖區(qū)音比,這個緩沖區(qū)的存儲大小是有限的氢惋,一旦管道被填滿之后,繼續(xù)向該管道的寫入操作就會被阻塞直到讀者從管道中移除一些數(shù)據(jù)為止骚亿。

2.3 函數(shù)

????1熊赖、管道創(chuàng)建/關(guān)閉

????#include<unistd.h>intpipe(intfd[2]);

????成功的pipe()調(diào)用會在數(shù)組fields中返回兩個打開的文件描述符:一個表示管道的讀取端(fields[0]),另一個表示管道的寫入端(fields[1])俱笛。

??? 2传趾、管道的一個常見用途是執(zhí)行shell命令并讀取其輸出或者向其發(fā)送一些輸入墨缘,popen()和pclose()函數(shù)簡化了這個任務(wù)。

????FILE?*popen(constchar*?command?,constchar*?type?);intpclose( FILE * stream );

??? popen函數(shù)創(chuàng)建了一個管道宽涌,然后創(chuàng)建了一個子進程來執(zhí)行shell蝶棋,而shell又建立了一個子進程來執(zhí)行command字符串。mode參數(shù)是一個字符串兼贸,它確定調(diào)用進程是從管道中讀取數(shù)據(jù)(mode是r)還是將數(shù)據(jù)寫入到管道中(mode是w)。

03?信號

3.1?概述

????由于管道是一種無形鸯檬、無名的文件螺垢,它就只能通過fork的過程創(chuàng)建在“近親”的進程之間,而不可能成為可以在任意兩個進程之間建立通信的機制功茴,更不可能稱為一般的孽亲、通用的進程間通信模型。因此引入有名管道FIFO玲昧,它與管道最大的區(qū)別在于在文件系統(tǒng)中有名稱旭等,并且打開方式與打開普通文件一樣搔耕,可以實現(xiàn)非相關(guān)進程間的通信。

3.2 特點

????有名管道也是半雙工的通信方式菩收,但是它允許無親緣關(guān)系進程間的通信鲸睛。

3.3 函數(shù)

????#include<sys/types.h>#include<sys/stat.h>intmkfifo(constchar*pathname,mode_tmode);

????返回:若成功返回0,出錯返回-1箱舞。

????FIFO相關(guān)出錯信息:

????EACCES? 無存取權(quán)限

????EEXIST? 指定文件不存在

????ENAMETOOLONG? 路徑名太長

????ENOENT? 包含的目錄不存在

????ENOSPC? 文件系統(tǒng)剩余空間不足

????ENOTDIR? 文件路徑無效

????EROFS? 指定的文件存在于只讀文件系統(tǒng)中

04?信號

4.1 概述

????信號(signal)是Linux進程間通信的一種機制拳亿,全稱為軟中斷信號肺魁,也被稱為軟中斷。信號本質(zhì)上是在軟件層次上對硬件中斷機制的一種模擬。

????信號表示一種事件怎诫,也可能異步發(fā)生贷痪。如果程序并未安排怎么處理一個特定的信號劫拢,那么該信號出現(xiàn)時程序就作出一個缺省的反應(yīng)。標準未定義這個缺省反應(yīng)是什么,但絕大多數(shù)編譯器選擇終止程序哪廓。另外涡真,程序可以調(diào)用signal函數(shù),或者忽略這個信號哆料,或者設(shè)置一個信號處理函數(shù)东亦,當(dāng)信號發(fā)生時程序就調(diào)用這個函數(shù)。

????與其他進程間通信方式相比奋渔,信號所能傳遞的信息比較粗糙壮啊,只是一個整數(shù)。但正是由于傳遞的信息量少玄渗,信號也便于管理和使用狸眼,可以用于系統(tǒng)管理相關(guān)的任務(wù)份企,例如通知進程終結(jié)、中止或恢復(fù)等。

4.2 信號名

????SIGABRT程序請求異常終止

????SIGFPE發(fā)生一個算術(shù)錯誤

????SIGILL檢測到非法指令

????SIGSEGV檢測到對內(nèi)存的非法訪問

????SIGINT收到一個交互性注意信號

????SIGTERM收到一個終止程序的請求

????注:前幾個都是同步的降宅,SIGINT囚霸、SIGTERM是異步的拓型,它們在程序外部發(fā)生,同城是由程序的用戶觸發(fā)册养。

4.3 函數(shù)

????void (*signal(intsig , void (*func)(int)))(int);

????參數(shù):

????sig:信號編號

????void(*func)(int):信號處理函數(shù)

????返回值:類型是一個信號處理函數(shù)的函數(shù)指針

????SIG_ERR錯誤返回結(jié)果(void(*)(int))(-1)

????SIG_IGN忽略某個信號(void(*)(int))(0)

????SIG_DFL默認處理某個信號(void(*)(int))(1)

????信號集操作

????對信號集進行信號的清空压固、加入帐我、刪除等操作。

????intsigemptyset(sigset_t *set);將set集合置空

????intsigfillset(sigset_t *set)谣光;將所有信號加入set集合

????intsigaddset(sigset_t *set,intsigno)將signo信號加入到set集合

????intsigdelset(sigset_t *set芬为,intsigno);從set集合中移除signo信號

????intsigismember(constsigset_t *set,intsigno);signo判斷信號是否存在于set集合中

????設(shè)置或獲取信號集的信號屏蔽字:

????intsigprocmask(inthow,constsigset_t*restrictset,sigset_t*restritoset);

????返回值:成功返回0,出錯返回-1

????SIG_BLOCK? ? 追加屏蔽某個信號

????SIG_UNBLOCK? 取消屏蔽某個信號

????SIG_SETMASK???設(shè)置新的屏蔽字信號集

????如果屏蔽所有信號捡絮,可以進行如下設(shè)置:

????sig_set_tset;

????sigfillset(&set);

????sigprocmask(SIG_BLOCK, &set,NULL)福稳;

????等價于如下設(shè)置:

????sig_set_tset;

????sigfillset(&set);

????sigprocmask(SIG_SETMASK,?&set,NULL);

????如果清空所有信號屏蔽字集合瑞侮,可以進行如下設(shè)置:

????sig_set_tset;

????sigfillset(&set);

????sigprocmask(UN_BLOCK, &set,NULL);

????等價于如下設(shè)置:

????sig_set_tset;

????sigemptyset(&set);

????sigprocmask(SIG_SETMASK,?&set,NULL);

????獲取當(dāng)前信號屏蔽字信號集:

????sig_set_tset;

????sigemptyset(&set);

????sigprocmask(SIG_BLOCK,NULL, &set);

05?消息隊列

5.1 概述

????消息隊列是由消息的鏈表半火,存儲在內(nèi)核中并由消息隊列標識符標識。消息隊列克服了信號傳遞信號量少梅掠、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。

????與管道和FIFO不同酪我,進程可以在沒有另外一個進程等待讀的情況下進行寫且叁。另外一方面,管道和FIFO一旦相關(guān)進程都關(guān)閉并退出后欺矫,里面的數(shù)據(jù)也就沒有了展氓,但是對于消息隊列遇汞,一個進程往消息隊列中寫入數(shù)據(jù)后退出,另外一個進程仍然可以打開并讀取消息勺疼。消息隊列與UNIX域套接字相比执庐,在速度上沒有多少優(yōu)勢导梆。

5.2 函數(shù)

????System V定義:

????#include<sys/msg.h>

????intmsgget(key_tkey,intflag);

????intmsgctl(intmsgid,intcmd,struct?msqid_ds?*buf);

????intmsgsnd(intmsgqid,constvoid*ptr,size_tnbytes,intflag);

????size_tmsgrcv(intmsgqid,void*ptr,size_tnbytes,longtype,intflag);

????Posix定義:

????#include<mqueue.h>

????mqd_tmq_open(constchar*name,intoflag,/*?mode_t?mode,?struct?mq_attr?*attr?*/);

????mqd_tmq_close(mqd_tmqdes);

????mqd_tmq_unlink(constchar*name);

????mqd_tmq_send(mqd_tmqdes,constchar*msg_ptr,size_tmsg_len,unsignedmsg_prio);

????mqd_tmq_receive(mqd_tmqdes,char*msg_ptr,size_tmsg_len,unsigned*msg_prio);

06?共享內(nèi)存

6.1 概述

????共享內(nèi)存區(qū)域是被多個進程共享的一部分物理內(nèi)存看尼。如果多個進程都把該內(nèi)存區(qū)域映射到自己的虛擬地址空間,則這些進程就都可以直接訪問該共享內(nèi)存區(qū)域躏结,從而可以通過該區(qū)域進行通信狰域。

????共享內(nèi)存是進程間共享數(shù)據(jù)的一種最快的方法兆览,一個進程向共享內(nèi)存區(qū)域?qū)懭霐?shù)據(jù),共享這個內(nèi)存區(qū)域的所有進程就可以立刻看到其中的內(nèi)容子巾。

6.2 函數(shù)

????SYSTEM V定義:

????intshmget(key_tkey,intsize,intshmflg);

????void*shmat(intshmid,constvoid*shmaddr,intshmflg);

????intshmdt(constvoid*shmaddr);

????intshmctl(intshmid,intcmd,?struct?shmid_ds?*buf);

????POSIX定義:

????intshm_open(constchar*name,intoflag,mode_tmode);

????intshm_unlink(constchar*name);

????intftruncate(intfd,off_tlength);

????由于POSIX標準比較通用,一般建議使用該標準定義的方法集椰于。

07?信號量

7.1 概述

????信號量(semaphore)缠导,有時稱為信號燈僻造,是多線程環(huán)境下使用的一種設(shè)施,可以用來保證兩個或多個關(guān)鍵代碼段不被并發(fā)調(diào)用(就是具有原子性的計數(shù)器)竹挡。

????信號量是一個計數(shù)器立膛,可用來控制多個進程對共享資源的訪問。它常常作為一種鎖機制好啰,防止某進程正在訪問共享資源時儿奶,其他進程也訪問該資源闯捎。因為,作為進程間以及同一進程內(nèi)不同線程之間的同步手段瓤鼻。

7.2 函數(shù)

????System V定義:

????#incldue<sys/sem.h>

????intsemget(key_tkey,intnsems,intflag);

????intsemctl(intsemid,intsemnum,intcmd,.../*union?semun?arg*/)

????intsemop(intsemid,struct sembuf *semop,size_tnops);

????Posix定義:

????intsem_init(sem_t*sem,intpshared,unsignedintvalue);

????intsem_wait(sem_t*sem);

????intsem_trywait(sem_t* sem);

????intsem_timedwait(sem_t*sem,conststruct timespec *abs_timeout);

????intsem_post(sem_t*sem);

????intsem_close(sem_t*sem);

????intsem_unlink(constchar*name);

????intsem_destroy(sem_t*sem);

08?內(nèi)存映射

8.1 概述

??? mmap()系統(tǒng)調(diào)用在調(diào)用進程的虛擬地址空間中創(chuàng)建一個新內(nèi)存映射,映射分為兩種:

? ??1清焕、文件映射

????文件映射將一個文件的一部分直接映射到調(diào)用進程的虛擬內(nèi)存中耐朴,一旦一個文件被映射之后就可以通過在相應(yīng)的內(nèi)存區(qū)域中操作字節(jié)來訪問文件內(nèi)容了访诱。映射的分頁會在需要的時候從文件中(自動)加載影晓。這種映射也被稱為基于文件的映射或內(nèi)存映射文件。

? ??2疤祭、匿名映射

????一個匿名映射沒有對應(yīng)的文件饵婆,相反,這種映射的分頁會被初始化為0草穆。

8.2 函數(shù)

????void*mmap(void*start,size_tlength,intprot,intflags,intfd,off_toffset);

????intmunmap(void*start,size_tlength);

????參數(shù):start:映射區(qū)的開始地址悲柱。

????length:映射區(qū)的長度些己。

????prot:期望的內(nèi)存保護標志,不能與文件的打開模式?jīng)_突涯冠。

????是以下的某個值逼庞,可以通過or運算合理地組合在一起

????PROT_EXEC//頁內(nèi)容可以被執(zhí)行

????PROT_READ//頁內(nèi)容可以被讀取

????PROT_WRITE//頁可以被寫入

????PROT_NONE//頁不可訪問flags:指定映射對象的類型往堡,映射選項和映射頁是否可以共享共耍。

09?RPC

????遠程過程調(diào)用(Remote Protocol Call),跨主機通信穆咐。

10?套接字

????網(wǎng)絡(luò)通信字旭,包括UDP和TCP兩種遗淳,單機或跨主機通信。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拆讯,一起剝皮案震驚了整個濱河市种呐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汁讼,老刑警劉巖阔墩,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戈擒,死亡現(xiàn)場離奇詭異,居然都是意外死亡搜囱,警方通過查閱死者的電腦和手機柑土,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門稽屏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坛增,你說我怎么就攤上這事薄腻♀挚” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵咐蚯,是天一觀的道長弄贿。 經(jīng)常有香客問我差凹,道長豆拨,這世上最難降的妖魔是什么施禾? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任搁胆,我火速辦了婚禮渠旁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粤铭。我一直安慰自己杂靶,他們只是感情好吗垮,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怯屉,像睡著了一般饵沧。 火紅的嫁衣襯著肌膚如雪狼牺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機與錄音咏瑟,去河邊找鬼痪署。 笑死狼犯,一個胖子當(dāng)著我的面吹牛领铐,可吹牛的內(nèi)容都是我干的宋舷。 我是一名探鬼主播祝蝠,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼细溅!你這毒婦竟也來了喇聊?” 一聲冷哼從身側(cè)響起蹦狂,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鸥咖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后啊研,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸥拧,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡富弦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年沟娱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腕柜。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡济似,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盏缤,到底是詐尸還是另有隱情砰蠢,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布唉铜,位于F島的核電站台舱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏潭流。R本人自食惡果不足惜柜去,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拆宛。 院中可真熱鬧嗓奢,春花似錦、人聲如沸胰挑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞻颂。三九已至豺谈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贡这,已是汗流浹背茬末。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盖矫,地道東北人丽惭。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像辈双,于是被迫代替她去往敵國和親责掏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容