Linux Pipe Source Code Analysis

Source: Internet
Author: User

Linux Pipe Source Code Analysis


The pipe pipe, as the oldest IPC mechanism in UNIX, exists in Unix of each version number, primarily for communication between parent and child processes (using fork, so that the child process gets the open file table of the parent process). Pipe () system calls the underlying implementation is equivalent to a special file system, each time a call to create an inode associated with two file. One for reading and one for writing. Thus, one-way flow of data is realized.



User Layer API:

#include <unistd.h>       int pipe (int pipefd[2]);       #define _GNU_SOURCE/             * See Feature_test_macros (7) */       #include <unistd.h>       int pipe2 (int pipefd[2], int flags);


the kernel source code path is as follows:
Sys_pipe (...) SYSCALL_DEFINE1 (pipe, int __user *, fildes) {return sys_pipe2 (fildes, 0);}     Syscall_define2 (pipe2, int __user *, fildes, int, flags) {struct file *files[2];     int fd[2];     int error;     The core is do_pipe error = __do_pipe_flags (fd, files, flags);               if (!error) {//Everything is ready, copy the 2 fd that was just associated with the pipeline to the user space if (unlikely (Copy_to_user (Fildes, FD, sizeof))) {               Fput (Files[0]);               Fput (Files[1]);               PUT_UNUSED_FD (Fd[0]);               PUT_UNUSED_FD (fd[1]);          Error =-efault;               } else {//To update the mapping relationship of FD and file to the file descriptive narrative table of the process fdtable Fd_install (fd[0], files[0]);          Fd_install (Fd[1], files[1]); }} return error;}     static int __do_pipe_flags (int *fd, struct file **files, int flags) {int error;     int FDW, FDR; if (Flags & ~ (O_cloexec | O_nonblock |     O_direct)) Return-einval; Create two struct file error = Create_pipe_files for this pipeline (files, flags);     if (error) return error;     Get two available file descriptive descriptors error = Get_unused_fd_flags (flags);     if (Error < 0) goto Err_read_pipe;     FDR = error;     Error = Get_unused_fd_flags (flags);     if (Error < 0) goto ERR_FDR;     FDW = error;     Audit_fd_pair (FDR, FDW);     Fd[0] = FDR;     FD[1] = FDW;     Return 0;ERR_FDR:PUT_UNUSED_FD (FDR); Err_read_pipe:fput (Files[0]);     Fput (Files[1]); return error;}     /** Create two file instances for pipelines */int create_pipe_files (struct file **res, int flags) {int err;     Create an inode for the pipe and do some initialization of the struct inode *inode = Get_pipe_inode ();     struct file *f;     struct path path; static struct Qstr name = {. Name = ""};     Quick string??     if (!inode) return-enfile;     err =-enomem;     Assign a directory entry Path.dentry = D_alloc_pseudo (PIPE_MNT-&GT;MNT_SB, &name);     if (!path.dentry) goto Err_inode;  Path.mnt = Mntget (PIPE_MNT); Reference count plus 1 d_instantiate (path.dentrY, Inode);     err =-enfile;     f = Alloc_file (&path, Fmode_write, &pipefifo_fops);     if (Is_err (f)) Goto err_dentry; F->f_flags = O_wronly | (Flags & (O_nonblock |     O_direct));     F->private_data = inode->i_pipe;     So you will be clear fd[0] is read Fd[1] is written res[0] = Alloc_file (&path, Fmode_read, &pipefifo_fops);     if (Is_err (res[0])) goto Err_file;     Path_get (&path);     Res[0]->private_data = inode->i_pipe; Res[0]->f_flags = O_rdonly |     (Flags & O_nonblock);     Res[1] = f;     Return 0;err_file:put_filp (f); Err_dentry:free_pipe_info (inode->i_pipe);     Path_put (&path);     Return Err;err_inode:free_pipe_info (Inode->i_pipe);     Iput (Inode); return err;}     static struct inode * Get_pipe_inode (void) {struct Inode *inode = New_inode_pseudo (PIPE_MNT-&GT;MNT_SB);     struct Pipe_inode_info *pipe;     if (!inode) goto Fail_inode; Assign an inode number Inode->i_ino = Get_next_ino ();     Assign a pipe kernel-level object pipe = Alloc_pipe_info ();     if (!pipe) goto fail_iput;     Inode->i_pipe = pipe;     Pipe->files = 2;     Pipe->readers = Pipe->writers = 1;     INODE-&GT;I_FOP = &pipefifo_fops; /* Mark the inode dirty from the very beginning, * That's the It'll never be moved to the dirty * list Becau     Se "mark_inode_dirty ()" would think * that it already _is_ on the dirty list.     */inode->i_state = I_dirty; Inode->i_mode = S_ififo | S_IRUSR |     S_IWUSR;     Inode->i_uid = Current_fsuid ();     Inode->i_gid = Current_fsgid ();     Inode->i_atime = Inode->i_mtime = Inode->i_ctime = Current_time; Return Inode;fail_iput:iput (inode); Fail_inode:return NULL;} File Operation example for pipe const struct File_operations pipefifo_fops = {. open = Fifo_open,. Llseek = no_l     Lseek,. Read = New_sync_read,. Read_iter = Pipe_read,. Write = New_sync_write,. Write_iter = Pipe_write,. Poll = Pipe_poll,. Unlocked_ioctl = Pipe_ioctl,. Release = Pip E_release,. Fasync = Pipe_fasync,};



The overall logic diagram can do this:

TODO: detailed read and write implementation details new_sync_read/write () need to be analyzed.

References:(1) Linux kernel 3.18 source code?(2) Linux man page(3) Linux kernel source code scenario analysis



Linux Pipe Source Code Analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.