Interprocess communication (IPC): nameless pipe and named pipe

Posted by mraza on Tue, 28 Dec 2021 17:22:29 +0100

Nameless pipe ❤️ ❤️ ❤️

  • Pipe is also called anonymous pipe. It is the oldest form of IPC (interprocess communication) in UNIX system. All UNIX systems support this communication mechanism.
  • When the parent process calls the pipe function, the kernel will create a cache in the kernel space when executing the pipe function. This cache is the nameless pipe

Characteristics of unknown pipeline:

1. Half duplex, data can only flow in one direction at the same time.

2. Data can only be written from one end of the pipe and read from the other end.

3. Data written to the pipeline follows the first in, first out rule.

4. The data transmitted by the pipeline is unformatted, which requires that the reader and writer of the pipeline must agree on the data format in advance, such as how many bytes count as a message.

5. The pipeline is not an ordinary file and does not belong to a file system. It only exists in memory.

6. The pipeline corresponds to a buffer in memory. Different systems may not have the same size. (general default 64K)

7. Reading data from the pipeline is a one-time operation. Once the data is read, it will be discarded from the pipeline to free up space for writing more data.

8. The pipeline has no name and can only be used between processes with common ancestors (parent process and child process, or two brother processes, which are related to each other)

pipe function

#include <unistd.h>

int pipe(int pipefd[2]);
/*******************************************
Function: create anonymous pipe.
Parameters:
	pipefd : Is the first address of the int array, which stores the file descriptors pipefd[0] and pipefd[1] of the pipeline.
	When a pipeline is established, it creates two file descriptors fd[0] and fd[1]. Where fd[0] is fixed for the read pipe and fd[1] is fixed for the write pipe. Generally, the functions of file I / O can be used to operate the pipeline (except lseek()).
Return value: 	 0 is returned for success and - 1 is returned for failure
************************************************/
  • To enable parent-child processes to communicate with each other, you can create two pipes
  • Read pipeline: when there is data, the data in the pipeline will be read whether there is data at the writing end or not; When there is no data, if the writer does not exist, read returns 0. If a process has a writer, read is blocked
  • Write pipeline: you can write with a read end; If no read end exists, the pipeline breaks and the process receives the SIGPIPE signal (13)
  • Half duplex pipe after fork:

Parent process - | pipe | > example of child process

  • The parent process closes the read side and the child process closes the write side:

  • Sample code pipe c:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    //int pipe(int pipefd[2]);
    int main()
    {
        int fd[2];
        int pid;
        char buf[32] = {0};
        if(pipe(fd) == -1){            //Create the pipeline and judge whether the creation failed
            printf("creat pipe fail\n");
        }
        pid = fork();                  //Create process
        if(pid < 0){                   //If the creation process fails
            printf("creat pid fail\n");
        }
        else if(pid > 0){             //Enter parent process
            printf("this is father\n");
            close(fd[0]);             //Turn off read
            write(fd[1],"wo nen die!",strlen("wo nen die!")); //Write string to fd[1]
            sleep(1); //Equal child process exit
        }
        else{                        //Enter child process
            printf("this is child\n"); 
            close(fd[1]);           //Turn off write
            read(fd[0],buf,128);    //Read the string written in the parent process from fd[0]
            printf("read father %s\n",buf); //Print
        }
        return 0;
    }
    
    

Named pipeline (FIFO) ❤️ ❤️ ❤️

  • A named pipe, also known as a named pipe, is a pipe file that exists in the file system directory.
  • The pipeline file is just a mark in the file system and does not occupy space on the disk. When in use, open up space in memory as a channel for data interaction between the two processes.
  • FIFO is different from the anonymous pipeline in that it provides a path name associated with it and exists in the file system in the form of FIFO file. In this way, even processes that are not related to the creation process of FIFO can communicate with each other through FIFO as long as they can access the path. Therefore, processes that are not related to FIFO can also exchange data.

mkfifo

  • You can create a pipe file directly at the terminal using the shell command mkfifo file name

  • Create with function:

    #include <sys/types.h>
    #include <sys/stat.h>
    
    int mkfifo(const char *pathname, mode_t mode);
    
    • Function: creation of famous pipes.
    • Parameters:
      • Pathname: common pathname, that is, the name of the created FIFO.
      • Mode: the permission of the file, which is the same as the mode parameter in the open() function of opening an ordinary file.
    • Return value: 0 is returned successfully; Failure returns - 1. (if the file exists, return - 1. In this case, errno = EEXIST)
  • When open() opens the FIFO in read-only mode, it is blocked until a process opens the FIFO for writing

  • When open() opens the FIFO in write only mode, it is necessary to block a process from opening the FIFO for reading

Sample code

  • Send mkfifo_w.c:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    	
    int main()
    {
    	
    	if(mkfifo("./named pipe",0600) == -1 && errno != EEXIST){
    		printf("creat named pipe failed\n"); 
    		perror("why");
    	}
    
    	int fd = open("./named pipe",O_WRONLY);
    	write(fd,"NB 666 My Baby!\n",strlen("NB 666 My Baby!\n"));
    		
    	close(fd);
    
    	return 0;
    }
    
  • Receive mkfifo_r.c:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    	
    int main()
    {
    	int i = 5;
    	char buf[128] = {0};
    
    	if(mkfifo("./named pipe",0600) == -1 && errno != EEXIST){
    		printf("creat named pipe failed\n"); 
    		perror("why");
    	}
    
    	int fd = open("./named pipe",O_RDONLY);
    	while(i--){
    		read(fd,buf,128);
    		printf("read from named pipe:\n%s",buf);
    		sleep(1);
    	}
    	close(fd);
    
    	return 0;
    }
    
  • Receiver display:

Topics: C Linux Embedded system kernel multiple processes