天天看點

Linux程序間通訊(2):管道、共享記憶體

三、管道

        管道是一種半雙工通信,即允許信号在兩個方向上傳輸,但某一時刻隻允許信号在一個信道上單向傳輸。管道是把一個程式的輸出直接連接配接到另一個程式的輸入,常說的管道多是指無名管道,無名管道隻能用于父子的程序之間,這是它與有名管道的最大差別。

(1)、管道有固定大小:實際上,管道是一個固定大小的緩沖區

(2)、管道讀取程序比檔案讀取程序快:當所有目前程序資料已被讀取時,管道變空。當這種情況發生時,管道一個随後的read()調用将預設地被阻塞,等待某些資料被寫入,而檔案read()調用傳回檔案結束。

 注:從管道讀資料是一次性操作,資料一旦被讀,它就從管道中被抛棄,釋放空間以便寫更多的資料。

(3)、管道檔案存儲在磁盤,普通檔案存儲在記憶體裡面。

Linux程式間通訊(2):管道、共享記憶體

1、有名管道:

在檔案系統中存在一個檔案辨別(檔案名),但是管道檔案不占據磁盤的空間,需要傳遞的資料緩存在記憶體區域。

具體操作有:

建立:mkfifo 檔案名

打開:int open(char &path,int flag,);

在僅僅一端打開時,open會阻塞。直到有讀端、寫端,open才會傳回 

讀:int read(int fd,void *buf,size_t size);

read阻塞有兩種情況:一種是管道中沒有資料,另一種是管道中有資料,但所有的寫端關閉

寫:int write(int fd,void *buf,size_t size);

wirte阻塞有兩種情況:一種是管道緩存區滿,另一種是管道中有空間,但所有的讀端關閉

關閉:int close(int fd);

注:讀和寫的次數沒有必然關系

2、無名管道

沒有名稱的管道(沒有管道檔案存在)。fork 之後,父子程序對于檔案描述符共享

限制:隻能應用于父子程序之間完成程序間通訊,并且管道的建立與打開必須在fork 之前完成。

Linux程式間通訊(2):管道、共享記憶體

 具體操作:

建立和打開:int pipe(int fds[2]);           pipe 函數建立一個無名管道,fds[0]指向讀端,fds[1]指向寫端。

因為管道是半雙工通訊,是以在fork之後,父子程序分别關閉一對讀寫;

讀資料:read(int fds,void *buff,size_t size);       read傳回值為0,則讀端通訊完成

寫資料:write(int fds,void* buff,size_t size);      若子程序不關閉寫端,當父程序結束,read傳回 ??

關閉檔案:close(fds);

四、共享記憶體:是最快的一種 IPC

共享記憶體是最快IPC原因:

(1)、在通訊之前通路核心對象,需要使用者态切換核心态,但真正發送資料時,直接通過指針操作空間,不需要使用者态切換核心态

(2)、共享記憶體可以直接通過指針将資料寫到共享記憶體區域,接收方直接通過指針操作共享記憶體區域的資料,相比于管道、消息隊列,共享記憶體少了兩次資料的拷貝

Linux程式間通訊(2):管道、共享記憶體

注:兩個程序的虛拟位址空間相等或者不相等,對于共享記憶體而言,無影響。

虛拟位址需要通過程序頁表,進行頁面映射才能找到實體内記憶體空間

注:本篇部落格内容部分取自https://blog.csdn.net/century_sunshine/article/details/79882445

共享記憶體共享的是實體記憶體空間

具體操作:

1.shmget函數:建立共享記憶體

int shmget(key_t key,size_t size,int shmflg);
           

失敗傳回-1 成功傳回辨別符shmid

2.shmat函數:第一次建立共享記憶體時,它不被任何通路,要想啟動對該共享記憶體的通路,必須将其連接配接到一個程序的位址空間中,這項工作由shmat函數完成。

void *shmat(int shmid,const void * shm_addr,int shmflg);
           

失敗傳回-1  成功傳回指向共享記憶體第一個位元組的指針

3.将共享記憶體從目前程序中分離

int shmdt(void *shmatrt)
           

失敗傳回-1,成功為0。

4.删除核心對象、且立即删除

int shmctl(int shm_id,int command,struct shmid_ds*buf);
           

5、優點:我們可以看到使用共享記憶體進行程序間的通信真的是非常友善,而且函數的接口也簡單,資料的共享還使程序間的資料不用傳送,而是直接通路記憶體,也加快了程式的效率。同時,它也不像匿名管道那樣要求通信的程序有一定的父子關系。

6、缺點:共享記憶體沒有提供同步的機制,這使得我們在使用共享記憶體進行程序間通信時,往往要借助其他的手段來進行程序間的同步工作。

繼續閱讀