有名管道和無名管道的介紹
技術標籤:程序間通訊linux程式語言多執行緒javapython
文章目錄
前言
在程序間通訊的幾種方式中,管道可謂是最簡單的了,今天我們就來介紹一下兩種管道的用法。
一、無名管道
1.概念介紹
無名管道和有名管道是Linux系統核心的特殊檔案,用於程序之間的通訊。
無名管道相當於一個佇列結構,fd[1]為寫入端(入隊),fd[0]為讀出端(出隊)。其中資訊讀出後即刪除,再次讀取時即為下一個資訊。
2.相關函式介紹
函式形式:int pipe(int fd[2])
功能:建立無名管道檔案。無名管道是一個特殊檔案,不可由open函式建立。
引數:fd[2]有兩個成員 fd[0]和 fd[1],他們都是檔案描述符。 管道有固定的讀端 fd[0]和固定的寫端 fd[1]。
返回值:成功返回 0,出錯返回-1。
3.關於無名管道的一些說明
①管道是建立在記憶體中,程序結束空間釋放,管道不復存在。
②無名管道和有名管道都是半雙工通訊,實現雙向通訊需要建立兩個管道。
③無名管道是linux特殊檔案,不能在與windows共享的資料夾中建立。
④無名管道只用於父子程序之間,有名管道可用於無親緣關係的程序之間
4.無名管道程式設計實戰
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd[2];
int pid;
char buf[128];
if(pipe(fd)==-1){
printf("creat pipe failur\n");//建立一個無名管道
}
pid=fork();//獲取fork後的pid號
if (pid<0){
printf("creat child failur\n");
}else if(pid>0){
sleep(3);
printf("thid is father\n");
close(fd[0]);
write(fd[1],"wencai love pingping",strlen("wencai love pingping"));//將要傳遞的資料寫入fd這個陣列中
wait();//父程序等待子程序
}else{
printf("this is child\n");
close(fd[1]);
read(fd[0],buf,128);//讀取管道中的資料
printf("read from father:%s\n",buf);
exit(0);
}
return 0;
}
無名管道在進行通訊時不能同時讀寫,因而在讀的這一段需關閉寫,而在寫的一端則需關閉讀,下面我們來看看程式執行後的實際效果
可以看到通過無名管道成功的將一串字串從父程序傳遞到了子程序。
二、有名管道
1.概念
有名管道是一種檔案型別,在檔案系統中可以看到。程式中可以檢視檔案stat結構中st_mode成員的值來判斷檔案是否是FIFO檔案。建立一個FIFO檔案類似於建立檔案,FIFO檔案就像普通檔案一樣。FIFO中可以很好地解決在無關程序間資料交換的要求,並且由於它們是存在於檔案系統中的,這也提供了一種比匿名管道更持久穩定的通訊辦法。
FIFO的通訊方式類似於在程序中使用檔案來傳輸資料,只不過FIFO型別檔案同時具有管道的特性。在資料讀出時,FIFO管道中同時清除資料。在shell中mkfifo命令可以建立有名管道,下面通過程式設計實戰來幫助讀者理解FIFO。
2.程式設計實戰
有名管道一般用的多的是令其堵塞,因而在建立管道後開始讀取時,需要另一程序進行寫,才能正確讀取到。
建立有名管道程式設計及寫入資料:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
int n_write;
int cnt;
cnt=0;
char *str="wencai love pingping";//要傳送的資料,可自己決定
fd=open("./file1",O_WRONLY);
printf("open sucesess\n");
while(1){
n_write=write(fd,str,strlen(str));
sleep(1);
cnt++;
if(cnt==4){
break;
}
}
close(fd);
return 0;
}
讀取管道中的資料:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
int n_read;
int cnt=0;
char buf[30]={0};
if((mkfifo("./file1",0600)==-1)&&errno!=EEXIST){ //檢視是否有建立成功的管道
printf("creat failuer\n");
perror("why");
}
fd=open("./file1",O_RDONLY);
printf("open sucesess\n");
while(1){
memset(buf,'\0',sizeof(buf));//清空收到的訊息
n_read=read(fd,buf,30);//讀取管道中的資料
printf("read %d byte from,context:%s\n",n_read,buf);
if(cnt++==4){
break;
}
}
close(fd);
return 0;
}
然後我們在liunx平臺下檢查程式碼的執行效果
可以看到,通過寫入與讀取操作,我們完成了在兩個不同程序間的通訊
總結
管道是liunx平臺下最古老的程序間通訊的方式,雖然目前已經有了其他多種程序間通訊的方式,但對於管道的學習還是有必要的。