Interprocess communication ------ pipes

More linux knowledge: linux directory index


1. What is a pipeline

  A data stream that connects one process to another is called a "pipe" and is usually used to connect the output of one process to the input of another process through a pipe. The pipeline is essentially a cache of the kernel

example:

  Enter the command in the shell: ls -l | grep string, we know that the ls command (actually a process) will list all the files in the current directory, but it will not output directly, but will output to the screen The data is output to the grep process through the pipeline, as the input of the grep process, and then the process filters the input information, and prints the string (in line units) of the information that exists in the string on the screen.

2. The realization principle of the pipeline

write picture description here


3. Anonymous pipes

  1. concept

       Anonymous pipes are file descriptor-based communication methods. When implementing communication between two processes, a child process must be created through fork to realize communication between parent and child processes

  2. read and write rules

    1. When there is no data in the pipeline, the read end (read) is blocked, waiting for valid data to be read
    2. When the pipe capacity is filled with data, the write end (write) blocks, waiting for the process to read the data and then write
    3. If all the file descriptors corresponding to the write end of the pipe are closed, read returns 0, but the data in the previous pipe will be read.
    4. If the file descriptors corresponding to the read ends of all pipes are closed, the write operation will generate a signal, SIGPIPE, which will cause the write process to exit
    5. When the amount of data to be written is not greater than the capacity of the pipe (PIPE_BUF), linux will guarantee the atomicity of the write
    6. When the amount of data to be written is larger than the pipe capacity (PIPE_BUF), linux will no longer guarantee the atomicity of the write
  3. Features

    1. Only one-way communication is possible
    2. It can only be used between processes that are related by blood (father-son, brother, grandfather-grandson), and is often used between father and son
    3. The pipeline has its own synchronization mechanism: the child process writes one, and the parent process reads one
    4. When the pipeline communicates, the service provided to the outer layer is called a byte stream-oriented service
    5. When the process exits, the pipe is also released, consistent with the file
    6. The life cycle of the pipeline is with the process, and the pipeline is gone when the process ends.
      流:相当于水流,写入数据时,写多少字节和你自己有关系,读的时候没有 格式的要求,完全取决你自己;
      字节流:以字节来读取和写入,字节数的大小完全取决于自己
  4. Single process communication principle

write picture description here

  1. The principle of parent-child process communication

    write picture description here

  2. Create pipeline

     #include <unistd.h>
     int pipe(int pipefd[2]);
     参数:fd为文件描述符数组,其中fd[0]表示读端,fd[1]
          表示写端
    返回值:成功返回0,失败返回-1
    
  3. Single process communication example

    Code:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    int main()
    {
        int fd[2];//文件描述符数组
        char buf[1024];//临时缓冲区
        int len;
        ssize_t s;
        ssize_t w;
        if(pipe(fd) == -1){//创建管道
             perror("pipe");
             return -1;
        }
    
         while(1){
             printf("Please enter:");
             fflush(stdout);
              s = read(0,buf,sizeof(buf));//从屏幕上读取内容
              if( s < 0){
                     perror("read");
                     return -2;
                }
                len = strlen(buf);
    
                 w = write(fd[1],buf,len);//将读取的数据写入管道
                if(w != len){
                        perror("write");
                        return -3;
                }
    
    
               memset(buf,0,sizeof(buf));//将buf清0
    
                s = read(fd[0],buf,sizeof(buf));//从管道当中读取数据
                if(s < 0){
                        perror("read");
                        return -4;
                        }
    
                w = write(1,buf,len);//将读的数据写入屏幕
                if(w != len){
                        perror("write");
                        return -5;
                    }
             }
    
            return 0;
        }
    

    result:

    write picture description here

  4. Parent-child process communication example

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    int main()
    {
            int fds[2];
            if(pipe(fds) < 0){//创建一个管道,用于父子间进行通信
                     perror("pipe");
                     return 1;
            }
            char buf[1024];//临时数组,用于存放通信的消息
    
            printf("Please enter:");
            fflush(stdout);
            ssize_t s =  read(0,buf,sizeof(buf)-1);
            if(s > 0){
                buf[s] = 0;
            }
    
            pid_t pid = fork();
            if(pid == 0){//子进程只写,关闭读端
                    close(fds[0]);
                    while(1){
                            sleep(1);
                            write(fds[1],buf,strlen(buf));//将buf的内容写入管道
                    }
            }
            else{//父进程只读,关闭写端
                  close(fds[1]);
                  char buf1[1024];
                  while(1){
                          ssize_t s = read(fds[0],buf1,sizeof(buf1)-1);//从管道里读数据,放入buf
                           if(s > 0){
                                    buf1[s-1] = 0;
                                    printf("client->farther:%s\n",buf1);
                           }
                   }
          }
    }
    

    result:

    write picture description here


4. Named Pipes

  1. Concept
       Named pipe is essentially a pipe file, which can be created by command or by function, user can see

  2. Features

      1. Communication between unrelated processes is possible

      2. A named pipe is a file, and operations related to files are also applicable to it

  3. read and write rules

      1. For the pipe file, when the current process operation is read-only, it will block until a process writes data to it.

      2. For the pipe file, when the current process operation is write-only, it will block until a process reads data from the pipe.

  4. Creation of named pipes

     1. Create with command

            mkfifo filename
    

     2. Function creation

            int mkfifo(const char *filename,mode_t mode);
    
            【参数】:
                filename:创建的有名管道的全路径名
                mode:创建的命名管道的模式,指明其存取权限
    
  5. file copy example

    write.c

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    //读取文件,将文件内容写入管道
    int main()
    {
         mkfifo("tp",0644);//创建一个管道文件
         int  infd = open("123",O_RDONLY);//打开一个文件
         if(infd == -1){
                     perror("open");
                      return 1;    
        }
    
         int outfd = open("tp",O_WRONLY);//打开管道文件,将123文件的内容写入管道文件
        if(outfd == -1){
                    perror("open");
                     return 2;
        }
    
         char buf[1024];//用于存放文件内容
         ssize_t s;
    
         while( (s = read(infd,buf,sizeof(buf))) >0)
         {
                     write(outfd,buf,s);
         }
         close(infd);
         close(outfd);
    
    }
    

    read.c

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    //从管道文件里面读取内容,并将内容写入另一个文件中
    int main()
    {
           int infd = open("abc.bak",O_CREAT | O_WRONLY | O_TRUNC,0644);//创建一个新的文件
           if(infd == -1){
                   perror("open");
                   return 1;
           }
    
            //将从管道读取的内容写入到新的文件中
    
            int outfd = open("tp",O_RDONLY);//打开管道文件
            if(outfd == -1){
                    perror("open");
                    return 2;
            }
    
            char buf[1024];//临时数组
            ssize_t s;
    
            while( (s = read(outfd,buf,sizeof(buf))) > 0)
            {
                write(infd,buf,s);
            }
            close(infd);
            close(outfd);
    
            return 0;
    }
    

    write picture description here

  6. Server, client instance

    server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
//
int main()
{
    umask(0);//将权限清0
    if(mkfifo("./mypipe",0666|S_IFIFO) < 0){//创建管道
        perror("mkfifo");
        return 1;
    }

    int fd = open("./mypipe",O_RDONLY);//打开管道
    if(fd < 0){
        perror("open");
        return 2;
    }

    char buf[1024];
    while(1){
        buf[0] = 0;
        printf("请等待。。。\n");
        ssize_t s = read(fd,buf,sizeof(buf)-1);

        if(s > 0){
            buf[s-1] = 0;//过滤\n
            printf("服务器:%s\n",buf);
        }else if(s == 0){//当客户端退出时,read返回0
            printf("客户端退出,自己退出\n");
            break;
        }
    }
    close(fd);
    return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main()
{

    int fd = open("./mypipe",O_WRONLY);//打开管道
    if(fd < 0){
        perror("open");
        return 1;
    }

    char buf[1024];
    while(1){
        printf("客户端:");
        fflush(stdout);
        ssize_t s = read(0,buf,sizeof(buf)-1);//向管道文件中写数据
        if(s > 0){
            buf[s] = 0;//以字符串的形式写
            write(fd,buf,strlen(buf));
        }
    }
    close(fd);
    return 0;
}

Makefile:

.PHONY:all
all:client server
client:client.c 
    gcc -o $@ $^

server:server.c 
    gcc -o $@ $^

.PHONY:clean
clean:
    rm -f client server mypipe

result:

write picture description here


5. Summary

Types of process relationship difference Nature
anonymous pipe must be kinship Created and opened by pipe kernel cache
named pipe two unrelated processes Created by mkfifo, open with open a file

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325805652&siteId=291194637