1. What is a pipe?
Pipelines are divided into nameless pipes and named Pipes, and no special instructions in this article refer to nameless pipes.
The pipeline is one of the original UNIX IPC forms supported by Linux and has the following features:
A. The pipeline is half-duplex, the data can only flow in one direction, when two sides need to communicate, need to set up two pipelines;
B. Can only be used between parent-child processes or sibling processes (affinity processes);
C. A separate file system: A pipeline is a file for the process at both ends of the pipe, but it is not a normal file, it is not a file system, it is a separate file system, and only exists in memory.
D. Read and Write data: a process that writes to the pipeline is read out by the process at the other end of the pipeline. The content that is written is added to the end of the pipe buffer every time, and the data is read from the head of the buffer each time.
2. How do I create a pipeline?
2.1 Include header file
#include <unistd.h>
int pipe (int pipefd[2]);
Return value: Success, returns 0, otherwise returns-1.
The parameter array contains the descriptor for the two files used by the pipe: fd[0]: Read-end, fd[1]: write-side.
3. Reading and writing of pipeline data
The two ends of the pipe can be described by the description character Fd[0] and fd[1], and it is important to note that the ends of the pipe are fixed on the task. That is, one end can only be used for reading, represented by the description word fd[0], which is called the pipe reading end, and the other end can only be used for writing, by the description word fd[1] to be said to be the pipe write end. If you attempt to read data from the pipe write end, or write data to the pipe read end, it will cause an error to occur. General file I/O functions can be used for pipelines, such as close, read, write, and so on.
To read data from the pipeline:
If the write end of the pipeline does not exist, it is considered that the end of the data has been read, the Read function returns the number of read bytes is 0;
When the write side of the pipeline exists, if the number of bytes requested is greater than pipe_buf, the number of existing data bytes in the pipeline is returned, and if the requested number of bytes is not greater than pipe_buf, the number of existing data bytes in the pipeline is returned (in this case, the amount of data in the pipeline is less than the requested amount of data) or return the requested number of bytes (in this case, the amount of data in the pipeline is not less than the requested amount of data)
4. Example 1
#include <unistd.h>
#include <memory.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main ()
{
pid_t pid;
int r_num;
int pipe_fd[2];
Char buf_r[100];
char* P_wbuf;
memset (buf_r,0,sizeof (buf_r));
if (pipe (PIPE_FD) <0)
{
printf ("Pipe Create error\n");
return-1;
}
if ((Pid=fork ()) ==0)
{
printf ("\ n");
Close (pipe_fd[1]);
Sleep (1);
if ((R_num=read (pipe_fd[0],buf_r,100)) >0)
{
printf ("%d numbers read from pipe is:\n%s\n", r_num,buf_r);
}
Close (pipe_fd[0]);
Exit (0);
}
else if (pid>0)
{
Close (pipe_fd[0]);
if (write (pipe_fd[1], "Hello", 5)!=-1)
printf ("Parent write success!\n");
if (write (pipe_fd[1], "pipe", 5)!=-1)
printf ("Parent wirte2 succes!\n");
Close (pipe_fd[1]);
Sleep (3);
Waitpid (pid,null,0);
Exit (0);
}
}
4.1 Function explanation
The function first creates a pipeline, then creates a process with fork, first closes the write end of the pipe in the child process, then reads the data from the pipeline, then closes the pipe read end, and the last child process exits; In the parent process, the read end of the pipe is first closed, then two data is written to the pipeline, and then the pipe write ends Wait for the child process to exit, and finally exit the program;
4.2 Fork () function
The fork () function creates a process that is almost identical to the original process through a system call, and once a process calls the fork () function, the system first assigns resources to the new process, such as the space for storing data and code. All the values of the original process are then copied to the new new process, with only a few values that are different from the value of the original process. The equivalent of cloning a self.
A wonderful thing about a fork call is that it is called only once, but it can return two times, and it may have three different return values:
1) In the parent process, fork returns the process ID of the newly created child process;
2) in the sub-process, fork returns 0;
3) If an error occurs, fork returns a negative value;
4.3 Compiling and running the program
[[email protected] pipe] $ls
Pipe.c
[[email protected] pipe] $GCC pipe.c-o pipe
[[email protected] pipe] $ls
Pipe PIPE.C
[Email protected] Pipe]$./pipe
Parent Write success!
Parent Wirte2 succes!
Ten numbers read from pipe is:
Hello PIPE
[Email protected] pipe]$
5. Example 2
This example is the official standard example, the program first creates a pipeline, then creates a child process, then the parent process closes the read end of the pipe, then writes the arguments passed to the command line to the pipe, and then closes the write end of the pipeline, the parent process exits; in the subprocess, first close the pipe write end, then read the pipeline, program exit;
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main (int argc, char *argv[])
{
int pipefd[2];
pid_t Cpid;
Char buf;
if (argc! = 2)
{
fprintf (stderr, "Usage:%s <string>\n", argv[0]);
Exit (Exit_failure);
}
if (pipe (PIPEFD) = =-1)
{
Perror ("pipe");
Exit (Exit_failure);
}
Cpid = fork ();
if (cpid = =-1)
{
Perror ("fork");
Exit (Exit_failure);
}
if (Cpid = = 0)
{/* child reads from PIPE */
Close (pipefd[1]); /* Close Unused write end */
while (read (pipefd[0], &buf, 1) > 0)
Write (Stdout_fileno, &buf, 1);
Write (Stdout_fileno, "\ n", 1);
Close (pipefd[0]);
_exit (exit_success);
}
Else
{/* Parent writes ARGV[1] to pipe */
Close (pipefd[0]); /* Close Unused read end */
Write (Pipefd[1], argv[1], strlen (argv[1]));
Close (pipefd[1]); /* Reader'll see EOF */
Wait (NULL); /* Wait for child */
Exit (exit_success);
}
}
5.1 Compiling and running the program
[[email protected] pipe2] $ls
Pipe2.c
[[email protected] pipe2] $GCC pipe2.c-o pipe2
[[email protected] pipe2] $ls
Pipe2 pipe2.c
[Email protected] pipe2]$./pipe2 Hello-pipe
Hello-pipe
[Email protected] pipe2]$
interprocess communication One (pipeline)