1. 程式人生 > 其它 >有名管道和無名管道的介紹

有名管道和無名管道的介紹

技術標籤:程序間通訊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平臺下最古老的程序間通訊的方式,雖然目前已經有了其他多種程序間通訊的方式,但對於管道的學習還是有必要的。