Linux remote development - anonymous pipe PIPE and named pipe FIFO

content

1. What is a pipeline

2. Anonymous Pipeline (PIPE)

1. Anonymous pipeline introduction

2, pipe () function

3. Parent and child processes communicate through anonymous pipes

(1) Demand analysis

(2) Code implementation

(3) Test results

3. Named Pipes (FIFO)

1. Introduction to named pipes

2. Create a named pipe

(1) Command line mode

(2) Code method

(3) mkfifo() function prototype

3. Open the named pipe file FIFO

4. Open rules for named pipes


1. What is a pipeline

        Pipes are the oldest form of interprocess communication in Unix. We call a stream of data connected from one process to another a "pipe".

        Pipes are half-duplex, and data can only flow in one direction. When two parties need to communicate, two pipes need to be established. It can only be used for communication between parent and child processes or between sibling processes (processes with affinity).

        Typically, a pipe is created by a process, and then the process calls fork, after which the pipe can be used between the parent and child processes. That is, pipeline creation is performed before fork().

2. Anonymous Pipeline (PIPE)

1. Anonymous pipeline introduction

        An anonymous pipe is also an anonymous pipe. A pipe can be created through the pipe() function, and anonymous pipes can only communicate in related processes. What is related? Such as parent process and child process or two child processes created by the same parent process.

        Because the anonymous pipe is half-duplex, to realize the communication between two processes, it is necessary to create two pipes, one with the direction of parent->child, and the other with child->parent.

2, pipe () function

        The function of the pipe() function is to create an unnamed pipe. The following is the function prototype of pipe().

#include <unistd.h> //Header file

int pipe(int pipefd[2]);

parameter:

pipefd[2]: Array of file descriptors, pipefd[0] represents the read end, and pipefd[1] represents the write end.

return value:

Returns 0 on success, -1 on failure.

The following code uses the pipe() function to test the communication between parent and child processes through anonymous pipes.

3. Parent and child processes communicate through anonymous pipes

(1) Demand analysis

1. Two pipelines need to be prepared, parent -> child, child -> parent.

2. Parent->Son pipeline, the father wants to send data, so close the read end, and the son wants to receive data, so close the write end.

3. Son -> parent's pipeline, the father wants to receive data, so close the write end, and the son wants to send data, so close the read end.

4. The parent and child processes need to read or send information through the while loop.

(2) Code implementation

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

using namespace std;

int main()
{
	//pipe匿名管道:1、没有名字  2、是用在由同一个进程fork具有亲缘关系的子进程

	int pid = 0;
	int fatherTochild[2] = { 0 };//父到子文件描述符数组
	int childTofather[2] = { 0 };//子到父文件描述符数组
	
	//管道创建要在进程之前,管道一定是放在进程里面使用的,所以管道要在进程创建前创建
	if (pipe(fatherTochild) < 0 || pipe(childTofather) < 0)
	{
		perror("pipe open error");//管道创建失败
	}
	else
	{
		cout << "管道开启成功" << endl;
		pid = fork();
		//子进程
		if (pid == 0)
		{
			char resbuf[255] = { 0 };
			
			close(fatherTochild[1]);//子进程  父到子 关闭写端
			
			close(childTofather[0]);//子进程  子到父  关闭读端
			while (1)
			{
				read(fatherTochild[0], resbuf, sizeof(resbuf));//接收父亲发过来的信息
				if (strlen(resbuf) != 0)
				{
					cout << "父亲对儿子说:" << resbuf << endl;
				}
				bzero(resbuf, sizeof(resbuf));//清空数组

				cout << "儿子:";
				fgets(resbuf, sizeof(resbuf), stdin);//控制台输入
				write(childTofather[1], resbuf, sizeof(resbuf));//给父亲发信息
				bzero(resbuf, sizeof(resbuf));//清空数组
			}
		}
		else if (pid > 0)//父进程
		{
			char sendbuf[255] = { 0 };
			close(fatherTochild[0]);//父进程  父到子 关闭读端
			
			close(childTofather[1]);//父进程  子到父 关闭写端
			while (1)
			{
				cout << "父亲:";
				fgets(sendbuf, sizeof(sendbuf), stdin);//控制台输入
				write(fatherTochild[1], sendbuf, sizeof(sendbuf));//给孩子发信息
				bzero(sendbuf, sizeof(sendbuf));//清空数组

				read(childTofather[0], sendbuf, sizeof(sendbuf));//接收孩子发过来的信息
				if (strlen(sendbuf) != 0)
				{
					cout << "儿子对父亲说:" << sendbuf << endl;
				}
				bzero(sendbuf, sizeof(sendbuf));//清空数组
			}
		}
	}
	
	return 0;
}

(3) Test results

        Through the test results, it can be found that the father entered the information first, because the son read() first, and the read() function is a blocking function, which ends when the information is read. After the son receives the information, the son executes read(), and then executes write(). At the same time, after the father sends the information, it executes write(), and then executes read(), waiting for the son to send the information. In this way, the information is sent and received cyclically, and the communication between the parent and child processes is realized.

3. Named Pipes (FIFO)

1. Introduction to named pipes

        The anonymous pipes above can only achieve inter-process communication with kinship, if we want to exchange data between unrelated processes, we can use FIFO files to do the job, which are often called named pipes.

        A named pipe is a special type of file, it exists in the form of a file, but it is not a real file, and does not retain data, but only plays a role in data transmission.

2. Create a named pipe

(1) Command line mode

mkfifo xxx.fifo

(2) Code method

umask(0);
mkfifo("/root/projects/test.fifo", 0777);

(3) mkfifo() function prototype

Function: Create pipeline file .fifo

#include <sys/types.h> //Header file
#include <sys/stat.h> //Header file

int mkfifo(const char *pathname, mode_t mode);

parameter:

pathname: file path

mode: file permissions

return value:

Returns 0 on success, -1 on failure.

3. Open the named pipe file FIFO

1. FIFO is different from the pipe created by the pipe call, it is a file with a name and represents an open file descriptor.

2. It must be opened before reading or writing to it.

3. The FIFO file should also be opened or closed with the open and close functions. Except for some additional functions, the entire operation process is the same as the file operation.

4. The path name of a FIFO file passed to the open call is not the path name of a normal file.

4. Open rules for named pipes

1. If the current open operation is to open the FIFO for reading, if a corresponding process has already opened the FIFO for writing, the current open operation will return successfully; otherwise, it may block until a corresponding process opens the FIFO for writing (currently The open operation sets the blocking flag, that is, only O_RDONLY is set), otherwise, if the current open operation does not set the non-blocking flag, that is, O_NONBLOCK, it returns success

2. If the current open operation is to open the FIFO for writing, if a corresponding process has already opened the FIFO for reading, the current open operation will return successfully; otherwise, it may block until a corresponding process opens the FIFO for reading (currently The blocking flag is set for the open operation); or, an ENXIO error is returned (the blocking flag is not set for the current open operation).

3. In layman's terms, to open a FIFO named pipe file, one process needs to open it for writing, and another process needs to open it for reading. Only when there are read open and write open, the named pipe can be opened successfully. Just like a water pipe, the inlet and outlet of the water pipe need to be open at the same time for the water to flow through.

Originality is not easy, please indicate the source when reprinting.

If it is helpful to you, you can like, collect + follow, and it will be updated continuously (hee hee).

Guess you like

Origin blog.csdn.net/wmcy123/article/details/123606929