管道 PIPE

沒錯,就講大家可能天天會用的“管道 | “,前者的輸出是後者的輸入。這裏簡單要提一點大家可能忽略了的一個有趣事實是,後者不用得到前者執行完畢才啓動。更有趣的是,只要後者獲取了足夠的數據,前者便會停止執行。

grep 'colin' bigfile.txt | head

故而當 grep 在給定文件中找到含有給定字符串的 10行文字後,即可功成身退,因爲那是 head 的全部所需。加入沒有管道機制,那就只能這樣:

grep 'colin' bigfile.txt > tmpfile; head tmpfile

pipes

管道

管道(pipe)是所有Unix都願意提供的一種進程間通信機制。管道是進程之間的一個單項數據流:一個進程寫入管道的所有數據都由內核定向到另一個進程,另一個進程由此就可以從管道中讀取數據。

管道被看作是打開的文件,但在已安裝的文件系統中沒有相應的映像。可以使用pipe()系統調用來創建一個新管道,這個系統調用會返回一對文件描述符; 然後進程通過fork()把這兩個描述符傳遞給它的子進程,由此與子進程共享管道。進程可以在read()系統調用中使用第一個文件描述符從管道中讀取數據,同樣也可以在write()系統調用中使用第二個文件描述符相管道中寫入數據。

eg:
pipeline

示例

ctipc.h 後面系列都使用此頭文件,所以這裏include了一些多餘的

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/mman.h>
/* #include <mqueue.h> */
#include <sys/fcntl.h>
/* mqueueh.h is for POSIX messaging queues, and is not available on OS X.  O_NONBLOCK has nothing to do with that, and is defined in fcntl.h */
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#define FILE_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH
#define MAXLINE 1024

pipe.cpp

#define READFD 0
#define WRITEFD 1
#include "ctipc.h"
int main(int argc, char ** argv){
        int pipe_fd[2], n, ret;
        if(pipe(pipe_fd) < 0){
                printf("create pipe error\n");
                return 0;
        }
        if((ret = fork()) < 0){
                printf("fork error \n");
                return 0;
        }
        if( ret > 0){  //parent process
                char buff[10240] = {0};
                close(pipe_fd[WRITEFD]);
                while(read(pipe_fd[READFD], buff, sizeof(buff))){
                        printf("<print from parent: %s> \n", buff);
                }
                printf("<print from parent: read end>\n");
                close(pipe_fd[READFD]);
                return 0;
        }
        else{ //child process
                close(pipe_fd[READFD]);
                char *info = "[printed in child process, hello world]";
                write(pipe_fd[WRITEFD], info, strlen(info));
                return 0;
        }
        return 0;
}

輸出

shell> g++ pipe.cpp -o pipe.out
pipe.cpp:26:30: warning: conversion from string literal to 'char *' is deprecated
      [-Wc++11-compat-deprecated-writable-strings]
                char *info = "[printed in child process, hello world]";
                             ^
1 warning generated.
shell>./pipe.out 
<print from parent: [printed in child process, hello world]> 
<print from parent: read end>

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章