Linux pipelines (anonymous pipe)

Source: Internet
Author: User

basic concept of piping

Pipelines are the oldest form of interprocess communication in UNIX.

We refer to a data flow from one process to another as a "pipe"

such as: PS aux | grep httpd | awk ' {print $} '

Pipeline



The nature of the pipeline

Fixed-size kernel buffers

Pipe limits

1) The pipe is half-duplex , the data can only flow in one direction, need to establish two pipelines when the two sides communicate;

2) Anonymous pipelines can only be used to communicate between processes that have a common ancestor, such as a parent process and a child process that is forked out; [Typically, a pipeline is created by a process, and then the process calls fork, and then the parent-child process shares the pipeline]

Anonymous piping pipe

Synopsis       #include <unistd.h>       int pipe (int pipefd[2]);

Function

Create a nameless pipe

Parameters

PIPEFD: An array of file descriptors, where pipefd[0] represents the read end, Pipefd[1] represents the write end

Pipeline creation

Implement its own pipeline void Err_exit (string str); int main () {int pipefd[2];    if (pipe (PIPEFD) = =-1) err_exit ("Pipe error");    pid_t pid;    if (PID = fork ()) < 0) err_exit ("fork Error");        if (PID = = 0)//in Child, Write pipe {close (pipefd[0]);        Make Stdout_fileno also point to pipefd[1], that is, the output of the LS command will be printed to the pipeline dup2 (Pipefd[1],stdout_fileno);        You can close the pipe write end close (pipefd[1]) at this time;        EXECLP ("/bin/ls", "/bin/ls", NULL);        If the process image substitution fails, print the following error message fprintf (stderr, "CHILD:EXECLP error");    Exit (0);    }//in Parent Close (pipefd[1]);    Make Stdin_fileno also point to pipefd[2], that is, the WC command will read the input dup2 (Pipefd[0],stdin_fileno) from the pipeline;    At this point close (pipefd[0]) can be closed at the end of pipe reading;    EXECLP ("/USR/BIN/WC", "/USR/BIN/WC", "-w", NULL);    If the process image substitution fails, print the following error message fprintf (stderr, "PARENT:EXECLP error"); return 0;}    void Err_exit (String str) {perror (Str.c_str ()); Exit (exit_failure);}

Example : piping programming practice

void Err_exit (string str); int main () {    int pipefd[2];    int ret;    if (ret = pipe (PIPEFD))! = 0)    {        err_exit ("pipe error");    }    pid_t pid = fork ();    if (PID = =-1)    {        err_exit ("fork Error");    }    if (PID = = 0)   //in Child, Write pipe    {        close (pipefd[0]);   Close Read pipe        string str ("I Can Write pipe from child!");        Write (Pipefd[1],str.c_str (), str.size ());    Write to Pipe        close (pipefd[1]);        Exit (0);    }    In Parent, Read pipe    Close (pipefd[1]);   Close Write Pipe    char buf[1024];    memset (buf,0,sizeof (BUF));    Read (pipefd[0],buf,sizeof (BUF));    Read from pipe    cout << "Read from pipe:" << buf << Endl;    Close (pipefd[0]);    return 0;} void Err_exit (String str) {    perror (str.c_str ());    Exit (exit_failure);}

Anonymous pipe Read and write rules

1) When the pipe is empty

O_nonblock the Disable:read call is blocked , that is, the process pauses execution until the data arrives.

The O_nonblock enable:read call returns a -1,errno value of eagain.

2) when the pipe is full

O_nonblock Disable:write Call blocked until a process reads the data.

O_nonblock Enable: Call returns -1,errno value of Eagain

3) The pipe is constantly written, full

O_nonblock Disable:write Call blocking (block)

O_nonblock Enable: Call returns -1,errno value of Eagain

Example: Set parent process unblock read Pipeint main () {int pipefd[2];    int ret;    if (ret = pipe (PIPEFD))! = 0) {err_exit ("pipe error");    } pid_t pid = fork ();    if (PID = =-1) {Err_exit ("fork Error");        } if (pid = = 0)//in Child, Write pipe {sleep (10);   Close (pipefd[0]);        Close Read Pipe String str ("I Can Write pipe from child!");    Write (Pipefd[1],str.c_str (), str.size ());        Write to pipe close (pipefd[1]);    Exit (0);   }//in Parent, Read pipe Close (pipefd[1]);    Close Write Pipe Char buf[1024];    memset (buf,0,sizeof (BUF));    Set Read PIPEFD unblock!    int flags = FCNTL (PIPEFD[0],F_GETFL);    Flags |= O_nonblock;    ret = Fcntl (pipefd[0],f_setfl,flags);    if (ret! = 0) {err_exit ("Set UnBlock error");    } int readcount = Read (pipefd[0],buf,sizeof (BUF));    Read from Pipe if (Readcount < 0) {//read returns immediately, no longer waits for the child process to send data err_exit ("read error"); } cout << "READ from pipe: "<< buf << Endl;    Close (pipefd[0]); return 0;}

4) If the file descriptor for all the pipe writes is closed, read returns 0

int main () {    int pipefd[2];    int ret;    if (ret = pipe (PIPEFD))! = 0)    {        err_exit ("pipe error");    }    pid_t pid = fork ();    if (PID = =-1)    {        err_exit ("fork Error");    }    if (PID = = 0)   //in child    {//close all        close (pipefd[0]);        Close (pipefd[1]);        Exit (0);    }    In Parent    sleep (1);    Close (pipefd[1]);   Close Write Pipe, now all PIPEFD[1] Closed!!!    Char buf[1024];    memset (buf,0,sizeof (BUF));    int readcount = Read (pipefd[0],buf,sizeof (BUF));    Read from pipe    if (Readcount = = 0)    {        cout << "OK, read 0 byte" << endl;    }    Close (pipefd[0]);    return 0;}

5) if the file descriptor corresponding to all the pipe reads is closed, the write operation generates a signal

void onsignalaction (int signalnumber) {switch (signalnumber) {case Sigpipe:cout << receive signal        Sigpipe: "<< signalnumber << Endl;    Break        Default:cout << "Other signal" << Endl;    Break    }}int Main () {if (signal (sigpipe,onsignalaction)! = 0) {err_exit ("signal error");    } int pipefd[2];    int ret;    if (ret = pipe (PIPEFD))! = 0) {err_exit ("pipe error");    } pid_t pid = fork ();    if (PID = =-1) {Err_exit ("fork Error");        } if (pid = = 0)//in Child, Write pipe {//wait Parent Close pipefd[0] sleep (1);        Close (pipefd[0]);        String str ("I Can Write Pipe from child!");    Write (Pipefd[1],str.c_str (), str.size ());        Write to pipe close (pipefd[1]);    Exit (0);    }//in Parent, close all Pipe close (pipefd[1]);    Close (pipefd[0]);    Wait (NULL); return 0;}

Linux Pipe Features

1) When the amount of data to be written is not greater than pipe_buf , Linux guarantees the atomicity of the write.

2) Linux will no longer guarantee the atomicity of writes when the amount of data to be written is greater than pipe_buf.

Example: Test pipe_buf size int main () {    int pipefd[2];    int ret = pipe (PIPEFD);    if (Ret < 0)    {        err_exit ("pipe error");    }    int flags = FCNTL (PIPEFD[1],F_GETFL);    Flags |= O_nonblock;    ret = Fcntl (pipefd[1],f_setfl,flags);    if (Ret < 0)    {        err_exit ("Fcntl error");    }    Write Test    unsigned int countfortestpipe = 0;    while (true)    {        ret = write (pipefd[1], "a", 1);        if (Ret < 0)        {break            ;        }        + + countfortestpipe;    }    cout << "size =" << countfortestpipe << Endl;} /** test results: Ubuntu 14.04 X64 [email protected]:~/apue/it$./main size = 65536*/


Attached-Pipeline capacity query

Man 7 pipe

Attached-deep understanding of file descriptors

int main () {    close (Stdin_fileno);    if (Open ("Readfile.txt", o_rdonly) = =-1)    {        err_exit ("Open read error");    }    Close (Stdout_fileno);    if (Open ("Writefile.txt", o_wronly| o_trunc| o_creat,0644) = =-1)    {        err_exit ("Open write Error");    }    if (EXECLP ("/bin/cat", "/bin/cat", NULL) = =-1)    {        err_exit ("EXECLP error");    }    return 0;}

Linux pipelines (anonymous pipe)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.