Linux pipeline - system call pipe() function implementation

pipeline concept

1. A pipe is a piece of operating system memory provided by an operation;
2. A pipe is the oldest inter-process communication method in Unix;
3. A data stream that connects one process to another is called a pipe.

The principle of pipeline communication

Between the parent process and the child process, or between two sibling processes, a one-way communication channel can be established through system calls. But this kind of pipeline can only be established by the parent process, and it is static and inherent to the child process. The processes at both ends of the pipe each treat the pipe as a file. One process writes, the other reads. And, what is passed through the pipeline follows the principle of "first in, first out" (FIFO). Each pipeline is one-way, and two pipelines are established when two-way communication is required.

Pipes are half-duplex communication. If you want to achieve full-duplex communication, you need to create two pipes.

System call pipe() function implementation

The main body of the pipeline mechanism is the system call pipe(), but both ends of the pipeline established by pipe() are in the same process, so it must be established between parent and child processes or between two child processes with the cooperation of fork. A communication channel between processes. Since both ends of the pipeline appear in the relevant process in the form of (opened) files, they are also implemented as anonymous files in the specific implementation. So the code of pipe() is closely related to the file system.

  • Read data from keyboard, write to pipe, read pipe, write to screen
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main()
{
  int fds[2];
  char buf[100];
  int len;

  if(pipe(fds) == -1)
  perror("make pipe");
  exit(-1);

//read from stdin
while(fgets(buf,100,stdin))
{
  len = strlen(buf);
   //read into pipe
   if(write(fds[1],buf,len)!=len)
     perror("write to pipe");
     break;
 }

memset(buf,0x00,sizeof(buf));

//read from pipe
if((len = read(fds[0],buf,100)) == -1)
{
  perrpr("read from pipe");
  break;
}

//write to stdout
if(write(1,buf,len) != len))
{
  perror("write to stdout");
  break;
}
}
Notice:

There are some limitations to using pipes:

Two processes can only achieve one-way communication through a pipe. For example, in the above example, the parent process writes to the child process and reads, if

Sometimes it is necessary for the child process to write to the parent process to read, so another pipe must be opened. Readers are asked to think, if only one pipeline is opened,

But the parent process does not close the read end, and the child process does not close the write end, both sides have a read end and a write end, why can't two-way be realized

communication?

The read and write ends of the pipe are passed through open file descriptors, so two processes to communicate must

Inherit pipe file descriptors from ancestors. The above example is the parent and child process after the parent process passes the file descriptor to the child process

For communication between the two child processes, the parent process can also fork twice, pass the file descriptor to the two child processes, and then communicate between the two child processes.

In short, the file descriptor needs to be passed through fork so that both processes can access the same pipe before they can communicate.

The following four special cases need to be paid attention to when using pipes (assuming that they are all blocking I/O operations, and the O_NONBLOCK flag is not set

Chi):

1. If all file descriptors pointing to the write end of the pipe are closed (the reference count of the write end of the pipe is equal to 0), and the

However, if a process reads data from the read end of the pipe, after the remaining data in the pipe is read, the read will return 0 again, and

Like reading to the end of the file.

2. If the file descriptor pointing to the write end of the pipe is not closed (the reference count of the write end of the pipe is greater than 0), and the

The process on the writing end does not write data to the pipe. At this time, a process reads data from the reading end of the pipe, then the remaining number of data in the pipe.

After the data has been read, the read will block again, and the data will be read and returned until the data in the pipeline is readable.

3. If all file descriptors pointing to the read end of the pipe are closed (the reference count of the read end of the pipe is equal to 0), then

If a process writes to the write end of the pipe, the process will receive the signal SIGPIPE, which usually causes the process to terminate abnormally.

In Chapter 33 Signals, we'll talk about how to make the SIGPIPE signal not terminate the process.

4. If the file descriptor pointing to the read end of the pipe is not closed (the reference count of the read end of the pipe is greater than 0), and the

The process on the reading end does not read data from the pipe. At this time, a process writes data to the writing end of the pipe, then when the pipe is full

Writing again will block until there is a free space in the pipe to write data and return.

These four special cases of pipelines are of general significance.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325728669&siteId=291194637