1. 程式人生 > >linux管道(pipe)

linux管道(pipe)

轉載自:http://blog.chinaunix.net/uid-27034868-id-3394243.html

管道是一種兩個程序間進行單向通訊的機制。因為管道傳遞資料的單向性,管道又稱為半雙工管道。管道的這一特點決定了器使用的侷限性。管道是Linux支援的最初Unix IPC形式之一,具有以下特點:


*** 資料只能由一個程序流向另一個程序(其中一個讀管道,一個寫管道);如果要進行雙工通訊,需要建 立兩個管道。
*** 管道只能用於父子程序或者兄弟程序間通訊。,也就是說管道只能用於具有親緣關係的程序間通訊。

   除了以上侷限性,管道還有其他一些不足,如管道沒有名字(匿名管道),管道的緩衝區大小是受限制的。管道所傳輸的是無格式的位元組流。這就需要管道輸入方和輸出方事先約定好資料格式。雖然有那麼多不足,但對於一些簡單的程序間通訊,管道還是完全可以勝任的。

   使用管道進行通訊時,兩端的程序向管道讀寫資料是通過建立管道時,系統設定的檔案描述符進行的。從本質上說,管道也是一種檔案,但它又和一般的檔案有所不同,可以克服使用檔案進行通訊的兩個問題,這個檔案只存在記憶體中。
    通過管道通訊的兩個程序,一個程序向管道寫資料,另外一個從中讀資料。寫入的資料每次都新增到管道緩衝區的末尾,讀資料的時候都是從緩衝區的頭部讀出資料的。

      #include

       int pipe(int pipefd[2]);

(匿名)管道兩端分別用描述符pipefd[0]pipefd[1]來描述。需要注意的是,管道兩端的任務是固定的,一端只能用於讀,有描述符pipefd[0]
表示,稱其為管道讀端;另一端只能用於寫,由描述符pipe[1]來表示,稱其為管道寫端。
該函式建立的管道的兩端處於一個程序中間,在實際應用中沒有太大意義,因此,一個程序在由pipe()建立管道後,一般再fork一個子程序,然後通過管道實現父子程序間的通訊。在此不再作多介紹,下面看看有名管道吧。
    管道的一個不足之處就是沒有名字,因此,只能用於具有親緣關係的程序間通訊,在有名管道(name pipe或FIFO)提出後,該限制得到了解決。FIFO不同與管道之處在與她提供一個路徑名與之關聯,以FIFO的檔案形式儲存在檔案系統中。有名管道是一個裝置檔案,因此,即使程序與建立FIFO的程序不存在親緣關係,只要可以訪問該路徑,就能夠通過FIFO相互通訊了。值得注意的是FIFO(First In First Out)總是按照先進先出的原則工作,第一個被寫入的資料首先從管道中讀出。
     在Linux中我們經常使用管道重定向資料。比如:
   
   


下面介紹一下建立有名管道的系統呼叫,有兩個,mknod和mkfifo





#include  

#include 

int mknod(const char *pathname, mode_t mode, dev_t dev);

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

函式mknod引數中pathname為建立有名管道的全路徑名,mode為建立有名管道的模式,指明其存取許可權;dev為裝置值,該值取決於檔案建立的種類,它只在建立裝置檔案是才會用到。這兩個函式呼叫成功都返回0,否則返回-1.
讀寫有名管道:

#include 

ssize_t read (int fd , void * buf , size_t nbytes)

ssize_t write (int fd , void * buf , size_t nbytes)

接下來給大家演示一下通過有名管道通訊的聊天程式。。。

    // 李四.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <errno.h>
    #include <pthread>

    #define FIFO_READ    "writefifo" //另外一個程式只要把本程式
    #define FIFO_WRITE    "readfifo" //拷貝一份然後調換這兩個巨集即可

    #define BUF_SIZE    1024
    int left = 0;
    void *read_buf()
    {
        int rfd = -1;
        char buf[BUF_SIZE] = { '\0' };
        int i;

        printf("等待對方……\n");
        while ((rfd = open(FIFO_READ, O_RDONLY)) == -1) {
            sleep(1);
        }
        while (left != 1) {
            //printf("i=%d ",i++);
            int len = read(rfd, buf, BUF_SIZE);
            if (len > 0) {
                buf[len] = '\0';
                
                if(strcmp(buf,"不理你了") == 0){
                    printf("\n對方已經走開!\n");
                    left = 1;
                    break;
                //    exit(0);
                }
                for(i = 0; i < strlen("我:"); i++)
                    printf("\b");

                printf("對方:%s\n", buf);
                printf("我:");
                fflush(stdout);
            }
        }
        
        close(rfd);
        return NULL;
    }

    void *write_to()
    {
        int wfd;
        char buf[BUF_SIZE];
        int len;

        umask(0);
        if (mkfifo(FIFO_WRITE, S_IFIFO | 0666)) {
            printf("Can't create FIFO %s because %s", FIFO_WRITE,
             strerror(errno));
            exit(1);
        }
        umask(0);
        wfd = open(FIFO_WRITE, O_WRONLY);
        if (wfd == -1) {
            printf("open FIFO %s error: %s", FIFO_WRITE, strerror(errno));
            exit(1);
        }
        while (left != 1) {
            printf("我: ");
            fgets(buf, BUF_SIZE, stdin);
            buf[strlen(buf) - 1] = '\0';
            if (strcmp(buf, "不理你了") == 0 || left == 1) {
                write(wfd, buf, strlen(buf));//通知對方
                close(wfd);
                unlink(FIFO_WRITE);
                exit(0);
            }
            write(wfd, buf, strlen(buf));
            fflush(stdin);
        }
    }
    int main(int argc, char *argv[])
    {
        pthread_t thIDr, thIDw;
        
        pthread_create(&thIDr, NULL,(void *)read_buf, NULL);
        pthread_create(&thIDw, NULL,(void *)write_to, NULL);
        pthread_join(thIDr, NULL);
        pthread_join(thIDw, NULL);

        return 0;
    }


學以置用,呵呵,效果如下:

pthread不是Linux下的預設的庫,也就是在連結的時候,無法找到phread庫中哥函式的入口地址,於是連結會失敗。

在gcc編譯的時候,要加 -lpthread引數即可解決。

不要忘了加上標頭檔案#include<pthread.h>  (原文中作者沒加,這裡加了)。

相關推薦

linux管道(pipe)

轉載自:http://blog.chinaunix.net/uid-27034868-id-3394243.html 管道是一種兩個程序間進行單向通訊的機制。因為管道傳遞資料的單向性,管道又稱為半雙工管道。管道的這一特點決定了器使用的侷限性。管道是Linux支援的最初Un

Linux管道(pipe)的那些事

Linux中可以使用重定向操作來指定檔案描述符,這分為輸入重定向和輸出重定向。在使用輸入重定向(>)時,linux會用重定向指定的檔案來替換標準輸入檔案描述符,它會讀取檔案並提取資料,如同是在鍵盤上輸入的。在使用輸出重定向(>)時,linux會用重定向指定的檔案來替換標準輸出檔案描述符。(>

Linux 進程間通信之管道(pipe),(fifo)

命名 som 新的 ima fcntl node hello 字符串 oot 無名管道(pipe) 管道可用於具有親緣關系進程間的通信,有名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關系進程間的通信; 定義函數: int pipe(int

Linux進程間通信之管道(pipe)、命名管道(FIFO)與信號(Signal)

阻塞 node include 系統 types.h 標準 div [0 pipe 整理自網絡 Unix IPC包括:管道(pipe)、命名管道(FIFO)與信號(Signal) 管道(pipe) 管道可用於具有親緣關系進程間的通信,有名管道克服了管道沒有名字的

Linux--無名管道pipe示例

無名管道pipe用於父子程序之間的通訊。 #include <stdio.h> #include <unistd.h> int main(void) { int pipe_fd[2];//pipe_fd[1]---pipe頭部,讀

Linux 多工程式設計——程序間通訊:無名管道(PIPE)

管道的概述 管道也叫無名管道,它是是 UNIX 系統 IPC(程序間通訊) 的最古老形式,所有的 UNIX 系統都支援這種通訊機制。 無名管道有如下特點: 1、半雙工,資料在同一時刻只能在一個方向上流動。 2、資料只能從管道的一端寫入,從另一端讀出。 3、寫入管道中的資料遵循先入先出

Linux管道命令(pipe)之選取命令grep

grep 分析一行資訊,如果包含所查詢的,則取出該行。 常用引數: -a:將binary檔案以text檔案的方式查詢資料; -c: 返回找到“目標字串”的次數; -i: 忽略大小寫; -n: 輸出行號; -v: 反向選擇,查詢不包含“目標字串”的行 --color=[wh

Python--線程隊列(queue)、multiprocessing模塊(進程對列Queue、管道(pipe)、進程池)、協程

有一種 啟動進程 fin 機制 內部 優先級隊列 queue類 解決 producing 隊列(queue) 隊列只在多線程裏有意義,是一種線程安全的數據結構。 get與put方法 ‘‘‘ 創建一個“隊列”對象 import queue q = queue.Que

擼代碼--類QQ聊天實現(基於linux 管道 信號 共享內存)

time 針對 -s .net water pos 關閉 mes sigint 一:任務描寫敘述 A,B兩個進程通過管道通信,像曾經的互相聊天一樣,然後A進程每次接收到的數據通過A1進程顯示(一個新進程,用於顯示A接收到的信息),A和A1

Java-NIO(九):管道 (Pipe)

png bsp java nio pri java-nio ges 線程 pre logs Java NIO 管道是2個線程之間的單向數據連接。Pipe有一個source通道和一個sink通道。數據會被寫到sink通道,從source通道讀取。 代碼使用示例:

[Linux管道和IPC]管道的實際應用2

linux管道#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <limits.h> #include <str

Linux入門-7 Linux管道、重定向以及文本處理

cas tde blog linux中 err linuxcast 重要 nal new Linux管道、重定向以及文本處理 1 Linux多命令協作:管道及重定向 管道和重定向 2 Linux命令行文本處理工具 文件瀏覽 基於關鍵字搜索-grep 基於列處理文本-

Linux 管道

圖片 gpo blank 最大 輸出內容 字符串 oot 後綴 ike 管道命令 “ | ”,豎線符號代表的就是管道符 管道是一種兩個進程間進行單向通信的機制。因為管道傳遞數據的單向性,所以又稱為半雙工管道。 介紹: 管道可以根據一組命令按照數據流向的方式來進行操作。簡單

linux管道詳解

linux原文鏈接:http://blog.csdn.net/qq_38646470/article/details/79564392 #符號表示| 和管道特別形象。#作用:    管道是Linux中很重要的一種通信方式,是把一個程序的輸出直接連接到另一個程序的輸入

NIO之管道 (Pipe)

接收 put 管道 itl read 並保存 src ech 緩沖區 Java NIO 管道是2個線程之間的單向數據連接。Pipe有一個source通道和一個sink通道。數據會被寫到sink通道,從source通道讀取。 代碼使用示例: 1 @Test 2

Linux管道符、重定向與環境變量

相對路徑 pat 直接 類型 別名 分組 查看 lin 絕對路徑 ——《Linux就該這麽學》筆記 輸入輸出重定向輸入重定向   指把文件導入到命令中輸出重定向   指把原本要輸出到屏幕的數據信息寫入到指定文件中 輸出重定向   分為標準輸出重定向和錯誤輸出重定向

Linux -管道符和作業控制

RoCE sleep 輸出 images ges shadow fin img obs | : 管道符,將前面輸出的內容,輸入給後面的命令例如:ps -ef | grep java #grep,用來過濾指定關鍵詞的命令,只要文件裏面包含關鍵詞,就會將

7.程序間通訊:匿名管道pipe

匿名管道pipe 1.管道的概念 本質: 核心緩衝區 偽檔案-不佔用磁碟空間 特點:兩部分 讀端,寫端,對應兩個檔案描述符 資料寫端流入,讀端流出 操作管道的程序被銷燬後,管道自動被釋放 管道預設是阻塞的 2.管道的原理 內部實現方式:環形佇列 特點:先進先出,不能操作中

linux 管道、cut、grep、sort詳細用法

linux 管道、cut、grep、sort用法 linux 管道、cut、grep、sort用法 順序執行命令 管道 cut列印每一行的某一欄位 grep 命令,在文字中或 stdin 中查詢匹配字串 sort 排序

usb設計中的管道pipe描述

usb設計中的管道pipe描述  在USB設計中,常有描述管道的說明,對應的圖示為:  在實際設計中:pipe為一個int數  定義如下:  以32位系統為例,int為32 bit. bit:31-30:為管道傳輸的流型別 00: isoch