Linux pipeline (anonymous PIPE), linux pipeline anonymous pipe

Source: Internet
Author: User

Linux pipeline (anonymous PIPE), linux pipeline anonymous pipe
Basic concepts of Pipelines

Pipelines are the oldest form of inter-process communication in Unix.

We call a data stream that connects a process to another process as a "Pipeline"

For example: ps aux | grep httpd | awk '{print $2 }'

 

MPs queue



Essence of Pipelines

Fixed-size kernel buffer

MPs queue restrictions

1) pipelines are half-duplex and data can only flow in one direction. Two pipelines need to be established when both parties need to communicate;

2) an anonymous pipeline can only be used for communication between processes with common ancestor (for example, parent processes and fork child processes). [generally, one pipeline is created by one process, then the process calls fork, and then the Parent and Child processes share the pipeline]

 

Anonymous pipeline pipe

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

 

Function

Create an unknown MPs queue

Parameters

Pipefd: an array of file descriptors. pipefd [0] indicates the read end and pipefd [1] indicates the write end.

 

MPs queue Creation

// Self-implemented pipe void err_exit (string str); int main () {int pipefd [2]; if (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]); // point STDOUT_FILENO to pipefd [1], that is, the output of the ls command will be printed to dup2 (pipefd [1], STDOUT_FILENO) in the pipeline; // close the pipeline write end (pipefd [1]) at this time; execlp ("/bin/ls", "/bin/ls", NULL); // if the process image replacement fails, print the following error message fprintf (stderr, "Child: execlp error "); exit (0);} // In Parent close (pipefd [1]); // point STDIN_FILENO to pipefd [2], that is, the wc command reads the input dup2 (pipefd [0], STDIN_FILENO) from the pipeline; // close the pipeline read end (pipefd [0]) at this time; execlp ("/usr/bin/wc", "/usr/bin/wc", "-w", NULL); // If process image replacement 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: Pipeline programming practices

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 MPs queue read/write rules

1) when the MPs queue is empty

O_NONBLOCK disable: The read call is blocked, that is, the process is paused until data arrives.

O_NONBLOCK enable: The read call returns-1, and the errno value is EAGAIN.

 

2) When the MPs queue is full

O_NONBLOCK disable: The write call is blocked until a process reads data.

O_NONBLOCK enable: The call returns-1, and the errno value is EAGAIN.

 

3) pipelines are constantly written and full

O_NONBLOCK disable: write call blocking (Block)

O_NONBLOCK enable: The call returns-1, and the errno value is EAGAIN.

// Example: Set the parent process to 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 waiting for the sub-process to send data err_exit ("read error ");} cout <"Read from pipe:" <buf <endl; close (pipefd [0]); return 0 ;}

 

4) if the file descriptor corresponding to the write end of all pipelines is disabled, 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 the reading end of all pipelines is disabled, the write operation will generate the signal SIGPIPE

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 data volume to be written is not greater than PIPE_BUF, Linux ensures the atomicity of writing.

2) When the data volume to be written is greater than PIPE_BUF, Linux will no longer guarantee the atomicity of writing.

 

// Example: test the 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 Result: Ubuntu 14.04X64 xiaofang @ xiaofang-Lenovo-G470 :~ /Apue/it $./main size = 65536 */


Appendix-MPs queue capacity Query

Man 7 pipe

 

 

 

Appendix-in-depth 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;}

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.