Linux系统【四】进程间通信-管道
進(jìn)程間通信(IPC Interprocess Communication)
進(jìn)程和進(jìn)程之間的通信只能通過(guò)內(nèi)核,在內(nèi)核中提供一塊緩沖區(qū)進(jìn)行通信。內(nèi)核提供的這種機(jī)制叫做IPC
在進(jìn)程間完成數(shù)據(jù)傳輸需要借助操作系統(tǒng)提供的特殊方法,如:文件(開銷較大,穩(wěn)定性低)、管道(使用簡(jiǎn)單)、信號(hào)(開銷最小)、共享內(nèi)存(共享映射區(qū),可以完成沒有血緣關(guān)系的進(jìn)程之間的 通信)、消息隊(duì)列、本地套接字(復(fù)雜,較難,最穩(wěn)定)、命名管道等。
管道
進(jìn)程的內(nèi)存在虛擬內(nèi)存上互不相關(guān),但是有血緣關(guān)系的進(jìn)程在物理內(nèi)存上,進(jìn)程的內(nèi)核區(qū)在同一片區(qū)域。離得很近。
管道是一種最基本的IPC機(jī)制。作用于有血緣關(guān)系的進(jìn)程之間,完成數(shù)據(jù)傳遞。
特征:
- 本質(zhì)是一個(gè)偽文件(實(shí)際上是內(nèi)核緩沖區(qū))
Linux操作系統(tǒng)中實(shí)際上有七中數(shù)據(jù)類型(-,d,l,s,b,p,c),其中只有文件、目錄和符號(hào)鏈接占用磁盤空間,符號(hào)鏈接當(dāng)路徑不是非常長(zhǎng)的時(shí)候保存在inode中,其他類型都是偽文件,不占用實(shí)際存儲(chǔ)空間 - 由兩個(gè)文件描述符引用,一個(gè)一個(gè)表示讀端,一個(gè)表示寫端
- 規(guī)定數(shù)據(jù)從管道的寫端流入管道,從讀端讀出數(shù)據(jù)。
原理:管道實(shí)際上是內(nèi)核使用環(huán)形隊(duì)列機(jī)制,借助內(nèi)核緩沖區(qū)(4K)實(shí)現(xiàn),即一般是八個(gè)扇區(qū)
圓形的磁盤被劃分為多個(gè)扇區(qū),每個(gè)扇區(qū)512字節(jié)。一個(gè)文件最少占用一個(gè)扇區(qū)。
因?yàn)槭怯申?duì)列實(shí)現(xiàn)的,所以我們不能進(jìn)行多次讀取,而且只能是固定方向傳送文件。
局限性:
- 數(shù)據(jù)不能同時(shí)讀寫
- 數(shù)據(jù)一旦讀走便不在管道中存在,不可重讀讀取數(shù)據(jù)
- 數(shù)據(jù)采用半雙工通信方式(數(shù)據(jù)只能在一個(gè)方向流動(dòng)的通信方式,還有雙向全雙工、雙向半雙工、單工通信)
- 只能在有公共祖先的進(jìn)程(有血緣關(guān)系的進(jìn)程)間使用管道
pipe函數(shù)
頭文件:#include<unistd.h>
函數(shù)聲明:int pipe(int pipefd[2]);
規(guī)定fd[0]讀,fd[1]寫
返回值:成功返回0,失敗返回-1,同時(shí)設(shè)置erron
為了保證管道的單向流動(dòng)性需要在進(jìn)程中關(guān)閉一部分文件描述符。
從管道中讀取數(shù)據(jù)時(shí)當(dāng)管道中沒有數(shù)據(jù)將會(huì)自動(dòng)阻塞,直到有數(shù)據(jù)寫入。
讀管道:
- 如果管道中有數(shù)據(jù),則read返回實(shí)際讀到的字節(jié)數(shù)
- 如果管道中沒有數(shù)據(jù),若寫端關(guān)閉,read返回0,如果仍有寫端打開,則阻塞等待寫入。
寫管道:
- 如果讀端全關(guān)閉,則進(jìn)程異常終止(SIGPIPE信號(hào))
- 如果讀端打開,若管道未滿,則寫入數(shù)據(jù),返回寫入字節(jié)數(shù)。若管道已滿,則阻塞(這種情況很少出現(xiàn))。
當(dāng)寫進(jìn)程向管道中寫入時(shí),它利用標(biāo)準(zhǔn)的庫(kù)函數(shù)write(),系統(tǒng)根據(jù)庫(kù)函數(shù)傳遞的文件描述符,可找到該文件的 file 結(jié)構(gòu)。file 結(jié)構(gòu)中指定了用來(lái)進(jìn)行寫操作的函數(shù)(即寫入函數(shù))地址,于是,內(nèi)核調(diào)用該函數(shù)完成寫操作。寫入函數(shù)在向內(nèi)存中寫入數(shù)據(jù)之前,必須首先檢查 VFS 索引節(jié)點(diǎn)中的信息,同時(shí)滿足如下條件時(shí),才能進(jìn)行實(shí)際的內(nèi)存復(fù)制工作:
1.內(nèi)存中有足夠的空間可容納所有要寫入的數(shù)據(jù);
2.內(nèi)存沒有被讀程序鎖定。
如果同時(shí)滿足上述條件,寫入函數(shù)首先鎖定內(nèi)存,然后從寫進(jìn)程的地址空間中復(fù)制數(shù)據(jù)到內(nèi)存。否則,寫入進(jìn)程就休眠在 VFS 索 引節(jié)點(diǎn)的等待隊(duì)列中,接下來(lái),內(nèi)核將調(diào)用調(diào)度程序,而調(diào)度程序會(huì)選擇其他進(jìn)程運(yùn)行。寫入進(jìn)程實(shí)際處于可中斷的等待狀態(tài),當(dāng)內(nèi)存中有足夠的空間可以容納寫入 數(shù)據(jù),或內(nèi)存被解鎖時(shí),讀取進(jìn)程會(huì)喚醒寫入進(jìn)程,這時(shí),寫入進(jìn)程將接收到信號(hào)。當(dāng)數(shù)據(jù)寫入內(nèi)存之后,內(nèi)存被解鎖,而所有休眠在索引節(jié)點(diǎn)的讀取進(jìn)程會(huì)被喚醒。
管道的讀取過(guò)程和寫入過(guò)程類似。但是,進(jìn)程可以在沒有數(shù)據(jù)或內(nèi)存被鎖定時(shí)立即返回錯(cuò)誤信息,而不是阻塞該進(jìn)程,這依賴于文件或管道的打開模式。反之,進(jìn)程可 以休眠在索引節(jié)點(diǎn)的等待隊(duì)列中等待寫入進(jìn)程寫入數(shù)據(jù)。當(dāng)所有的進(jìn)程完成了管道操作之后,管道的索引節(jié)點(diǎn)被丟棄,而共享數(shù)據(jù)頁(yè)也被釋放。
參考博客 linux管道詳解
獲取管道緩沖區(qū)的大小:ulimit -a
優(yōu)點(diǎn):實(shí)現(xiàn)手段簡(jiǎn)單
缺點(diǎn):單向通信、只有血緣關(guān)系進(jìn)程間使用
總結(jié)
以上是生活随笔為你收集整理的Linux系统【四】进程间通信-管道的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 现在版本的LOL怎么发所有人
- 下一篇: Linux系统【五】进程间通信-共享内存