linux——IPC 進程間通信

?IPC ? 進程間通信 ?interprocess communicate

IPC(Inter-Process Communication),即進程間通信,其產生的原因主要可以歸納為以下幾點:

進程空間的獨立性

  1. 資源隔離:在現代操作系統中,每個進程都擁有自己獨立的代碼和數據空間。這種隔離機制確保了進程之間的安全性和穩定性,但同時也使得進程間無法直接訪問對方的資源。

  2. 資源無法共享:由于進程空間的獨立性,一個進程無法直接讀取或修改另一個進程的內存空間中的數據。這種情況下,如果需要進行數據交換或共享資源,就需要通過特定的機制來實現。

進程間協作的需求

  1. 數據交換:在多進程操作系統中,不同的進程可能需要交換數據以完成共同的任務。例如,一個進程可能負責生成數據,而另一個進程則負責處理這些數據。為了實現這種數據交換,就需要使用IPC機制。

  2. 資源共享:進程間通信還允許進程共享資源,如文件、數據庫、內存等。通過IPC,進程可以協調對共享資源的訪問,避免沖突和競爭條件。

  3. 任務協調:在分布式系統或并發編程中,多個進程可能需要協同工作以完成復雜的任務。IPC提供了進程間同步和互斥的機制,確保任務能夠按照預定的順序和條件執行。

IPC的必要性

  1. 提高系統并發性:通過IPC,多個進程可以并行處理不同的任務,從而提高系統的并發處理能力。

  2. 優化資源利用:IPC允許進程共享資源,減少了資源的重復分配和浪費,提高了資源利用率。

  3. 實現復雜功能:在構建復雜的軟件系統時,往往需要多個進程協同工作。IPC為這些進程之間的通信和協作提供了必要的支持。

IPC的實現方式

IPC的實現方式多種多樣,包括但不限于以下幾種:

  1. 管道(Pipe):一種單向通信方式,常用于具有親緣關系的進程間通信。

  2. 消息隊列(Message Queue):允許多個進程從同一個隊列中讀取數據,具有獨立性和異步性。

  3. 共享內存(Shared Memory):一段可以被多個進程同時訪問的物理內存區域,提高了進程間的數據交換效率。

  4. 信號(Signal):一個進程向另一個進程發送信號來傳遞某種信息或通知某個事件的發生。

  5. 套接字(Socket):用于不同主機之間的進程通信,提供了網絡通信的能

管道==》無名管道、有名管道

?? ?無名管道 ===》pipe ==》只能給有親緣關系進程通信
?? ?有名管道 ===》fifo ==》可以給任意單機進程通信


?? ?管道的特性:
?? ?1、管道是 半雙工的工作模式(收或者發)
?? ?2、所有的管道都是特殊的文件不支持定位操作。不支持lseek->> fd ?fseek ->>FILE*?
?? ?3、管道是特殊文件,讀寫使用文件IO。fgets,fread,fgetc,

? ? ? ?一般情況下使用open,read,write,close;

主要看是否是二進制文件,如果是文本文件使用fges之類的標準io。

注意事項:??
? ?1,讀端存在,一直向管道中去寫,超過64k,寫會阻塞。(寫的快,讀的慢)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[]="hello,world";close(pipefd[0]);sleep(3);write(pipefd[1],buf,strlen(buf));}else if(0 == pid){close(pipefd[1]);char buf[100]={0};read(pipefd[0],buf,sizeof(buf));printf("pipe %s\n",buf);}else {perror("fork");exit(1);}return 0;
}

?? 2,寫端是存在的,讀管道,如果管道為空的話,讀會阻塞(讀的快,寫的慢)

? ? 讀阻塞和寫阻塞都是正常情況。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[1024]={0};close(pipefd[0]);memset(buf,'a',1024);int i = 0 ;for(i=0;i<65;i++){write(pipefd[1],buf,sizeof(buf));printf("i is %d\n",i);}}else if(0 == pid){close(pipefd[1]);char buf[100]={0};
//        read(pipefd[0],buf,sizeof(buf));//      printf("pipe %s\n",buf);while(1)sleep(1);}else {perror("fork");exit(1);}return 0;
}

??3.管道破裂,讀端關閉,寫管道。

(會導致寫關閉,接收端關閉,導致發送端關閉)類似于段錯誤

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[]="hello,world";close(pipefd[0]);sleep(3);// 管道破裂 gdb  跟蹤write(pipefd[1],buf,strlen(buf));printf("aaaa\n");}else if(0 == pid){close(pipefd[1]);close(pipefd[0]);}else {perror("fork");exit(1);}return 0;
}


?? 4. read 0 ,寫端關閉,如果管道沒有內容,read 0 ;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[]="hello,world";close(pipefd[0]);write(pipefd[1],buf,strlen(buf));write(pipefd[1],buf,strlen(buf));close(pipefd[1]);}else if(0 == pid){close(pipefd[1]);char buf[5]={0};while(1){//memset(buf,0,5);bzero(buf,sizeof(buf));int rd_ret = read(pipefd[0],buf,sizeof(buf)-1);if(rd_ret<=0){break;}printf("pipe %s\n",buf);}}else {perror("fork");exit(1);}return 0;
}

?if(rd_ret<=0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }

如果讀端進程調用read()函數從管道中讀取數據,并且管道已經為空(即沒有任何待讀取的數據),同時寫端已經被關閉,那么read()函數將會立即返回,并且返回值為0。這個返回值0是一個特殊的信號,它告訴讀端進程,管道的寫端已經被關閉,并且管道中沒有更多的數據可以讀取了。

使用框架:
?? ?創建管道 ==》讀寫管道 ==》關閉管道

1、無名管道 ===》管道的特例 ===>pipe函數
?? ?特性:
?? ?1.1 ?親緣關系進程使用
?? ?1.2 ?有固定的讀寫端

? ?

流程:
?? ?創建并打開管道: pipe函數

先創建管道再fork();

關閉管道1或者0用,close(xx);
#include <unistd.h>
int pipe(int pipefd[2]);
功能:創建并打開一個無名管道
參數:pipefd[0] ==>無名管道的固定讀端
?? ? ?pipefd[1] ==>無名管道的固定寫端
返回值:成功 0
?? ??? ?失敗 -1;

注意事項:
?? ?1、無名管道的架設應該在fork之前進行。
?? ?
無名管道的讀寫:===》文件IO的讀寫方式。
?? ?讀: read()
?? ?寫: write()

關閉管道: close();

通過管道的方式實現文件的復制:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){close(pipefd[0]);int fd =  open("/home/linux/1.png",O_RDONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[4096]={0};int rd_ret = read(fd,buf,sizeof(buf));if(rd_ret<=0){break;}write(pipefd[1],buf,rd_ret);}close(fd);close(pipefd[1]);}else if(0 == pid){close(pipefd[1]);int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);if(-1==fd){perror("open");exit(1);}while(1){char buf[1024]={0};int rd_ret = read(pipefd[0],buf,sizeof(buf));if(rd_ret<=0){break;}write(fd,buf,rd_ret);}close(fd);close(pipefd[0]);}else {perror("fork");exit(1);}return 0;
}


驗證如下問題:
1、父子進程是否都有fd[0] fd[1],
? ?如果在單一進程中寫fd[1]能否直接從fd[0]中讀到。

? ?可以,寫fd[1]可以從fd[0]讀

2、管道的數據存儲方式是什么樣的
? ?數據是否一直保留?
?? ?棧, 先進后出
? ?隊列形式存儲 讀數據會剪切取走數據不會保留
? ?先進先出

3、管道的數據容量是多少,有沒有上限值。
?? ?操作系統的建議值: 512* 8 = 4k
?? ?代碼測試實際值: ? 65536byte= 64k

4、管道的同步效果如何驗證?讀寫同步驗證。
?? ?讀端關閉能不能寫? 不可以 ===>SIGPIPE 異常終止 (觸發管道破裂)
?? ?寫端關閉能不能讀? 可以,取決于pipe有沒有內容,===>read返回值為0 不阻塞

?? ?結論:讀寫端必須同時存在,才能進行
?? ??? ? ?管道的讀寫。


5、固定的讀寫端是否就不能互換?
?? ?能否寫fd[0] 能否讀fd[1]? ? 不可以,是固定讀寫端。

?? ?
練習:
?? ?如何用管道實現一個雙向通信功能
?? ?將從父進程發送的消息在發回給父
?? ?進程。
?? ?
?? ?
?? ?pipe,
?? ?
?? ?fork()
?? ?
?? ?if(pid>0)
?? ?{
?? ??? ?read(file,,)
?? ??? ?wirte(fd[1]);
?? ?}
?? ?
?? ?if(0 == pid)
?? ?{
?? ??? ??? ?read(fd[0]);
?? ??? ??? ?write(newfile);
?? ?}
?? ?
?? ?
?? ?
?? ?person
?? ?{
?? ??? ?char name[];
?? ??? ?int age;
?? ??? ?char phone;
?? ?}
?? ?
?? ?
?? ?pipe[];
?? ?fork();
?? ?
?? ?> 0
?? ?fgets 獲得輸入
?? ?填結構體,
?? ?寫入管道,
?? ?==0
?? ?
?? ?read,
?? ?填結構體,,
?? ?
?? ?顯示到。。。
?? ?
?? ?hello
?? ?pipe:hello?
?? ?wordld
?? ?pipe2 ::world;
?? ?
?? ?
?? ?
?? ?
?? ?
?? ?

有名管道===》fifo ==》有文件名稱的管道。
?? ??? ??? ??? ??? ? ?文件系統中可見

框架:
?? ?創建有名管道 ==》打開有名管道 ==》讀寫管道
?? ?==》關閉管道 ?==》卸載有名管道

1、創建:mkfifo
#include <sys/types.h>
#include <sys/stat.h>
?remove();

int mkfifo(const char *pathname, mode_t mode);
功能:在指定的pathname路徑+名稱下創建一個權限為
? ? ? mode的有名管道文件。
參數:pathname要創建的有名管道路徑+名稱
?? ? ?mode ?8進制文件權限。
返回值:成功 0
?? ??? ?失敗 ?-1;

2、打開有名管道 open
?? ?注意:該函數使用的時候要注意打開方式,
?? ?因為管道是半雙工模式,所有打開方式直接決定
?? ?當前進程的讀寫方式。
?? ?一般只有如下方式:
?? ?int fd-read = open("./fifo",O_RDONLY); ==>fd 是固定讀端
?? ?int fd-write = open("./fifo",O_WRONLY); ==>fd 是固定寫端

?? ?不能是 O_RDWR 方式打開文件。
?? ?不能有 O_CREAT 選項,因為創建管道有指定的mkfifo函數


3、管道的讀寫: 文件IO

?? ?讀: read(fd-read,buff,sizeof(buff));
?? ?寫: write(fd-write,buff,sizeof(buff));

4、關閉管道:
?? ??? ?close(fd);

5、卸載管道:remove();
?? ??? ?int unlink(const char *pathname);
?? ??? ?功能:將指定的pathname管道文件卸載,同時
?? ??? ??? ? ?從文件系統中刪除。
?? ??? ?參數: ptahtname 要卸載的有名管道?
?? ??? ?返回值:成功 0
?? ??? ??? ??? ?失敗 ?-1;

open會阻塞,等到另一端讀端打開,解除阻塞。

函數是否會阻塞,具體根據操作的對象有關。


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在錯誤,讓程序繼續運行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}//open 會阻塞,等到另一端讀段打開,解除阻塞int fd = open("myfifo",O_WRONLY);if(-1 == fd){perror("open");exit(1);}char buf[256]="hello,fifo,test";write(fd,buf,strlen(buf));close(fd);return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在錯誤,讓程序繼續運行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}int fd = open("myfifo",O_RDONLY);if(-1 == fd){perror("open");exit(1);}char buf[256]={0};read(fd,buf,sizeof(buf));printf("fifo %s\n",buf);close(fd);//remove("myfifo");return 0;
}

remove可以在命令行調用。

運行方法:

練習:
?? ?編寫一個非親緣關系進程間通信程序,可以從
?? ?A程序向B程序連續發送不同的數據,并從B中
?? ?將發送的信息打印輸出,當雙方收到quit的時候
?? ?程序全部退出。

思考題:
?? ?是否每次啟動程序必須進行有名管道的創建工作
?? ?能否有一個獨立的維護工具,可以任意創建并刪除
?? ?有名管道?
?? ?比如:
?? ??? ?./fifo_tool -A fifo ?==>創建一個有名管道fifo
?? ??? ?./fifo_tool -D fifo ?==>刪除一個有名管道fifo

作業:

?? ?有名管道的操作函數封裝:
?? ?int fifo_read(char *fifoname,void *s,int size);
?? ?int fifo_write(char *fifoname,void *s,int size);

?? ?編寫測試程序驗證以上兩個函數效果。

?? ?gstream

? 有名管道 ===》

?? ?1、是否需要同步,以及同步的位置。
?? ??? ?讀端關閉 是否可以寫,不能寫什么原因。
?? ??? ?寫端關閉 是否可以讀。

?? ??? ?結論:有名管道執行過程過必須有讀寫端同時存在。
?? ??? ??? ? ?如果有一端沒有打開,則默認在open函數部分阻塞。

?? ?2、有名管道是否能在fork之后的親緣關系進程中使用。
?? ??? ?結論: 可以在有親緣關系的進程間使用。
?? ??? ?注意: 啟動的次序可能會導致其中一個稍有阻塞。

?? ?3、能否手工操作有名管道實現數據的傳送。
?? ??? ?讀: cat ?fifoname
?? ??? ?寫: echo "asdfasdf" > fifoname

?

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

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

相關文章

圖解 Kafka 架構

寫在前面 Kafka 是一個可橫向擴展&#xff0c;高可靠的實時消息中間件&#xff0c;常用于服務解耦、流量削峰。 好像是 LinkedIn 團隊開發的&#xff0c;后面捐贈給apache基金會了。 kafka 總體架構圖 Producer&#xff1a;生產者&#xff0c;消息的產生者&#xff0c;是消息的…

【高考志愿】測繪科學與技術

目錄 一、專業介紹 1.1 專業概述 1.2 專業方向 1.3 課程內容 二、就業前景 三、報考注意事項 四、測繪科學與技術專業排名 五、職業規劃與未來發展 高考志愿選擇測繪科學與技術專業&#xff0c;對于許多有志于空間信息技術領域發展的學生來說&#xff0c;無疑是一個極具…

怎么把錄音轉文字?推薦幾個簡單易操作的方法

在小暑這個節氣里&#xff0c;炎熱的天氣讓人分外渴望效率up&#xff01;Up&#xff01;Up&#xff01; 對于那些在會議或課堂中急需記錄信息的朋友們&#xff0c;手寫筆記的速度往往難以跟上講話的節奏。此時&#xff0c;電腦錄音轉文字軟件就像一陣及時雨&#xff0c;讓記錄…

PHP pwn 學習 (1)

文章目錄 A. PHP extensions for C1. 運行環境與工作目錄初始化2. 構建與加載3. 關鍵結構定義PHP_FUNCTIONINTERNAL_FUNCTION_PARAMETERSzend_execute_data等ZEND_PARSE_PARAMETERS_START等zend_parse_arg_stringzend_module_entryzend_function_entry等PHP類相關 原文鏈接&…

Python 作業題1 (猜數字)

題目 你要根據線索猜出一個三位數。游戲會根據你的猜測給出以下提示之一&#xff1a;如果你猜對一位數字但數字位置不對&#xff0c;則會提示“Pico”&#xff1b;如果你同時猜對了一位數字及其位置&#xff0c;則會提示“Fermi”&#xff1b;如果你猜測的數字及其位置都不對&…

Flower花所:穩定運營的數字貨幣交易所

Flower花所是一家穩定運營的數字貨幣交易所&#xff0c;致力于為全球用戶提供安全、高效的數字資產交易服務。作為一家長期穩定運營的數字貨幣交易平臺&#xff0c;Flower花所以其可靠的技術基礎和優質的客戶服務而聞名。 平臺穩定性與可靠性&#xff1a; 持續運營&#xff1a;…

Vue前端練習

此練習項目只涉及前端&#xff0c;主要是vue和ElementUI框架的使用。&#xff08;ElementUI官網&#xff1a;Element - The worlds most popular Vue UI framework&#xff09; 一、環境準備 安裝idea 安裝Node.js 一鍵式安裝(不需要做任何配置) npm -v&#xff08;也可用nod…

mysql-sql-第十五周

學習目標&#xff1a; sql 學習內容&#xff1a; 41.查詢沒有學全所有課程的同學的信息 select *from students where students.stunm not in (select score.stunm from score group by score.stunm having count(score.counm) (select count(counm) from course)) 42.查詢…

數據結構_線性表

線性表的定義和特點 線性表是具有相同特性的數據元素的一個有限序列 :線性起點/起始節點 :的直接前驅 :的直接后繼 :線性終點/終端節點 n:元素總個數,表長 下標:是元素的序號,表示元素在表中的位置 n0時稱為空表 線性表 由n(n>0)個數據元素(結點),組成的有限序列 將…

安卓模擬器如何修改ip地址

最近很多老鐵玩游戲的&#xff0c;想多開模擬器一個窗口一個IP&#xff0c;若模擬器窗口開多了&#xff0c;IP一樣會受到限制&#xff0c;那么怎么更換自己電腦手機模擬器IP地址呢&#xff0c;今天就教大家一個修改模擬器IP地址的方法&#xff01;廢話不多說&#xff0c;直接上…

Matlab 中 fftshift 與 ifftshift

文章目錄 【 1. fftshift、ifftshift 的區別】【 2. fftshift(fft(A)) 作圖 】【 3. fftshift(fft(A)) 還原到 A 】Matlab 直接對信號進行 FFT 的結果中,前半部分是正頻,后半部分是負頻,為了更直觀的表示,需要將 負頻 部分移到 前面。【 1. fftshift、ifftshift 的區別】 M…

alibaba EasyExcel 簡單導出數據到Excel

導入依賴 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>4.0.1</version> </dependency> 1、alibaba.excel.EasyExcel導出工具類 import com.alibaba.excel.EasyExcel; import …

探索哈希函數:數據完整性的守護者

引言 銀行在處理數以百萬計的交易時&#xff0c;如何確保每一筆交易都沒有出錯&#xff1f;快遞公司如何跟蹤成千上萬的包裹&#xff0c;確保每個包裹在運輸過程中沒有丟失或被替換&#xff1f;醫院和診所為龐大的患者提供有效的醫療保健服務&#xff0c;如何確保每個患者的醫療…

假陽性和假陰性、真陽性和真陰性

在深度學習的分類問題中&#xff0c;真陽性、真陰性、假陽性和假陰性是評估模型性能的重要指標。它們的定義和計算如下&#xff1a; 真陽性&#xff08;True Positive, TP&#xff09;&#xff1a; 定義&#xff1a;模型預測為正類&#xff08;陽性&#xff09;&#xff0c;且實…

電梯修理升級,安裝【電梯節能】能量回饋設備

電梯修理升級&#xff0c;安裝【電梯節能】能量回饋設備 1、節能率評估 15%—45% 2、降低機房環境溫度&#xff0c;改善電梯控制系統的運行環境&#xff1b; 3、延長電梯使用壽命&#xff1b; 4、機房可以不需要使用空調等散熱設備的耗電&#xff0c;間接節省電能。 歡迎私詢哦…

智能數字人系統的主要功能

智能數字人系統或虛擬數字人系統&#xff0c;是指利用人工智能技術構建的虛擬人物形象&#xff0c;能夠與人進行自然交互的系統。數字人系統的主要功能包括以下幾個方面。北京木奇移動技術有限公司&#xff0c;專業的軟件外包開發公司&#xff0c;歡迎交流合作。 1. 語言理解與…

昇思25天學習打卡營第2天|初學入門

昇思25天學習打卡營第2天 文章目錄 昇思25天學習打卡營第2天網絡構建定義模型類模型層nn.Flattennn.Densenn.ReLUnn.SequentialCellnn.Softmax 模型參數 函數式自動微分函數與計算圖微分函數與梯度計算Stop GradientAuxiliary data神經網絡梯度計算 問題集合打卡記錄 網絡構建 …

橋接模式與適配器模式

一、共性和區別 橋接設計模式和適配器設計模式的共同點和明顯&#xff0c;它們都是使兩種不同的類配合工。 二者的區別在于&#xff0c;適配器模式是將已有的兩個不同接口接口組合到一起&#xff0c;使得適配器同時擁有兩個不同接口的功能&#xff0c;其目的是使兩個不兼…

Spring Boot與微服務治理框架的集成方法

Spring Boot與微服務治理框架的集成方法 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 在當今快速發展的軟件開發領域&#xff0c;微服務架構因其靈活性、可…

華為DCN之:SDN和NFV

1. SDN概述 1.1 SDN的起源 SDN&#xff08;Software Defined Network&#xff09;即軟件定義網絡。是由斯坦福大學Clean Slate研究組提出的一種新型網絡創新架構。其核心理念通過將網絡設備控制平面與數據平面分離&#xff0c;從而實現了網絡控制平面的集中控制&#xff0c;為…