The pipeline process communication under linux

The concept: a buffer pipeline is managed by the kernel, we put the equivalent of a piece of paper in memory. A connection process of the output end of the pipe. This process will put the information into the pipeline. The other end of the pipe is connected to a process input, the process information is taken into the duct.

Advantages: no lock, byte-oriented data structure need not be defined

Disadvantages: slow, limited capacity, can only be used between parent and child, using a narrow scene

Fundamental:

It does not require a large buffer, which is designed to be annular structure data , so that the pipe can be recycled. When the pipeline is no information, then read from the process piping will wait until the other end of the process into information. When the pipe is filled with information, try placing the information in the process will wait until the other end of the process out information. When the two processes are terminated, the pipeline automatically disappears.

In principle, the use of the pipeline fork mechanism is established, so that the two processes can be connected to the same PIPE. The very beginning, the above two arrows are connected to the same 1 (connected to the two arrows Process 1) a process Process. When the fork copying process, the two connections will be copied to the new process (Process 2). Subsequently, each of the process does not require a close their connections (two black arrows are closed; Process 1 is closed from the input connection to PIPE, Process 2 is connected to the output off PIPE) so that the remaining red connector constitutes PIPE of the above FIG.

Implementation details:

In Linux, the realization of the pipeline does not use specialized data structures, but by means of the inode inode file structure VFS and file system. By two file structure point to the same temporary VFS inode, inode VFS and this in turn points to a physical page achieved. As shown below

There are two file data structures, but they define the file operation routine addresses are different, one of which is the address of the routine to write data to the pipe, and the other is the address of a routine of reading data from the pipeline. In this way, the system calls the user program is still the usual file operations, and the kernel are making use of this abstraction mechanism to achieve this particular pipeline operations.

 

Reading and writing on pipes

      管道实现的源代码在fs/pipe.c中,在pipe.c中有很多函数,其中有两个函数比较重要,即管道读函数pipe_read()和管道写函数pipe_wrtie()。管道写函数通过将字节复制到 VFS 索引节点指向的物理内存而写入数据,而管道读函数则通过复制物理内存中的字节而读出数据。当然,内核必须利用一定的机制同步对管道的访问,为此,内核使用了锁、等待队列和信号。

     当写进程向管道中写入时,它利用标准的库函数write(),系统根据库函数传递的文件描述符,可找到该文件的 file 结构。file 结构中指定了用来进行写操作的函数(即写入函数)地址,于是,内核调用该函数完成写操作。写入函数在向内存中写入数据之前,必须首先检查 VFS 索引节点中的信息,同时满足如下条件时,才能进行实际的内存复制工作:

       ·内存中有足够的空间可容纳所有要写入的数据;

       ·内存没有被读程序锁定。

     如果同时满足上述条件,写入函数首先锁定内存,然后从写进程的地址空间中复制数据到内存。否则,写入进程就休眠在 VFS 索引节点的等待队列中,接下来,内核将调用调度程序,而调度程序会选择其他进程运行。写入进程实际处于可中断的等待状态,当内存中有足够的空间可以容纳写入数据,或内存被解锁时,读取进程会唤醒写入进程,这时,写入进程将接收到信号。当数据写入内存之后,内存被解锁,而所有休眠在索引节点的读取进程会被唤醒。

     管道的读取过程和写入过程类似。但是,进程可以在没有数据或内存被锁定时立即返回错误信息,而不是阻塞该进程,这依赖于文件或管道的打开模式。反之,进程可以休眠在索引节点的等待队列中等待写入进程写入数据。当所有的进程完成了管道操作之后,管道的索引节点被丢弃,而共享数据页也被释放。

Linux函数原型:

#include <unistd.h>

int pipe(int filedes[2]);

filedes[0]用于读出数据,读取时必须关闭写入端,即close(filedes[1]);

filedes[1]用于写入数据,写入时必须关闭读取端,即close(filedes[0])。

程序实例:

int main(void)
{
    int n;
    int fd[2];
    pid_t pid;
    char line[MAXLINE];
   
    if(pipe(fd)  0){                 /* 先建立管道得到一对文件描述符 */
        exit(0);
    }

    if((pid = fork())  0)            /* 父进程把文件描述符复制给子进程 */
        exit(1);
    else if(pid > 0){                /* 父进程写 */
        close(fd[0]);                /* 关闭读描述符 */
        write(fd[1], "\nhello world\n", 14);
    }
    else{                            /* 子进程读 */
        close(fd[1]);                /* 关闭写端 */
        n = read(fd[0], line, MAXLINE);
        write(STDOUT_FILENO, line, n);
    }

    exit(0);
}

 

Guess you like

Origin www.cnblogs.com/best-farmer/p/10986400.html