Today we are going to talk about interprocess communication in Linux system programming, and we discussed the basic operation of the process in the previous section. In this section, we will discuss inter-process communication.
Common inter-process communication methods are: Nameless pipes, Named pipes, signals, shared memory, message queues, semaphores, sockets.
Let's start by talking about the following:
First, nameless pipe:
1. Pipelines are the oldest form of IPC for UNIX systems, and most UNIX systems offer this type of communication. 、
2, the pipeline is a half-duplex communication mode, the data can only flow in one direction, and can only be used between the processes with affinity. A process's affinity usually refers to a parent-child process relationship.
3, although the pipeline is half-duplex, but we can create two nameless pipes to achieve mutual communication between parent-child processes. Let's look at common programming models:
4. Function prototype:
#include <unistd.h> int pipe (int pipefd[2]);
5, the above is the nameless pipe some basic syntax, when using the nameless pipe communication, before the parent process to create the child process, we create the data is shared, so, by creating a pipeline before fork to achieve communication between the parent-child process, here is a test case to help understand how to use the pipeline:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include < errno.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define bufsize 1024int main () { pid_t pid = -1; char str[bufsize] = {0}; //first implementation of single-duplex, parent write sub-read int fd[1]; int res = -1; res = pipe (FD); if ( -1 == res) { perror ("pipe"); exit (1); } pid = fork (); if (pid >&NBSP;0) { //parent process, parent write sub-read, need to close the read end in the parent process, 0 Read 1 Write printf ("i am parent\n"); memset (str, 0,bufsize); int status = 0; //off Read- close (fd[0]); strcpy (str, "hello world hello linux\n"); //writes data to the pipe res = write (FD [1],str,strlen (str)); if ( -1 == res) { perror ("write"); exit (1); } res = wait (status); if ( -1 ==&Nbsp;res) { perror ("wait "); exit (1); } } else if (0 &NBSP;==&NBSP;PID) { //child process, parent write sub-read, Close the Write-end printf ("i am child\n") in the subprocess; close (fd[1]); memset (str,0, BUFSIZE); res = read (fd[0],str,bufsize); if ( -1 == res ) { perror ("resd "); &nbSp; exit (1); } res = write (Stdout_fileno,str,strlen (str)); if ( -1 == res) { perror ("write"); exit (1); } } return 0;}
The above gives a half-duplex means of communication of the nameless pipe, the so-called full-duplex test code, is to create a process before the creation of two pipelines, in the parent-child process, respectively, turn off a read-write side, so that the parent-child interprocess communication can be realized. While this enables communication between parent-child processes, we can also see a problem where well-known pipelines can only use the kinship between parent-child interprocess communication. This is very inconvenient, down we look at the famous pipe:
Second, FIFO (famous pipeline)
A, the basic concept:
FIFO is sometimes named named pipe. Pipelines can only be used by related processes, and the common ancestor process of these related processes creates pipelines. Processes that are not related to FIFO can also exchange data.
FIFO is a file type. The code of the stat struct member St_mode Indicates whether the file is a FIFO type and can be tested with a S_ISFIFO macro.
B, function prototype:
Creating a FIFO is similar to creating a file.
#include <sys/types.h>
#include <sys/stat.h>
int Mkfifo (const char *pathname, mode_t mode);
Once the MKFIFO has been created with a FIFO, open it by opening it. In fact, general file I/O functions (Close, read, write, unlink, etc.) can be used.
C, FIFO for two purposes:
1. FIFO is used by the shell command to transfer data from one pipeline to another, eliminating the need to create intermediate temporary files.
2. FIFO for customer process-server process application, repeatedly passing data between client process and server process
D, Examples:
1. FIFO Copy output stream:
FIFO can replicate the output stream between serial pipe commands, so there is no need to write data to the intermediate disk file. Pipelines can only be used for linear connections between processes, but FIFO is used for nonlinear connections.
2. Client-Server process
Another application of FIFO is the transfer of data between the client process and the server process. If there is a server process that is associated with multiple client processes that can write its request to a well-known FIFO created by the server process, the problem with FIFO in the type of client process-server process communication is how the server sends the answer back to the individual client processes.
A single FIFO cannot be used because the server process makes a request response to individual client processes, and the requestor does not know when to read to properly read it appropriately. One workaround is for each client process to include its process ID in its request. The server process then creates a FIFO for each process, using the path name based on the process ID of the client process.
3. Let's come down to the specific code:
We use MKFIFO to implement simple communication between processes, there is an inter-process synchronization problem, in general, when a process is written to the data, the other process is not read before they are read by themselves, synchronization between the processes we go back to summarize, here first simple implementation of communication between the two processes.
/*********************************************************** > file name: mkfifo-ser-1.c* > author:xiao_k* > mail:[ Email protected] * > created time: wed 21 feb 2018 09:55:21 pm cst**********************************************************/#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define bufsize 1024int main () { char buf[bufsize]; int res = - 1,fd = -1; res = mkfifo ("./testfifo", 0777); if (-1 == res) { perror ("mkfifo "); &nbsP; exit (1); } fd = open ("./testfifo", O_RDWR| O_EXCL); if ( -1&NBSP;==&NBSP;FD) { Perror ("open"); } while (1) { printf ("ser-> "); memset (Buf,0,BUFSIZE); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;SCANF ("%s", buf); if (0 == &NBSP;STRCMP (buf, "quit")) break; write (Fd,buf,strlen (BUF)); sleep (2); read (fd,buf,bufsize); printf ("cli-> %s\n", buf); } if (Open (". /testfifo ", O_EXCL) > 0 ) { if ( -1 == (res = Unlink ("./testfifo"))) { perror ("unlink"); exit (1); } } else { perror ("open "); exit (1); } return 0;} /********************************************************** * > file name: mkfifo-ser-1.c * > author:xiao_k * > Mail:[email protected] * > Created Time: Wed 21 feb 2018 09:55:21 pm cst **********************************************************/#include <stdio.h># include<stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/ types.h> #include <sys/stat.h> #include <fcntl.h> #define bufsize 1024int main () { char buf[bufsize]; int fd = -1,res= -1 ; fd = open ("./testfifo", o_rdwr| O_EXCL); if ( -1&NBSP;==&NBSP;FD) { perror ("open"); } while (1) { memset (buf,0,bufsize); read (fd,buf,bufsize); printf ("ser-> % S\n ", buf); memset (buf,0,bufsize); printf ("cli->"); &NBSP;&NBSP;&NBSP;&NBSP;SCANF ("%s", buf); if (0 == strcmp (buf, "quit")) break; write (Fd,buf,strlen (BUF)); Sleep (1); } if (Open ("./testfifo", O_EXCL) > 0 ) { if ( -1 == (res = Unlink ("./testfifo"))) { perror ("unlink"); exit (1); } } else &nBsp; { perror ("open "); exit (1); } return 0;}
Above is the most basic Linux communication methods are only to do the most basic examples, the latter I will be divided into thematic separate summary, summed up all the topics, will be integrated use.
Inter-process communication of Linux system programming