程序間通訊 管道和FIFO

2021-06-07 19:42:01 字數 4100 閱讀 5202

程序間通訊 管道和

fifo

管道,顧名思義就是像水管一樣,水管是用來流通水的,而對與管道來說,做為程序間通訊的一種方式,傳送的是資料而已。對於管道來說,沒有名字,在程式內部以識別符號進行識別,這也就注定了管道只能用於有親緣關係的各個程序間使用。但是這一缺點可以通過

fifo

,又程為有名管道來彌補,先介紹一下管道的基本函式。

#include

intpipe(int fd[2]);

pipe

函式用於管道的建立,函式返回兩個檔案描述符,

fd[0]

用來開啟讀和

fd[1]

用來開啟寫

,管道是單個程序建立的,但是很少在單個程序之間使用,大部分的使用例子如下,父程序建立了乙個管道,通過

fork

呼叫建立了子程序,子程序擁有父程序開啟管道的描述符,然後雙方一方用於從管道中讀出資料,另一方用於從管道中寫入資料,以此來進行程序之間的通訊。

下面寫乙個程式,完成如下功能,客戶服務程式從標準輸入讀取檔案路徑名,然後通過管道傳送給伺服器,然後伺服器呼叫系統函式讀取檔案內容,然後通過管道返回給客戶端,客戶端收到內容以後輸出到標準輸出或者標準錯誤上去,由於雙方都需要讀寫,所以需要使用雙管道進行通訊

#include#include#include#include#include#include#includeint main(int argc,char *argv)

close(fone[0]);

close(ftwo[1]);

client(fone[1],ftwo[0]);//呼叫客戶端程式

waitpid(childfd,null,0);

return 0;

} void server(int readfd,int writefd)

if((fd=open(buf,o_rdonly))<0)//開啟檔案

else

}void client(int writefd,int readfd)

標準

i/o函式庫提供了另外函式對管道進行操作

#include

file *popen(const char *command

,const char *type);

int pclose(file *stream);

popen

建立了乙個管道,並啟動另外乙個程序,

command

是shell

命令,如果

type為r

,那麼呼叫程序讀

command

的標準輸出,如果

type是w

,呼叫程序往

command

寫。這個函式使用起來還是比較方便的,個人覺得比exec函式更加容易控制,不過對於popen函式而言,只能重定向標準輸入和標準輸入,如果是標準出錯的話,還是會輸出到程式本書的標準出錯中去的。

管道沒有名字,因此只能用於有親緣關係的程序之間使用,

fifo

類似與管道,先進先出,單項資料流,與管道不同的就是能夠實現無親緣關係之間通訊。

#include

#include

int mkfifo(const char *pathname,mode_t mode);

mkfifo

用於管道的建立

pathname

是unix

路徑名,

mode

用於指定許可權位,定義在

sys/stat.h

中,隱含指定了

o_creat|o_excl

如果沒有的話建立,如過存在的話,返回錯誤。

我們可以用管道重新寫上面的客戶伺服器模式,只需要把建立兩個管道,換成建立兩個

fifo

就行了,

fifo

以pathname

為引數名建立以後開啟進行通訊。

關於管道和

fifo

阻塞的問題。如果乙個函式讀取乙個阻塞的管道或者

fifo

的話,如果該管道裡面沒有資料,那麼讀資料掛起,一直到管道內部有資料為止,如果設定成非阻塞的話,那麼沒有資料的話讀取返回乙個錯誤。

fifo

的阻塞標誌可以在

open

的時候指定。

open(fifo,o_wronly|o_nonblock,0)

;o_nonblock

非阻塞標誌設定,可以進行與或;對於管道來說,沒有名字也就沒有辦法開啟,可以用

fcntl

來獲取和設定

flag=fcntl(fd,f_getfl,0);

用來獲取標誌位 與或以後用

fcntl(fd,f_setfl,flag);

進行設定。

下面就寫乙個無親源關係的客戶伺服器程式,伺服器以公共的名字建立

fifo

,客戶以一定的規則加上自己的

pid建立自己的

fifo

。客戶向伺服器傳送自己

pid和檔名,伺服器返回檔案的內容到客戶的有名管道中,供客戶讀出。

伺服器端程式:#include#include#include#include#include#include#define flag o_creat|o_excl

#define mode s_irusr|s_iwusr|s_irgrp|s_iwgrp

int main()

fdread=open("/tmp/server.fifo",o_rdonly);

fdwrite=open("/tmp/server.fifo",o_wronly);

read(fdread,buff,1024);

sscanf(buff,"%ld %s",&pid,filename);

sprintf(usrfile,"/tmp/fifo.client.%ld",(long)pid);

if((usrfd=open(usrfile,o_wronly))<0)

if((fdfile=open(filename,o_rdonly))<0)

while((len=read(fdfile,buff,1024))>0)

write(usrfd,buff,len);

close(usrfd);

close(fdfile);

return 0;

}

客戶端程式:

#include#include#include#include#include#include#include#define flag o_creat|o_excl

#define mode s_irusr|s_iwusr|s_irgrp|s_iwgrp

int main()

len=strlen(buf);

write(fdserver,buf,len);

sprintf(buf,"/tmp/fifo.client.%ld",(long)pid);

if(mkfifo(buf,mode)<0)

if((fdclient=open(buf,o_rdonly))<0)

while((len=read(fdclient,buf,1024))>0)

write(1,buf,len);

close(fdserver);

close(fdclient);

return 0;

}

可以實現單伺服器,多使用者模式,伺服器在程式後台執行,前台向伺服器提交請求,伺服器端進行回應。

系統對於管道和

fifo

有如下限制,

open_max

乙個程序在任意時刻可以開啟的最大描述符個數,

pipr_buf

可原子的往乙個管道或者

fifo

的最大資料量

關於這兩個限制,可以通過

sysconf

函式檢視,用過

ulimit

命令和limit

命令進行修改。其中很多規則制約這

fifo

和管道的是否阻塞問題和原子操作問題,關於這方面的討論,才疏學淺,不便多說了。

程序間通訊 管道 命名管道 FIFO

比較類似程序間的生產者 消費者模型。乙個程序向管道中寫入資料,另乙個程序從管道中讀出資料。pipe為無名管道,提供的是一組半雙工通訊方式。pipe會建立兩個檔案物件,乙個索引節點。pipe在核心中會有乙個快取,快取大小可能若干個頁大小。呼叫write像管道裡寫資料時,系統會將資料存於快取,另乙個執行...

程序間通訊 管道通訊(pipe與fifo)

1.程序間通訊 ipc interprocess communication 程序間通訊常用的4中方式 2.pipe管道 pipe管道為匿名管道,就是乙個偽檔案,是乙個核心緩衝區,不占用磁碟空間。管道由讀端與寫端組成,分別對應兩個檔案描述符,管道的讀寫預設是阻塞的。管道的內部是由環形佇列構成的,具有...

程序間通訊 管道

include int pipe int fd 2 返回值 若成功,返回0,若出錯,返回 1經由引數fd返回兩個檔案描述符 fd 0 為讀而開啟,fd 1 為寫而開啟。fd 1 的輸出是fd 0 的輸入。else if pid 0 子程序 else else if pid 0 父程序 printf ...