Interprocess communication mechanism
Interprocess communication mechanism, also known as IPC mechanism, includes pipeline, semaphore, shared memory, message queue and socket.
Today, let's briefly introduce the pipeline, one of the IPC mechanisms.
The Conduit
When operating in Linux, you must use pipes.
Pipes can be used to transfer data between two processes, such as:
ps -ef | grep "bash"
Where '|' is the pipeline. Its function is to write the result of ps command to the pipeline file, and then grep reads the data from the pipeline file for filtering.
So now you can think about a question:
If process a wants to pass the data obtained from the keyboard to another process b, think about how to complete it with the existing knowledge?
We can have many methods, such as putting the data obtained by process a in a file, and then letting process b obtain it.
However, we know that the file is stored on the disk, and the speed of obtaining data from the disk must be very slow, so we can put it in memory to speed up the acquisition speed.
Our pipeline is stored in memory. We can temporarily put the data of process a in the pipeline, and process b obtains the data from the pipeline.
Famous pipeline
A named pipeline can communicate between any two processes.
How to create a named pipe:
- Command creation:
mkfifo fifo //fifo is the pipe name
- System call creation
#include <sys/types.h> #include <sys/stat.h> //filename is the pipe name and mode is the access right of the created file int mkfifo(const char *filename, mode_t mode);
The command creation result is shown in the figure below:
Now we solve the problem we just thought about through famous channels.
The code of process a is as follows:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <string.h> #include <fcntl.h> int main() { int fd = open("FIFO", O_WRONLY); assert(fd != -1); printf("open FIFO success\n"); while(1) { printf("please input: "); char buff[128] = ; fgets(buff, 128, stdin); write(fd, buff, strlen(buff) - 1); if(strncmp(buff, "end", 3) == 0) { break; } } close(fd); exit(0); }
The code of process b is as follows:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <string.h> #include <fcntl.h> int main() { int fd = open("FIFO", O_RDONLY); assert(fd != -1); printf("open FIFO success\n"); while(1) { char buff[128] = ; int n = read(fd, buff, 127); if(n <= 0 || 0 == strncmp(buff, "end", 3)) { break; } printf("%s\n", buff); } close(fd); exit(0); }
The operation results are as follows:
Unnamed Pipes
Anonymous pipeline is mainly used for communication between parent and child processes.
How anonymous pipes are created:
#include <unistd.h> /* pipe()0 is returned for success and - 1 is returned for failure fds[0]Is the descriptor of the pipeline reader fds[1]Is the descriptor of the pipeline write end */ int pipe(int fds[2]);
Anonymous pipeline code demonstration:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <string.h> int main() { int fd[2]; int res = pipe(fd); assert( res != -1 ); pid_t pid = fork(); assert( pid != -1 ); if( pid == 0 )//Child process operation { close(fd[1]);//Close write side char buff[128] = ; read(fd[0], buff, 127); printf("child read: %s\n", buff); close(fd[0]);//Close the reader } else { close(fd[0]); write(fd[1], "hello", 5); close(fd[1]); } exit(0); }
The operation results are as follows:
Characteristics of pipeline
- The data written to the pipeline is in memory, whether it is famous or unknown
- Pipeline is a half duplex communication mode (simplex, half duplex and full duplex)
- The difference between named and nameless pipes: names can be used between any process, while nameless pipes are mainly between parent and child processes.
So how is the pipeline implemented?
The pipeline is actually like a circular queue. There are head pointers and tail pointers to control the data between pipelines.
The specific performance is shown in the following figure: