色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux進程間通信之管道(pipe)、命名管道(FIFO)與信號(Signal)

Linux愛好者 ? 來源:華山大師兄 ? 作者:華山大師兄 ? 2020-12-11 16:41 ? 次閱讀

管道(pipe)

管道可用于具有親緣關系進程間的通信,有名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關系進程間的通信。

實現機制:

管道是由內核管理的一個緩沖區,相當于我們放入內存中的一個紙條。管道的一端連接一個進程的輸出。這個進程會向管道中放入信息

管道的另一端連接一個進程的輸入,這個進程取出被放入管道的信息。

一個緩沖區不需要很大,它被設計成為環形的數據結構,以便管道可以被循環利用。

當管道中沒有信息的話,從管道中讀取的進程會等待,直到另一端的進程放入信息。

當管道被放滿信息的時候,嘗試放入信息的進程會等待,直到另一端的進程取出信息。當兩個進程都終結的時候,管道也自動消失。

從原理上,管道利用fork機制建立,從而讓兩個進程可以連接到同一個PIPE上。

最開始的時候,上面的兩個箭頭都連接在同一個進程Process 1上(連接在Process 1上的兩個箭頭)。

當fork復制進程的時候,會將這兩個連接也復制到新的進程(Process 2)。

隨后,每個進程關閉自己不需要的一個連接 (兩個黑色的箭頭被關閉; Process 1關閉從PIPE來的輸入連接,Process 2關閉輸出到PIPE的連接),這樣,剩下的紅色連接就構成了如上圖的PIPE。

實現細節:

Linux 中,管道的實現并沒有使用專門的數據結構,而是借助了文件系統的file結構和VFS的索引節點inode。

通過將兩個 file 結構指向同一個臨時的 VFS 索引節點,而這個 VFS 索引節點又指向一個物理頁面而實現的。如下圖

dae718ba-28a5-11eb-a64d-12bb97331649.jpg

有兩個 file 數據結構,但它們定義文件操作例程地址是不同的,其中一個是向管道中寫入數據的例程地址,而另一個是從管道中讀出數據的例程地址。

這樣,用戶程序的系統調用仍然是通常的文件操作,而內核卻利用這種抽象機制實現了管道這一特殊操作。

關于管道的讀寫

管道實現的源代碼在fs/pipe.c中,在pipe.c中有很多函數,其中有兩個函數比較重要,即管道讀函數pipe_read()和管道寫函數pipe_wrtie()。

管道寫函數通過將字節復制到 VFS 索引節點指向的物理內存而寫入數據,而管道讀函數則通過復制物理內存中的字節而讀出數據。

當然,內核必須利用一定的機制同步對管道的訪問,為此,內核使用了鎖、等待隊列和信號

當寫進程向管道中寫入時,它利用標準的庫函數write(),系統根據庫函數傳遞的文件描述符,可找到該文件的 file 結構。

file 結構中指定了用來進行寫操作的函數(即寫入函數)地址,

于是,內核調用該函數完成寫操作。寫入函數在向內存中寫入數據之前,必須首先檢查 VFS 索引節點中的信息,同時滿足如下條件時,才能進行實際的內存復制工作:

·內存中有足夠的空間可容納所有要寫入的數據;

·內存沒有被讀程序鎖定。

如果同時滿足上述條件,寫入函數首先鎖定內存,然后從寫進程的地址空間中復制數據到內存。

否則,寫入進程就休眠在 VFS 索引節點的等待隊列中,接下來,內核將調用調度程序,而調度程序會選擇其他進程運行。

寫入進程實際處于可中斷的等待狀態,當內存中有足夠的空間可以容納寫入數據,或內存被解鎖時,讀取進程會喚醒寫入進程,這時,寫入進程將接收到信號。

當數據寫入內存之后,內存被解鎖,而所有休眠在索引節點的讀取進程會被喚醒。

管道的讀取過程和寫入過程類似。但是,進程可以在沒有數據或內存被鎖定時立即返回錯誤信息,而不是阻塞該進程,這依賴于文件或管道的打開模式。

反之,進程可以休眠在索引節點的等待隊列中等待寫入進程寫入數據。當所有的進程完成了管道操作之后,管道的索引節點被丟棄,而共享數據頁也被釋放。

Linux函數原型

#include int pipe(int filedes[2]);

filedes[0]用于讀出數據,讀取時必須關閉寫入端,即close(filedes[1]);

filedes[1]用于寫入數據,寫入時必須關閉讀取端,即close(filedes[0])。

程序實例:

int main(void){ int n; int fd[2]; pid_t pid; char line[MAXLINE]; if(pipe(fd) 0){ /* 先建立管道得到一對文件描述符 */ exit(0); } if((pid = fork()) 0) /* 父進程把文件描述符復制給子進程 */ exit(1); else if(pid > 0){ /* 父進程寫 */ close(fd[0]); /* 關閉讀描述符 */ write(fd[1], " hello world ", 14); } else{ /* 子進程讀 */ close(fd[1]); /* 關閉寫端 */ n = read(fd[0], line, MAXLINE); write(STDOUT_FILENO, line, n); } exit(0);}

命名管道(named PIPE)

由于基于fork機制,所以管道只能用于父進程和子進程之間,或者擁有相同祖先的兩個子進程之間 (有親緣關系的進程之間)。

為了解決這一問題,Linux提供了FIFO方式連接進程。FIFO又叫做命名管道(named PIPE)。

FIFO (First in, First out)為一種特殊的文件類型,它在文件系統中有對應的路徑。

當一個進程以讀(r)的方式打開該文件,而另一個進程以寫(w)的方式打開該文件,那么內核就會在這兩個進程之間建立管道,所以FIFO實際上也由內核管理,不與硬盤打交道。

之所以叫FIFO,是因為管道本質上是一個先進先出的隊列數據結構,最早放入的數據被最先讀出來,從而保證信息交流的順序。

FIFO只是借用了文件系統(file system,命名管道是一種特殊類型的文件,因為Linux中所有事物都是文件,它在文件系統中以文件名的形式存在。)來為管道命名。

寫模式的進程向FIFO文件中寫入,而讀模式的進程從FIFO文件中讀出。

當刪除FIFO文件時,管道連接也隨之消失。

FIFO的好處在于我們可以通過文件的路徑來識別管道,從而讓沒有親緣關系的進程之間建立連接

函數原型:

#include #include int mkfifo(const char *filename, mode_t mode);int mknode(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0 );

其中pathname是被創建的文件名稱,mode表示將在該文件上設置的權限位和將被創建的文件類型(在此情況下為S_IFIFO),dev是當創建設備特殊文件時使用的一個值。

因此,對于先進先出文件它的值為0。

程序實例:

#include #include #include #include int main() { int res = mkfifo("/tmp/my_fifo", 0777); if (res == 0) { printf("FIFO created/n"); } exit(EXIT_SUCCESS); }

編譯這個程序:

gcc –o fifo1.c fifo

運行這個程序:

$ fifo1

用ls命令查看所創建的管道

$ls-lF/tmp/my_fifoprwxr-xr-x 1 root root 0 05-08 20:10 /tmp/my_fifo|

注意:ls命令的輸出結果中的第一個字符為p,表示這是一個管道。

最后的|符號是由ls命令的-F選項添加的,它也表示是這是一個管道。

FIFO讀寫規則

1.從FIFO中讀取數據:約定:如果一個進程為了從FIFO中讀取數據而阻塞打開了FIFO,那么稱該進程內的讀操作為設置了阻塞標志的讀操作

2.從FIFO中寫入數據:約定:如果一個進程為了向FIFO中寫入數據而阻塞打開FIFO,那么稱該進程內的寫操作為設置了阻塞標志的寫操作。

詳見:http://blog.csdn.net/MONKEY_D_MENG/article/details/5570468

信號(Signal)

信號是比較復雜的通信方式,用于通知接受進程有某種事件發生,除了用于進程間通信外,進程還可以發送信號給進程本身;

Linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基于BSD的,BSD為了實現可靠信號機制,又能夠統一對外接口,用sigaction函數重新實現了signal函數)

信號種類

db100efa-28a5-11eb-a64d-12bb97331649.jpg

每種信號類型都有對應的信號處理程序(也叫信號的操作),就好像每個中斷都有一個中斷服務例程一樣。

大多數信號的默認操作是結束接收信號的進程;

然而,一個進程通常可以請求系統采取某些代替的操作,各種代替操作是:

忽略信號。隨著這一選項的設置,進程將忽略信號的出現。

有兩個信號 不可以被忽略:SIGKILL,它將結束進程;

SIGSTOP,它是作業控制機制的一部分,將掛起作業的執行。

恢復信號的默認操作。

執行一個預先安排的信號處理函數。

進程可以登記特殊的信號處理函數。

當進程收到信號時,信號處理函數將像中斷服務例程一樣被調用,當從該信號處理函數返回時,控制被返回給主程序,并且繼續正常執行。

但是,信號和中斷有所不同。

中斷的響應和處理都發生在內核空間,而信號的響應發生在內核空間,信號處理程序的執行卻發生在用戶空間。

那么,什么時候檢測和響應信號呢?通常發生在兩種情況下:

當前進程由于系統調用、中斷或異常而進入內核空間以后,從內核空間返回到用戶空間前夕;

當前進程在內核中進入睡眠以后剛被喚醒的時候,由于檢測到信號的存在而提前返回到用戶空間。

函數原型等詳見:

http://www.cnblogs.com/biyeymyhjob/archive/2012/08/04/2622265.html

信號本質

信號是在軟件層次上對中斷機制的一種模擬,在原理上,一個進程收到一個信號與處理器收到一個中斷請求可以說是一樣的。

信號是異步的,一個進程不必通過任何操作來等待信號的到達,事實上,進程也不知道信號到底什么時候到達。

信號是進程間通信機制中唯一的異步通信機制,可以看作是異步通知,通知接收信號的進程有哪些事情發生了。

信號機制經過POSIX實時擴展后,功能更加強大,除了基本通知功能外,還可以傳遞附加信息。

信號來源

信號事件的發生有兩個來源:

硬件來源(比如我們按下了鍵盤或者其它硬件故障);

軟件來源,最常用發送信號的系統函數是kill, raise, alarm和setitimer以及sigqueue函數,軟件來源還包括一些非法運算等操作。

關于信號處理機制的原理(內核角度)

內核給一個進程發送軟中斷信號的方法,是在進程所在的進程表項的信號域設置對應于該信號的位。

這里要補充的是,

如果信號發送給一個正在睡眠的進程,那么要 看該進程進入睡眠的優先級,如果進程睡眠在可被中斷的優先級上,則喚醒進程;

否則僅設置進程表中信號域相應的位,而不喚醒進程。

這一點比較重要,因為進程檢查是否收到信號的時機是:一個進程在即將從內核態返回到用戶態時;

或者,在一個進程要進入或離開一個適當的低調度優先級睡眠狀態時。

內核處理一個進程收到的信號的時機是在一個進程從內核態返回用戶態時。

所以,當一個進程在內核態下運行時,

軟中斷信號并不立即起作用,要等到將返回用戶態時才處理。

進程只有處理完信號才會返回用戶態(上面的例子程序中,在步驟5中,解除阻塞后,先打印caught SIGQUIT,再打印SIGQUIT unblocked,即在sigprocmask返回前,信號處理程序先執行),進程在用戶態下不會有未處理完的信號。

內核處理一個進程收到的軟中斷信號是在該進程的上下文中,因此,進程必須處于運行狀態。

如果進程收到一個要捕捉的信號,那么進程從內核態返回用戶態時執行用戶定義的函數。

而且執行用戶定義的函數的方法很巧妙,內核是在用戶棧上創建一個新的層,該層中將返回地址的值設置成用戶定義的處理函數的地址,

這樣進程從內核返回彈出棧頂時就返回到用戶定義的函數處,從函數返回再彈出棧頂時,才返回原先進入內核的地方,接著原來的地方繼續運行。

這樣做的原因是用戶定義的處理函數不能且不允許在內核態下執行(如果用戶定義的函數在內核態下運行的話,用戶就可以獲得任何權限)。

在信號的處理方法中有幾點特別要引起注意。

第一,在一些系統中,當一個進程處理完中斷信號返回用戶態之前,內核清除用戶區中設定的對該信號的處理例程的地址,

即下一次進程對該信號的處理方法又改為默認值,除非在下一次信號到來之前再次使用signal系統調用。

這可能會使得進程在調用signal之前又得 到該信號而導致退出。在BSD中,內核不再清除該地址。

但不清除該地址可能使得進程因為過多過快的得到某個信號而導致堆棧溢出。為了避免出現上述情況。

在 BSD系統中,內核模擬了對硬件中斷的處理方法,即在處理某個中斷時,阻止接收新的該類中斷。

第二個要引起注意的是,如果要捕捉的信號發生于進程正在一個系統調用中時,并且該進程睡眠在可中斷的優先級上(若系統調用未睡眠而是在運行,根據上面的分 析,等該系統調用運行完畢后再處理信號),

這時該信號引起進程作一次longjmp,跳出睡眠狀態,返回用戶態并執行信號處理例程。

當從信號處理例程返回 時,進程就象從系統調用返回一樣,但返回了一個錯誤如-1,并將errno設置為EINTR,指出該次系統調用曾經被中斷。

這要注意的是,BSD系統中內 核可以自動地重新開始系統調用,或者手如上面所述手動設置重啟。

第三個要注意的地方:若進程睡眠在可中斷的優先級上,則當它收到一個要忽略的信號時,該進程被喚醒,但不做longjmp,一般是繼續睡眠。

但用戶感覺不 到進程曾經被喚醒,而是象沒有發生過該信號一樣。

所以能夠使pause、sleep等函數從掛起態返回的信號必須要有信號處理函數,如果沒有什么動作,可以將處理函數設為空。

第四個要注意的地方:內核對子進程終止(SIGCLD)信號的處理方法與其他信號有所區別。

當進程正常或異常終止時,內核都向其父進程發一個SIGCLD 信號,缺省情況下,父進程忽略該信號,就象沒有收到該信號似的,

如果父進程希望獲得子進程終止的狀態,則應該事先用signal函數為SIGCLD信號設 置信號處理程序,在信號處理程序中調用wait。

SIGCLD信號的作用是喚醒一個睡眠在可被中斷優先級上的進程。

如果該進程捕捉了這個信號,就象普通信號處理一樣轉到處理例程。

如果進程忽略該信號,則 什么也不做。

其實wait不一定放在信號處理函數中,但這樣的話因為不知道子進程何時終止,在子進程終止前,wait將使父進程掛起休眠。

信號生命周期

db47662a-28a5-11eb-a64d-12bb97331649.jpg

責任編輯:lq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11296

    瀏覽量

    209360
  • 管道
    +關注

    關注

    3

    文章

    145

    瀏覽量

    17969
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    40124
  • signal
    +關注

    關注

    0

    文章

    110

    瀏覽量

    24914

原文標題:Linux 進程間通信之管道(pipe)、命名管道(FIFO)與信號(Signal)

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-Linux C接口編程入門文件I/O

    。目錄:目錄也被視為文件,用于組織和存儲其他文件和目錄。通過目錄文件,可以進行文件的查找、創建、刪除和移動等操作。管道Pipe)和套接字(Socket):Linux提供了管道和套接字
    發表于 10-10 09:11

    飛凌嵌入式ElfBoard ELF 1板卡-Linux C接口編程入門文件I/O

    。目錄:目錄也被視為文件,用于組織和存儲其他文件和目錄。通過目錄文件,可以進行文件的查找、創建、刪除和移動等操作。管道Pipe)和套接字(Socket):Linux提供了管道和套接字
    發表于 10-09 15:38

    聲波定位技術在地下管道中如何應用

    隨著城市化進程的加速,地下管道作為城市基礎設施的重要組成部分,其安全、高效的維護與管理顯得尤為重要。聲波定位技術作為一種非破壞性探測手段,在地下管道中的應用日益廣泛,成為提升管道維護和
    的頭像 發表于 09-27 13:54 ?141次閱讀

    功率放大器在管道定位系統硬件中的應用

    實驗名稱:管道定位系統的硬件實現研究方向:管道無損檢測實驗內容:開展基于PCM的管道定位系統的可行性研究:采用函數發生器產生4Hz、8Hz和72Hz的多頻電流,并將信號輸出
    的頭像 發表于 08-19 16:00 ?670次閱讀
    功率放大器在<b class='flag-5'>管道</b>定位系統硬件中的應用

    功率放大器在管道螺旋導波信號測量實驗中的應用

    實驗名稱:功率放大器在管道螺旋導波信號測量實驗中的應用實驗內容:測量沿著管道壁面以螺旋方式行進的準lamb導波,研究其傳播規律。研究方向:管道導波無損檢測測試設備:
    的頭像 發表于 08-14 17:53 ?245次閱讀
    功率放大器在<b class='flag-5'>管道</b>螺旋導波<b class='flag-5'>信號</b>測量實驗中的應用

    管道風速傳感器安裝要求標準

    管道風速傳感器是一種用于測量管道內氣流速度的儀器,廣泛應用于工業、環保、建筑等領域。為了確保傳感器的準確性和穩定性,安裝過程中需要遵循一定的標準和要求。 一、管道風速傳感器概述 1.1 管道
    的頭像 發表于 07-01 09:16 ?886次閱讀

    管道風速傳感器的安裝在管道的前端還是后端

    管道風速傳感器是一種用于測量管道內氣流速度的儀器,廣泛應用于工業、農業、環保、氣象等領域。在安裝管道風速傳感器時,需要考慮多種因素,以確保測量結果的準確性和可靠性。本文將詳細介紹管道
    的頭像 發表于 07-01 09:14 ?830次閱讀

    進程通信的消息隊列介紹

    消息隊列是一種非常常見的進程通信方式。
    的頭像 發表于 04-08 17:27 ?309次閱讀

    進程通信信號問題分析

    Linux里面信號有60多個,分為標準信號和實時信號,編號從1到31,34到64。不同的內核版本略有區別。
    的頭像 發表于 04-07 10:16 ?408次閱讀

    功率放大器在管道定位系統的硬件實現研究中的應用

    實驗名稱:功率放大器在管道定位系統的硬件實現研究中的應用研究方向:管道無損檢測實驗設備:ATA-308C功率放大器,函數信號發生器,數字萬用表,示波器等實驗目的:開展基于PCM的管道
    的頭像 發表于 03-28 08:01 ?340次閱讀
    功率放大器在<b class='flag-5'>管道</b>定位系統的硬件實現研究中的應用

    功率放大器在管道螺旋導波信號測量實驗中的應用

      實驗名稱:功率放大器在管道螺旋導波信號測量實驗中的應用   實驗內容:測量沿著管道壁面以螺旋方式行進的準lamb導波,研究其傳播規律。   研究方向:管道導波無損檢測   測試設備
    發表于 03-08 18:03

    功率放大器在管道定位系統硬件中的應用

      實驗名稱:管道定位系統的硬件實現   研究方向:管道無損檢測   實驗內容:開展基于PCM的管道定位系統的可行性研究:采用函數發生器產生4Hz、8Hz和72Hz的多頻電流,并將信號
    發表于 03-08 17:39

    ATA-M4功率放大器在充粘液管道損傷檢測中的應用

    數據,通過USB接口發送到信號發生器,生成實驗所需的原始激勵信號信號發生器通過ch1將原始激勵信號輸入數字示波器,又通過ch2將激勵信號
    發表于 02-27 17:06

    linux管道概述

    一、進程通信(IPC)介紹 進程通信(IPC,InterProcess Communicat
    的頭像 發表于 02-18 14:51 ?493次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>管道</b>概述

    功率放大器在管道螺旋導波信號測量實驗中的應用

    實驗名稱:高壓放大器在骨的逆力電研究中的應用研究方向:管道導波無損檢測測試目的:測量沿著管道壁面以螺旋方式行進的準lamb導波,研究其傳播規律。測試設備:ATA-2022B高壓放大器、信號發生器
    的頭像 發表于 01-05 08:01 ?352次閱讀
    功率放大器在<b class='flag-5'>管道</b>螺旋導波<b class='flag-5'>信號</b>測量實驗中的應用
    主站蜘蛛池模板: 国产小视频免费看| 女教师苍井空体肉女教师S242| 小草影院免费| 极品内射少妇精品无码视频| 亚洲综合久久一本伊伊区| 免费一区在线观看| 国产精品亚洲AV色欲在线观看| 一区二一二| 少妇内射视频播放舔大片| 精品国产自在现线拍400部| cntv官网| 亚洲欧美另类无码专区| 欧美精品做人一级爱免费| 国产在线观看黄| 哺乳溢出羽月希中文字幕| 性肥胖BWBWBW| 性满足久久久久久久久| 无码任你躁久久久久久老妇双奶| 两百磅美女| 国产人妻人伦精品无码.麻豆| 99在线免费观看| 亚洲日本欧美天堂在线| 亚洲人成伊人成综合网久久久| 亚洲天堂一区二区三区| 午夜噜噜噜私人影院在线播放| 欧美 亚洲 另类 综合网| 免费看美女的网站| 欧美人妇无码精品久久| 人驴交f ee欧美| 久久天堂网| 国产一区二区三区内射高清| 国语对白老女人8av| 国产成人免费观看在线视频| 97SE亚洲国产综合自在线不卡| 性生大片免费看| 亚洲伊人久久大香线蕉综合图片| 中国老女人xxhd69| 亚洲欧美综合乱码精品成人网 | 囯产少妇BBBBBB高潮喷水一| 9277高清在线观看视频| xxx性欧美在线|