Interprocess Communication--Pipeline

Keywords: shell

First, the principle of interprocess communication

Each process has its own user address space, and the global variables of any process can not be seen in another process. Therefore, the exchange of data between processes must open a buffer in the kernel through the kernel. Process 1 copies data from user space to the kernel buffer, and process 2 reads data from the kernel buffer. The mechanism provided by the kernel is called process. Intercommunication (IPC)

2. Interprocess Communication-Pipeline

(1) Anonymous Pipeline

Anonymous pipeline is a basic IPC system, which is created by pipe function.

#include <unistd.h>
int pipe(int fd[2]);

The pipe function call successfully returns 0, the call fails to return - 1, the parameter is the file descriptor, fd[0] points to the pipeline reader, fd[1] points to the pipeline writer, and the pipeline is like an open file that can be read(fd[0]) or written (fd[1]) to read and write.

(1) Ideas for verifying anonymous pipelines:
(1) The parent process calls pipe to open up the pipeline and gets two file descriptors pointing to both ends of the pipeline.
(2) The parent process calls fork to create a child process, and the two file descriptors of the child process point to the same pipeline reader and writer.
(3) The parent process closes the write end, the child process closes the read end, the child process writes to the pipeline, and the parent process reads from the pipeline to achieve process communication.
Verification code:

int main()
  5 {
  6     int fds[2];//fds[0] is the pipeline reading end and fds[1] is the pipeline writing end.
  7     if (pipe(fds)<0)    //Pipeline creation Failure Return - 1;
  8     {
  9         perror("pipe");
 10         return 1;
 11     }
 12     //Pipeline creation returns to 0 successfully.
 13     //Implement interprocess communication, parent-child interprocess communication;
 14     pid_t id = fork();
 15     if(id == 0)
 16     {
 17         //child->write
 18         close(fds[0]);//fds[1]->write point
 19         const char* msg = "hello father,i am child,hello pipe!";
 20         while(1)
 21         {
 22             write(fds[1],msg,strlen(msg));
 23             sleep(1);
 24         }
 25     }
 26     else    //father->read;
 27     {
 28         close(fds[1]);//fds[0]->read point
 29         char buf[1024];
 30         while(1)
 31         {
 32             ssize_t s = read(fds[0],buf,sizeof(buf)-1);
 33             if(s >0)
 34             {
 35                 buf[s-1] = 0;
 36                 printf("ywx->#%s\n",buf);
 37             }
 38         }
 39     }
 40     return 0;
 41 }


As you can see, the parent process can output what the child process writes.
(2) Characteristics of anonymous pipelines
(1) Used for blood-related process communication, such as father-son process.
(2) One-way communication
(3) Byte stream-based
(4) Life cycle with process
(5) Synchronization
(3) Several special cases (you verify by yourselves)
(1) If the reader does not read and the writer keeps writing, the pipe will be filled and the writer will be blocked.
(2) If the writing end does not write and the reading end keeps reading, the reading end will be empty and the reading end will be blocked.
(3) If the reader keeps reading and the writer is closed, the reader will stop at the end of the file.
(4) Writer always writes, and when the reader is closed, the writer will be terminated by the operating system.

(2) Named Pipeline

Named pipelines overcome the fact that only blood relationships can communicate, and any two processes can communicate.
Named pipes are created in two ways. One is to build a named pipeline interactively under the shell. The other is to use system functions to build a named pipeline in the program. In the shell mode, mknod or mkfifo functions can be used. as follows

#include <sys/type.h>
#include <sys/stat.h>
int mknod(const char* path,mode_t mod,dev_t dev);
int mkfifo(const char* path,mode_t mod);

Two function calls returned 0 successfully and - 1 failed.
The first parameter path is the full path name (file name) for creating named pipes, mod is the permission for creating named pipes, dev is the device value, depending on the type of file created, which is only used when creating device files.
mknod function to create named pipes

umask(0);
if (mknod("/tmp/fifo",S_IFIFO|0666)==-1)
{
    perror("mknod error");
}
exit(1);

Creating named pipes with mkfifo functions

umask(0);
if (mkfifo("/tmp/fifo",S_IFIFO|0666)==-1)
{
    perror("mkfifo error");
}
exit(1);

"S_IIFIO|0666" specifies the creation of a named pipeline to access 0666. (Note the impact of umash on file permissions.) When a named pipeline is created successfully, it must be opened as open (), which is different from anonymous pipeline, because named pipeline is a file that exists on hard disk and anonymous pipeline is a special file in memory. Note that Open opens a named pipeline process that may block. At the same time, open in read-write mode (O_RDWR) will not block, open in read-only mode (O_RDONLY), then the process calling open function will be blocked until the pipeline is opened in write mode, and open in write mode (O_WRITE) will block until the pipeline is opened in read-write mode.

(1) Verify named pipes

Idea: Create named pipes to communicate between two processes
The code is as follows:
server.c

#include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <unistd.h>
  5 #include <fcntl.h>
  6 #include <string.h>
  7 #define _PATH_ "./mypipe"
  8 #define _SIZE_ 1024
  9 int main()
 10 {
 11     int fd = open(_PATH_,O_WRONLY);
 12     if(fd <0)
 13     {
 14         printf("open file error!\n");
 15         return 1;
 16     }
 17     char buf[_SIZE_];
 18     while(1)
 19     {
 20         printf("please Enter#");
 21         fflush(stdout);
 22         ssize_t s = read(0,buf,sizeof(buf)-1);
 23         if(s>0)
 24         {
 25             buf[s-1] = 0;
 26             write(fd,buf,strlen(buf));
 27 
 28         }
 29     }
 30     close(fd);
 31     return 0;
 32 }
 33 

client.c

#include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <string.h>
  5 #include <fcntl.h>
  6 #include <unistd.h>
  7 int main()
  8 {
  9     umask(0);
 10     if(mkfifo("./mypipe",0666|S_IFIFO)<0)
 11     {
 12         perror("mkfifo");
 13         return 1;
 14     }
 15 
 16     int fd = open("./mypipe",O_RDONLY);
 17     if(fd<0)
 18     {
 19         perror("open");
 20         return 2;
 21     }
 22     char buf[1024];
 23     memset(buf,'\0',sizeof(buf));
 24     while(1)
 25    {
 26        ssize_t s = read(fd,buf,sizeof(buf)-1);
 27        if (s >0)
 28        {
 29             buf[s] = 0;
 30             printf("server say# %s\n",buf);
 31        }
 32        else if(s== 0)
 33        {
 34             printf("server quit!  client begin quit!\n ");
 35             break;
 36        }
 37     }
 38     close(fd);
 39     return 0;
 40 }
 41 

The results are as follows:


In this way, interprocess communication is realized.

(2) Characteristics of Named Pipeline

(1) Any two processes can communicate without consanguinity restriction.
(2) Synchronization
(3) Byte stream-based
(4) Life cycle with process
(5) One-way communication

Posted by madsm on Wed, 26 Jun 2019 13:06:39 -0700