程序間通訊(1) 管道

2021-08-02 10:27:19 字數 4155 閱讀 1870

linux下一切皆檔案,我們可以建立乙個管道檔案進行通訊,實際上是呼叫pipe函式在核心中開闢一塊緩衝區(稱為管道)用於通訊,管道是一種最基本的ipc機制,由pipe函式建立

#include

int pipe (int filedes[2]);

它有乙個讀端乙個寫端,然後通過filedes引數傳出給使用者程式兩個檔案描述符,filedes[0]指向管道的讀端,filedes[1]指向管道的寫端(很好記,就像0是標準輸入1是標準輸出一樣)。所以管道在使用者程式看起來就像乙個開啟的檔案,通過read(filedes[0]);或者write(filedes[1]);向這個檔案讀寫資料其實是在讀寫核心緩衝區。pipe函式調⽤用成功返回0,調⽤用失敗返回-1。

管道的種類

<1>普通管道:pipe也叫匿名管道

a.單向通訊

b.只有在具有親緣關係的程序間通訊

c.具有同步機制

d.它是一種面向位元組流的通訊服務

e.生命週期隨程序

<2>流管道:s_pipe

可以進行雙向傳輸,其他同上

<3>命名管道:name_pipe

可以使毫不相干的程序進行通訊,其他同匿名管道

單向通訊

#include 

#include

#include

#include

#include

int main()

pid_t id = fork();

if(id < 0)

else

if(id==0)

sleep(1);

i++;

}// close(_pipe[1]);

}else

close(_pipe[0]);

sleep(10);

if(waitpid(id,null,0)< 0)

}return

0;}

執行結果:

分析:父子程序進行單向通訊,子程序寫,父程序讀

使用管道需要注意以下四種特殊情況(假設都是阻塞i/o操作,沒有設定o_nonblock標誌)

1. 如果所有指向管道寫端的檔案描述符都關閉了,(管道寫端的引用計數為0),而仍然有程序從管道的讀端讀取資料,那麼管道中剩餘的資料都被讀取之後,再次read將會返回0,就像讀到檔案結尾一樣。也就是說,寫端不會寫,讀端讀完之後就會再等著寫端去寫,但是寫端關閉了啊,不會寫了,所以就出現上面說的情況。這就體現出了管道的同步機制。

如果有指向管道寫端的檔案描述符沒有關閉,(管道寫端的引用計數大於0)而持有管道寫端的程序也沒有向管道中寫資料,這時有程序管道讀端讀資料,那麼管道中剩餘的資料都被讀取後,再次read會阻塞,直到管道中有資料可讀了才讀取資料並返回。通俗講就是,讀端讀資料,一直讀,但是寫端不寫了,而且寫端並沒有關閉,所以這時讀端就會一直等著寫端去寫。這就造成了阻塞式等待。

如果所有指向管道讀端的檔案描述符都關閉了(管道讀端的引用計數為0),這時有程序向管道的寫端寫資料,那麼該程序會收到sigpipe,通常會導致程序異常終止。所以程序就會異常退出了。

如果有指向管道讀端的檔案描述符沒關閉(管道讀端的引用計數大於0)而持有管道讀端的程序也沒有從管道中讀取資料,這時有程序向管道寫端寫資料,那麼在管道寫滿時再寫將會阻塞,直到管道中有了空位置才寫入並返回,也就是管道的同步機制。

雙向通訊

命名管道:

命名管道可以在不相關的程序之間和不同計算機之間使用,伺服器建立命名管道時給它指定乙個名字,任何程序都可以通過該名字開啟管道的另一端,根據給定的許可權和伺服器程序通訊。而且,fifo總是按照先進先出的原則工作,第乙個被寫入的資料首先從管道中讀出。

建立:

#include

#include

int mknod(const

char*path,mode_t mod,dev_t dev);

int mkfifo(const

char*path,mode_t mode);

引數:path為建立的命名管道的路徑名,mod為建立命名管道的模式,指明其訪問許可權,dev為裝置值,該值檔案建立的種類,它只在建立裝置檔案時才會用到。這兩個函式掉用成功返回0,失敗都返回-1.

命名管道實現通訊的**:

這裡寫**片.phony:all

all:server

client

client:client.c

gcc -o $@ $^

server:server.c

gcc -o $@ $^

.phony:clean

clean:

rm -f server

client

comm.h

#ifndef __comm_h_

#define __comm_h_

#include

#include

#include

#include

#include

#include

#include

#define onepath "./fifo_one.c"

#define twopath "./fifo_two.c"

#define size 1000

#endif

client.c

#include "comm.h"

int main()

int fdone = open(onepath,o_wronly);

int fdtwo = open(twopath,o_rdonly);

if((fdone<0)||(fdtwo<0))

char buf[size];

memset(buf,'\0',sizeof(buf));

while(1)

printf("guangyuan<<

int rettwo = read(fdtwo,buf,sizeof(buf));

if(rettwo<0)

printf("%s\n",buf);

}close(fdone);

close(fdtwo);

return

0;}

server.c

#include "comm.h"

int main()

int fdone = open(onepath,o_rdonly);

int fdtwo = open(twopath,o_wronly);

if((fdone<0)||(fdtwo<0))

char buf[size];

memset(buf,'\0',sizeof(buf));

while(1)

printf("%s\n",buf);

printf("megnnan->>>");

scanf("%s",buf);

int rettwo = write(fdtwo,buf,strlen(buf)+1);

if(rettwo<0)

}close(fdone);

close(fdtwo);

return

0;}

結果:

注意

命名管道的使用和匿名管道基本相同,只是在使用命名管道之前首先要使用open函式開啟,因為命名管道是存在於硬碟上的檔案,而管道是存在於記憶體中的特殊檔案。

需要注意,使用open的幾點:

1. 呼叫open()開啟命名管道可能會被阻塞,但是如果同時用讀寫方式(o_rdwr)開啟,則一定不會造成阻塞。

2. 如果以唯讀方式(o_rdonly)開啟,則呼叫open()函式的程序將會被阻塞直到有寫才能開啟管道。

3. 同樣,以寫方式(o_wronly)開啟也會阻塞直到有讀方式開啟管道。

匿名管道(程序間通訊1)

前提 原來也寫過匿名管道的 但是總覺得沒有了解過底層,只是知道 管道是乙個檔案它存在與記憶體上,一般父子程序之間使用但是並沒有研究過底層。所以這次參考linux核心情景分析這本書進行整理。因為對linux虛擬檔案系統的了解因此這次對於匿名管道也有多幫助畢竟他也是個檔案哈哈哈哈哈開始吧 它的系統呼叫是...

程序間通訊(1) 管道pipe

學習linux的知識中,有乙個特別重要的概念叫 程序 而要進行程序間通訊時,有乙個特別重要的概念就是 管道,今天,我們就來學習一下什麼是管道,它能又幹什麼呢?一 概念 管道 把乙個程序連線到另外乙個程序的乙個資料流稱為管道。其實,我們聯絡現實生活,自來水管可以將我們使用者和供水站連線起來,通過管道運...

Linux 程序間通訊 1 管道

1.匿名管道 include 功能 建立匿名管道 int pipe int fd 2 引數fd 檔案描述符陣列,其中fd 0 表示讀端,fd 1 表示寫端 返回值 成功返回0,失敗返回 1管道並非屬於程序的資源,屬於作業系統,父子程序共享用於管道的檔案描述符,所以兩個程序通過作業系統提供的記憶體空間...