Linux進程間通信之管道

進程間通信介紹:

進程間通信的概念:

進程間通信簡稱IPC(Interprocess communication),進程間通信就是在不同進程之間傳播或交換信息。

進程間通信的目的:

數據傳輸: 一個進程需要將它的數據發送給另一個進程。
資源共享: 多個進程之間共享同樣的資源。
通知事件: 一個進程需要向另一個或一組進程發送消息,通知它(它們)發生了某種事件,比如進程終止時需要通知其父進程。
進程控制: 有些進程希望完全控制另一個進程的執行(如Debug進程),此時控制進程希望能夠攔截另一個進程的所有陷入和異常,并能夠及時知道它的狀態改變。

進程間通信的本質:

進程間通信的本質就是讓不同的進程看到同一份資源。

進程間通信的發展:

管道
System V進程間通信
POSIX進程間通信

進程間通信的分類:?

管道

  • 匿名管道
  • 命名管道

System V IPC

  • System V 消息隊列
  • System V 共享內存
  • System V 信號量

POSIX IPC

  • 消息隊列
  • 共享內存
  • 信號量
  • 互斥量
  • 條件變量
  • 讀寫鎖

管道:

認識管道:

由于進程間具有獨立性,想要實現進程間通信非常困難,想要實現進程間通信就必須借助第三方資源,讓兩個需要通信的進程都可訪問這個第三方資源,早期管道就是這樣的第三方資源來實現進程間通信。

管道是Unix中最古老的進程間通信的形式。
我們把從一個進程連接到另一個進程的一個數據流稱為一個“管道“

演示:

先來介紹兩個命令:

1.who

who指令可以用來顯示當前云服務器登錄的用戶數,一行顯示一個用戶。

如圖所示現在有2個用戶。?

?2.wc

wc指令可以查指定文件的計算文件的Byte數、字數、或是列數,若不指定文件名稱、或是所給予的文件名為"-",則wc指令會從標準輸入設備讀取數據

wc加上-l指令,計算指定文件的行數。

將上述兩個命令通過管道連接,就可以更準確地查出當前云服務器的登錄用戶:

who進程將數據寫入管道,wc從管道中讀取到數據,-l指令計算數據的行數,從而得出當前云服務器的登錄數。?

匿名管道:

匿名管道性質:?

匿名管道僅支持父子間進程通信。

當我們創建一個進程,在linux系統中它被如下圖進行管理:

我們再通過這個進程創建一個子進程,子進程繼承父進程的代碼和數據:

?沒錯,此時我們的父子進程能看到同一份資源,我們可以模擬一下通信,父進程往緩沖區寫入,子進程往緩沖區讀取,早期的工程師發現了這種現象,并且認為這是一種很好的進程間通信的方法,就在這種方法的基礎上進行了一下改動,創造了管道。

注意:

我們在進程間通信時,是沒必要對磁盤中的文件進行操作的,所以我們的管道沒必要與磁盤中的文件產生關聯。

文件級緩沖區是由操作系統來維護的,所以當父進程對其寫入時,是不會發生寫時拷貝的。

pipe函數:

int pipe(int pipefd[2]);

?pipe函數的參數是一個輸出型參數,數組pipefd中的兩個元素分別用來返回管道讀端和寫端的文件描述符:

數組元素含義
pipefd[0]管道讀端文件描述符
pipefd[1]管道寫端文件描述符

?匿名管道的使用:

注意下圖中的fd均指pipefd。

1.父進程用pipe函數創建管道。

2.父進程通過fork函數創建子進程。

3.假設我們讓子進程寫,父進程讀,所以我們要關閉不用的文件描述符,父進程關閉寫端,子進程關閉讀端。

?我們再站在文件描述符的角度深入理解:

匿名管道測試:?

現在用下述代碼測試匿名管道,父進程進行一直讀取,子進程進行一直寫入:

#include <iostream>
#include <cerrno>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>const int size = 1024;//子進程進行寫入
void SubProcessWrite(int wrd)
{std::string message = "father,i am your childen process! ";while(true){sleep(1);std::cout<<"childen begin write........."<<std::endl;static int cent = 0;pid_t id = getpid();//拼接消息std::string info = message;info += "my pid is ";info += std::to_string(id);info += ", cent: ";info += std::to_string(cent);//寫入write(wrd,info.c_str(),info.size());cent++;}
}
//父進程進行讀取
void FatherProcessReader(int rfd)
{char inbuffer[size];while(true){std::cout<<"father begin read,message:"<<std::endl;ssize_t n = read(rfd,inbuffer,sizeof(inbuffer) - 1);//讀取消息if(n > 0){inbuffer[n] = 0;//語言限制,在字符串最后加\0std::cout<<inbuffer<<std::endl;//打印消息}}
}
int main()
{int pipefd[2];int n = pipe(pipefd);//管道創建成功,返回0if(n != 0)//管道創建失敗{std::cerr<<"errno "<<errno<<"cerrstring: "<<strerror(errno)<<std::endl;}std::cout<<"讀端->pipefd[0]"<<pipefd[0]<<"寫端->pipefd[1]"<<pipefd[1]<<std::endl;sleep(1);pid_t id = fork();//創建子進程if(id == 0){//子進程進行寫入std::cout<<"子進程關閉不需要的fd了,準備寫消息了"<<std::endl;close(pipefd[0]);//關閉讀端SubProcessWrite(pipefd[1]);//子進程寫close(pipefd[1]);//任務完成關閉寫端exit(0);}//父進程std::cout<<"父進程關閉不需要的fd了,準備讀消息了"<<std::endl;close(pipefd[1]);//關閉寫端FatherProcessReader(pipefd[0]);//父進程讀close(pipefd[0]);//任務完成關閉讀端pid_t rid = waitpid(id,NULL,0);//父進程等待子進程,并回收return 0;
}

來看看運行結果:

?管道的4種情況:

1.寫端進程不寫,讀端進程一直讀,那么此時會因為管道里面沒有數據可讀,對應的讀端進程會被掛起,直到管道里面有數據后,讀端進程才會被喚醒。


2.讀端進程不讀,寫端進程一直寫,那么當管道被寫滿后,對應的寫端進程會被掛起,直到管道當中的數據被讀端進程讀取后,寫端進程才會被喚醒。


3.寫端進程將數據寫完后將寫端關閉,那么讀端進程將管道當中的數據讀完后,就會繼續執行該進程之后的代碼邏輯,而不會被掛起。


4.讀端進程將讀端關閉,而寫端進程還在一直向管道寫入數據,那么操作系統會將寫端進程殺掉。

管道的大小:

管道是有容量的,當管道被寫滿了,寫端將會阻塞或者失敗,查詢管道大小的方法有如下:

ulimit -a指令,查看當前資源限制。

從上圖可以算出管道的大小為512*8 = 4096字節。?

命名管道:

剛才介紹的匿名管道,只可用于父子進程間通信,如果兩個毫不相干的進程要實現通信該怎么辦呢?接下來就需要介紹一下命名管道了。

mkfifo函數:

mkfifo函數用于創建一個命名管道。

mkfifo的第一個參數表示要創建的命令管道文件,如果不帶路徑默認再當前文件夾下。

mkfifo的第二個參數表示管道的文件權限。

例如文件權限設置為0666,則理論創建的管道權限為

?但實際文件權限還會受文件默認掩碼umask影響,默認的umask是0002,我們實際的文件權限會先0666&(~umask),所以實際管道權限為0664:

mkfifo的返回值:?

管道創建成功返回0。

創建管道失敗返回-1,錯誤碼被設置。?

用命名管道實現serve&client通信

serve管理管道負責創建,銷毀和讀取消息,client負責往管道中寫入消息:

serve.cc:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>const std::string comm_name = "./myfifo";int main()
{//服務端創建命名管道int res = mkfifo(comm_name.c_str(),0666);if(res != 0)//創建失敗{perror("mkfifo");}//serve端打開管道int fd = open(comm_name.c_str(),O_RDONLY);if(fd < 0){std::cout<<"open file"<<errno<<std::endl;}//serve接受消息并打印char buffer[1024];while(true){std::cout<<"server begin read:"<<std::endl;ssize_t n = read(fd,buffer,sizeof(buffer)-1);if(n > 0)//讀取成功{buffer[n] = 0;std::cout<<buffer<<std::endl;}else if( n == 0){std::cout<<"read done"<<std::endl;break;}else{std::cout<<"read fail"<<errno<<std::endl;break;}}int n = unlink(comm_name.c_str());if(n != 0){perror("unlink");}return 0;
}

client.cc:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>const std::string comm_name = "./myfifo";int main()
{//client以寫打開管道int fd = open(comm_name.c_str(),O_WRONLY);if(fd < 0){std::cout<<"open fail"<<errno<<std::endl;}int cent = 100;sleep(5);while(cent--){sleep(1);std::cout<<"client begin write"<<std::endl;//消息拼接std::string message = "i sent a message ,cnet: ";message += std::to_string(cent);//寫入消息ssize_t n = write(fd,message.c_str(),sizeof(message));}return 0;
}

來看看運行結果:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/23927.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/23927.shtml
英文地址,請注明出處:http://en.pswp.cn/web/23927.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開源WebGIS全流程常用技術棧

1 數據生產 1.1 uDig uDig&#xff08;http://udig.refractions.net/&#xff09;是一個基于Java開源的桌面應用框架&#xff0c;它構建在Eclipse RCP和GeoTools&#xff08;一個開源的Java GIS包)上。可以進行shp格式地圖文件的編輯和查看&#xff1b;是一個開源空間數據查看…

?在哪些場景下,使用SOCKS5代理會特別有用?(socks5代理ip)?

SOCKS5代理作為網絡協議轉換的利器&#xff0c;其獨特功能在眾多實際場景中展現出了極大的價值。以下是幾個特定場景&#xff0c;其中SOCKS5代理的使用將變得尤為重要&#xff1a; 一、網絡安全與隱私訪問 1.高級滲透測試&#xff1a;在網絡安全領域&#xff0c;滲透測試人員…

Java 異常處理 - 自定義異常

在Java中&#xff0c;自定義異常是一種創建新異常類的方式&#xff0c;這些異常類繼承自Throwable類或其子類Exception&#xff08;或RuntimeException&#xff0c;如果它是運行時異常的話&#xff09;。自定義異常通常用于描述特定于應用程序的錯誤情況&#xff0c;以便為調用…

MS21112S單通道 LVDS 差分線路接收器

MS21112S 是一款單通道低壓差分信號 (LVDS) 線 路接收器。在輸入共模電壓范圍內&#xff0c;差分接收器可以 將 100mV 的差分輸入電壓轉換成有效的邏輯輸出。 該芯片可應用于 100Ω 的受控阻抗介質上&#xff0c;進行點對 點基帶數據傳輸。傳輸介質可以是印刷電路板、…

配音方面目前可以用AIGC替代嗎?( 計育韜老師高校公益巡講答疑實錄2024)

這是計育韜老師第 8 次開展面向全國高校的新媒體技術公益巡講活動了。而在每場講座尾聲&#xff0c;互動答疑環節往往反映了高校師生當前最普遍的運營困境&#xff0c;特此計老師在現場即興答疑之外&#xff0c;會盡量選擇有較高價值的提問進行文字答疑梳理。 *本輪巡講主題除了…

360誤刪掉的文件怎么恢復?3種文件找回辦法!

360是一款電腦安全輔助軟件&#xff0c;可以用它來清理垃圾、查殺病毒、修復系統等。然而&#xff0c;有時文件可能會被360誤認為是垃圾而自動清理&#xff0c;造成重要文件丟失&#xff0c;那么360刪掉的文件怎么恢復&#xff1f;下面&#xff0c;讓我們一起來看看如何恢復文件…

三維點云擬合平面推導及源代碼C++

1、背景介紹 實際中,很多人工構造物是由平面結構構造而成,如下圖所示,為一典型的由多個平面組成的人工構筑物。因此,根據離散點擬合成平面,獲取擬合平面方程,是點云數據處理中非常常見的數據處理操作。 2、平面擬合參數推導 基于若離散點,估算平面方程過程如下: 3、程序…

電子設計教學新篇章:SmartEDA引領學校教學升級風潮

在數字化時代的浪潮中&#xff0c;電子設計教學領域正迎來一場革命性的變革。SmartEDA&#xff0c;作為電子設計課程的新寵&#xff0c;以其高效、智能的特性&#xff0c;正成為學校教學升級的重要推手。它不僅極大地提升了電子設計的效率&#xff0c;還為學生們帶來了更為深入…

ChatGPT-4o提示詞的九大酷炫用法,你知道幾個?

ChatGPT-4o提示詞的九大酷炫用法&#xff0c;你知道幾個&#xff1f;&#x1f680; 博主貓頭虎的技術世界 &#x1f31f; 歡迎來到貓頭虎的博客 — 探索技術的無限可能&#xff01; 專欄鏈接&#xff1a; &#x1f517; 精選專欄&#xff1a; 《面試題大全》 — 面試準備的寶典…

xstream運用,JAVA對象轉xml,xml轉JAVA對象

目錄 xstream 優點&#xff1a; 缺點&#xff1a; XStream的應用場景 用到的依賴 代碼實現 xml標簽對應的實體類 Header Package Request Response TradeInfo 工具類 XmlUtils 執行結果 xstream XStream是一個Java類庫&#xff0c;主要用于將對象序列化為XML&#xf…

OV通配符ssl證書是什么

通配符https證書的產品比較豐富&#xff0c;為了方便區分&#xff0c;可以按照驗證方式將通配符https證書分為DV基礎型通配符https證書和OV企業型通配符https證書兩種。其中OV通配符https證書申請條件高&#xff0c;審核也比較嚴格&#xff0c;相比于DV基礎型通配符https證書&a…

IPv4 和 IPv6 是什么意思?它們之間的區別都有哪些?

什么是 IPv4 和 IPv6 什么是 IPv4 和 IPv6 呢&#xff1f;下面我們就來了解一下。 IPv4 就是互聯網協議第 4 版&#xff0c;是目前廣泛使用的網絡協議版本。它由互聯網工程任務組&#xff08;IETF&#xff09;在 1981 年開發完成。IPv4 使用 32 位地址&#xff0c;允許大約 4…

推薦系統三十六式學習筆記:原理篇.近鄰推薦07|人以群分,你是什么人就看到什么世界

目錄 協同過濾基于用戶的協同過濾背后的思想原理實踐1、構造矩陣2、相似度計算3、推薦計算4、一些改進 應用場景&#xff1a;總結 談及推薦系統&#xff0c;不得不說大名鼎鼎的協同過濾。協同過濾的重點在于協同&#xff0c;所謂協同&#xff0c;也就是群體互幫互助&#xff0c…

初級軟件測試快速入門

文章目錄 初級軟件測試-測試用例、缺陷報告的認識與使用軟件測試簡介測試分類模型質量模型測試模型 用例編寫的八大要素用例設計方法缺陷 初級軟件測試-測試用例、缺陷報告的認識與使用 軟件測試簡介 什么是軟件測試&#xff1f; 使用技術手段驗證軟件是否滿足需求 主流技能 …

關于 Vue.js 中`transition`組件使用:頁面切換動畫和標簽移動動畫都是要用到的

一、引言 在 Vue.js 中&#xff0c;transition組件提供了一種簡單而強大的方式來實現頁面過渡效果。它可以讓元素在狀態改變時&#xff0c;如進入或離開視圖時&#xff0c;以平滑的動畫方式進行過渡。通過transition&#xff0c;我們可以為應用增添更加生動和吸引人的用戶體驗…

Linux文件編碼格式為unknown 8bit

file -i 1.txt顯示文件編碼為unknown 8bit, 說明這個文件的編碼格式因為一些不明原因無法識別了。 可以嘗試用其他編輯器打開&#xff0c;來看一下編輯器最終是用什么編碼格式打開的。 vim :set filecodingnotepad 直接打開文件&#xff0c;右下角會顯示文件編碼 假設文件編…

《數學學習與研究》雜志是什么級別?知網收錄嗎?評職認可嗎?

《數學學習與研究》雜志是什么級別&#xff1f;知網收錄嗎&#xff1f;評職認可嗎&#xff1f; 《數學學習與研究》是由東北師范大學主管&#xff0c;吉林省數學會與東北師范大學出版社聯合主辦的省級優秀數學類期刊雜志。該雜志為半月刊&#xff0c;國際標準刊號為 ISSN1007-…

圖解通用網絡IO底層原理、Socket、epoll、用戶態內核態······

LInux 操作系統中斷 什么是系統中斷 這個沒啥可說的&#xff0c;大家都知道&#xff1b; CPU 在執行任務途中接收到中斷請求&#xff0c;需要保存現場后去處理中斷請求&#xff01;保存現場稱為中斷處理程序&#xff01;處理中斷請求也就是喚醒對應的任務進程來持有CPU進行需要…

《大宅門》特別活動走進李良濟,開啟探尋中醫藥文化之旅!

《大宅門》話劇將于6月14-16日在蘇州灣大劇院上演&#xff0c;為了讓大家了解到中醫藥知識&#xff0c;6月2日&#xff0c;李良濟攜手蘇州灣大劇院舉辦《大宅門》特別活動“探尋中醫藥文化之旅”&#xff01; 6月2日下午&#xff0c;大家一起走進李良濟&#xff0c;深度了解傳統…