Movatterモバイル変換


[0]ホーム

URL:


bald man icon

Pipes II

Introduction

In this part of the tutorial we will be creating and using apipe, wish me luck 😅, don’t worry we can do it.

Prerequisites

  1. Been on a Linux OS.
  2. A C/C++ compiler to compile a code of more than 10 lines😬.

Creating a pipe in C

Now how do we create apipe with code? Mmm 🤔, here’s a snippet.

#include <unistd.h>int main(void) {    //file descriptors    int pipefd[2];    int pipe(pipefd);}

Let’s see part of the documentation of thepipe() on the manpage:

pipe() creates apipe, aunidirectional data channel that can be used for interprocess communication. The arraypipefd is used to return two file descriptors referring to the ends of the pipe.pipefd[0] refers to the read end of the pipe.pipefd[1] refers to the write end of the pipe.

This argument that takes contains the file descriptors needed, one for theread end of the pipe and another for thewrite end of the pipe. So ideally with one you push the data on thepipe and with the other you access that data. Very ingenious, right?

Let’s see if we could do something with this, I will tested on a very simple program the will behave like this:

  • There’s going to betwo process.
  • One process will write sequentially the numbers from0 to 9, waiting one second on each write.
  • The other process will read the data from thepipe, and it will printed on the console.

I recommend you to play around with this by yourself. I mean you could try exactly as I put it here but you would understand better if you create a simple example by yourself. This steps will help you also:

  • Watch first this example, learn from it.
  • Try to explain it to someone else.
  • Get your hands dirty with code.

Let’s see the code and break it in pieces, it would be better that way, because you know, it isC 🙄 .

#include <stdio.h>#include <string.h>#include <sys/types.h>#include <unistd.h>int main(int argc, char *argv[]) {  // file descriptors to use on the write end  // and read end of the pipe  int filedes[2];  if (pipe(filedes) == -1) {    perror("pipe couldn't be created");    return -1;  }  // after this both file descriptors are open  // creating a child process  pid_t process = fork();  switch (process) {  case -1:    perror("fork failed");    return -1;  // we are in the child process  case 0:    // closing write end pipe in child    if (close(filedes[1]) == -1) {      perror("closing in child");      return -1;    }    break;  // we are in the parent process  default:    if (close(filedes[0]) == -1) {      perror("closing in parent");      return -1;    } // closing read end pipe in parent  }  if (passingMsg(process, filedes) == -1) {    perror("passingMsg");    return -1;  }  // cleaning  if (process == 0)    close(filedes[0]);  else    close(filedes[1]);  return 0;}

In this first snippet we can see that I made use offork() to create a new process, go to its manpage, withman fork and you will see its documentation. If the documentation is too heavy don’t worry I got your back, this 👉tutorial from Geeks for Geeks, is precisely aboutfork(), take a look at it is very concise.

If you read the code you notice that I created apipe, a new child process withfork() and then I made some magic there on the switch statement, right? What just happened there? Let me draw you the situation:

After the creation of the pipe

+-[Calling process]<-+   f0: read end of the pipe| f1          f0     |   f1: write end of the pipe|                    |+--->| Pipe  |-------+

This is with a single process because we haven’t usedfork() yet both file descriptors are on the calling process, we will call itparent process.

After the creation of the new process

    +-[Calling process]<-+   f0: read end of the pipe| f1          f0     |   f1: write end of the pipe|      _______       |    \+--->|       |-----+/      | Pipe  |/+--->|_______|-----+\| f1          f0     ||                    |+---[Child process]<-+

Now here is the trick, after the creation of thechild process, both processes can write and read from the pipe. Which may be the behavior needed by your application but in our case, I want to write from theparent or calling process and read from thechild process. That’s the reason why I closed on the switch statement first thewrite end file descriptor of thechild process, and later also closed theread end file descriptor on theparent process. It seems like a tongue twister, but my next draw will help you understand:

After the switch statement

    +-[Calling process]      f0: read end of the pipe| f1                   f1: write end of the pipe|      _______           \+--->|       |      | Pipe  |      |_______|-----+\              f0     |                     |    [Child process]<-+

After the switch statement I’m ready to pass messages from theparent to thechild, here is the part of the code corresponding to the functionpassingMsg.

int passingMsg(pid_t process, int *filedes) {  char buff[3];  int BUF_SIZE = 3;  int bRead;  char msg[3];  switch (process) {  //child process  case 0:    printf("MSG From Parent:\n");    for (;;) {      bRead = read(filedes[0], buff, BUF_SIZE); //reading from the pipe      if (bRead == -1) {        perror("read on child");        return -1;      }      if (bRead == 0) // end of steam data        break;      // writing msg to stdout      if (write(STDOUT_FILENO, buff, bRead) != bRead) { //writing to the console        perror("write to stdout");        return -1;      }    }    break;  //parent process  default:    for (int i = 0; i < 10; i++) {      sleep(1);      snprintf(msg, 3, "%d\n", i);      if (write(filedes[1], msg, strlen(msg)) == -1) { //writing on the pipe        perror("write from parrent");        return -1;      }    }  }  return 0;}

What about other language apart from C

I will leave you two links ofpipes inGo andPython.

Python:

Go:

No idea how is this for other programming languages go and find how are pipes on other programming language that you like :smiley:.

Conclusion

Well it is a pretty long article I admit it, but if you read it with calm you will learn a cool stuff. For me this is also new so don’t worry if you don’t understand it at first. There’s a lot of information about pipe.

That’s all folks :wave:.

Bibliography

  1. The Linux Programming Interface by Michael Kerrisk.
  2. fork() in C
  3. manpage forfork()

[8]ページ先頭

©2009-2025 Movatter.jp