【Linux】管道

【什麼是管道】
(1)管道是Unix中最古老進程間通信的形式
(2)我們把從一個進程連接到另一個進程的一個數據流稱爲一個“管道”。

【匿名管道】( pipe )
管道是IPC最基本的一種實現機制。我們都知道在Linux下“一切皆文件”,其實這裏的管道就是一個文件。管道實現進程通信就是讓兩個進程都能訪問該文件。
管道的特徵:
只提供單向通信,也就是說,兩個進程都能訪問這個文件,假設進程1往文件內寫東西,那麼進程2 就只能讀取文件的內容。
只能用於具有血緣關係的進程間通信,通常用於父子進程建通信
管道是基於字節流來通信的
依賴於文件系統,它的生命週期隨進程的結束結束(隨進程)
其本身自帶同步互斥效果

要實現管道,我們需瞭解兩個函數:
(1)創建管道:
這裏寫圖片描述
pipe—->創建一個匿名管道。
返回值:成功返回0,失敗返回-1。

(2)創建子進程:
這裏寫圖片描述
注:包含在頭文件 “unistd.h” 中,無參數,返回值類型爲 pid_t
返回值:調用成功將子進程的 pid 返回給父進程,失敗返回-1給父進程。
注意:調用成功會有兩個返回值,對於父進程,返回的是子進程的pid;對於子進程,返回的是0。

實例:
//從鍵盤讀取數據,寫入管道,讀取管道,寫到屏幕

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main()
{
    int fds[2];    //存放標識符,0爲讀,1爲寫。
    char buf[100];
    int len;

    if(pipe(fds)==-1)
        perror("make pipe"),exit(1);

    //read from stdin
    while(fgets(buf,100,stdin))
    {
        len=strlen(buf);
        //write into pipe
        if(write(fds[1],buf,len)!=len)
        {
            perror("write to pipe");
            break;
        }
        memset(buf,0x00,sizeof(buf));

        //read from pipe
        if((len=read(fds[0],buf,100))==-1)
        {
        perror("read from pipe");
        break;
        }

        //write to stdout
        if(write(1,buf,len)!=len)
        {
            perror("write to stdout");
            break;
        }
    }

    return 0;
}


【命名管道】

上述管道雖然實現了進程間通信,但是它具有一定的侷限性:首先,這個管道只能是具有血緣關係的進程之間通信;第二,它只能實現一個進程寫另一個進程讀,而如果需要兩者同時進行時,就得重新打開一個管道。
爲了使任意兩個進程之間能夠通信,就提出了命名管道(named pipe 或 FIFO)。
1、與匿名管道的區別:提供了一個路徑名與之關聯,以FIFO文件的形式存儲於文件系統中,能夠實現任何兩個進程之間通信。而匿名管道對於文件系統是不可見的,它僅限於在父子進程之間的通信。
2、 FIFO是一個設備文件,在文件系統中以文件名的形式存在,因此即使進程與創建FIFO的進程不存在血緣關係也依然可以通信,前提是可以訪問該路徑。
3、 FIFO(first input first output)總是遵循先進先出的原則,即第一個進來的數據會第一個被讀走。

【命名管道的創建】:

1.可在命令行上創建:
$ mkfifo filename

2.在程序裏創建:
int mkfifo (const char* filename , mode_t mode);
註釋:filename 爲管道名稱;mode 爲權限

實例:
//讀取文件,寫入命名管道

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>

#define ERR_EXIT(m)\
    do\
    {\
      perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)

int main(int argc,char* argv[])
{
    mkfifo("tp",0644);
    int infd;
    infd=open("abc",O_RDONLY);
    if(infd==-1)
        ERR_EXIT("open");

    int outfd;
    outfd=open("tp",O_WRONLY);
    if(outfd==-1)
        ERR_EXIT("open");

    char buf[1024];
    int n;
    while((n=read(infd,buf,1024))>0)
    {
        write(outfd,buf,n);
    }
    close(infd);
    close(outfd);
    return 0;
}

//讀取管道,寫入文件

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>

#define ERR_EXIT(m)\
    do\
    {\
      perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)

int main(int argc,char* argv[])
{
    int outfd;
    outfd=open("abc.bak",O_WRONLY | O_CREAT | O_TRUNC,0644);
    if(outfd==-1)
        ERR_EXIT("open");

    int infd;
    infd=open("tp",O_RDONLY);
    if(infd==-1)
        ERR_EXIT("open");

    char buf[1024];
    int n;
    while((n=read(infd,buf,1024))>0)
    {
        write(outfd,buf,n);
    }
    close(infd);
    close(outfd);
    unlink("tp");
    return 0;
}
發佈了70 篇原創文章 · 獲贊 92 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章