“This is the 24th day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

Each have their own different user address space, any process in the global variable in another process can not to, so want to exchange data between processes must by the kernel, open up a buffer in the kernel, process the data from 1 in the household space into a kernel buffer, process 2 go to read the data from the kernel buffer, The mechanism provided by the kernel is called InterProcess Communication (IPC).

Pipe line

Pipes are one of the most basic IPC mechanisms created by the PIPE function:

#include <unistd.h>
int pipe(int filedes[2]);
Copy the code

Pipes act between related processes and are passed through forks

When the pipe function is called, a buffer (called pipe) is opened in the kernel for communication, which has a read and a write, and two file descriptors are passed to the user program via the Filedes parameter, Filedes [0] points to the read and Filedes [1] points to the write. Just as 0 is standard input and 1 is standard output). So the pipe looks like an open file in the user program, through read(Filedes [0]); Or write (filedes [1]); Reading or writing data to this file is actually reading or writing to the kernel buffer. Pipe returns 0 on success and -1 on failure. How do you communicate between two processes once you have a pipeline? For example, you can follow these steps to communicate.

1. The parent process calls PIPE to open the pipe and gets two file descriptors pointing to both ends of the pipe.

2. The parent process calls fork to create a child process that also has two file descriptors pointing to the same pipe.

3. The parent process closes the pipe read end, and the child process closes the pipe write end. The parent process can write to the pipe and the child process can read from the pipe. The pipe is implemented by a ring queue. Data flows in and out of the pipe from the write end to the read end, thus realizing inter-process communication.

Cases of pipe line

#include <stdlib.h> 
#include <unistd.h> 
#define MAXLINE 80
int main(void) {
	int n;
	int fd[2];
	pid_t pid;
	char line[MAXLINE];
	if (pipe(fd) < 0) { 
		perror("pipe");
		exit(1); 
	}
	if ((pid = fork()) < 0) {
		perror("fork");
		exit(1); 
	}
	if (pid > 0) { /* parent */ 
		close(fd[0]);
		write(fd[1], "hello world\n", 12);
		wait(NULL);
	} else { /* child */
		close(fd[1]);
		n = read(fd[0], line, MAXLINE); 
		write(STDOUT_FILENO, line, n);
	}
	return 0; 
}
Copy the code

There are some limitations to using pipes:

Two processes can only communicate in one direction through a channel. For example, in the example above, the parent process writes to the child process and reads. If the child process also needs to write to the parent process, another channel must be opened. Please consider, if only one pipe 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 both the read end and the write end, why can not achieve two-way communication?

The read-write side of the pipe is passed through an open file descriptor, so the two processes communicating must inherit the pipe file descriptor from their common ancestor. The above example is the parent process pass file descriptors to communicate between a parent and child process after the child, can also be the parent process fork twice, pass two child process, the file descriptor and two letters, between the child in all need to be transmitted by the fork file descriptor that two processes can access the same pipe, they can communicate.

There are four special cases to be aware of when using pipes (assuming they are all blocking I/O operations and the O_NONBLOCK flag is not set):

  1. If all file descriptors pointing to the pipe writers are closed (the pipe writers reference count is 0) and a process is still reading data from the pipe’s readers, the rest of the pipe will be read and the next read will return 0, just as if it had read to the end of the file.

  2. If there is a point to pipeline to write the file descriptor is not closed (pipe to write the reference count is greater than zero), and the holding tube also have no way to write the process to write data in the pipeline, then have a process to read data read from the pipe end, so the remaining number of the pipe According to have been read, read again will be blocked, until the pipe to have data can be read to read data and return.

  3. If all file descriptors to the pipe reader are closed (the pipe reader reference count is 0) and a process writes to the pipe’s writer, the process receives a signal SIGPIPE, which usually causes the process to abort abnormally. We’ll talk about how to keep SIGPIPE signals from terminating processes.

  4. If there is a point to pipeline to read the file descriptor is not closed pipeline (the reference count is greater than zero), and the holding tube also have no way to read the process to read data from the pipeline, then have a process to write data pipeline to write end, so when the pipeline is full again write blocks, write data until the vacancies in the pipe and return.

These four special cases of pipelines are of general significance.

  • For a non-blocking pipe, the FCNTL function sets the O_NONBLOCK flag
  • Fpathconf (int fd, int name) tests the pipe buffer size, _PC_PIPE_BUF

Fifo named pipe

Create a named pipe to handle communication between unrelated processes, FIFO:

qingkouwei@ubuntu:~$mkfifo XWP qingkouwei@ubuntu:~$ls-l XWP prw-rw-r-- 1 qingkouwei qingkouwei 0 September 15 18:34 XWPCopy the code

Mkfifo has both commands and functions

#include <sys/types.h> 
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
Copy the code
  • Open write opens block if there is no FIFO read open when write only to open the FIFO pipe.
  • The FIFO kernel can support two-way communication when implemented. Pipe one-way communication because parent and child processes share the same file structure
  • FIFO can have one read end and more than one write end; You can also have one write end and multiple read ends. (Please test)

conclusion

This article introduced the concept of Linux process communication: solving the problem that global variables in either process cannot be seen in the other, and the most commonly used process peer mechanism: pipes.