Inter-process communication in Linux environment -- Study on the operating mechanism of unknown Pipelines

Source: Internet
Author: User

I. Introduction
As an open-source operating system, Linux is one of the best ways for us to operate the system and improve programming.
Good programs are perfect and clever like good music. Open source code programs are tested by countless people, this article will take linux-kernel-2.6.5 as an example to elaborate the working mechanism of pipe.

Ii. Classification of inter-process communication
Most large programs involve some form of inter-process communication. A large application is designed as a "Fragmentation" that can communicate with each other, so that a task is assigned to multiple processes. There are three methods for inter-process communication:
Pipeline (PIPE)
Socket)
System v ipc Mechanism
The channel mechanism has been provided in the early stage of Unix development. It delivers excellent data transmission between two processes on the local machine. sockets are in the BSD (Berkeley Software Development) and the current application is also quite extensive, and the UNIX System V version of the System v ipc Mechanism appears.

Iii. Working Mechanism
Pipelines are divided into pipe (unknown pipe) and FIFO (Named Pipe). They are all transmitted in the first-in-first-out mode through the kernel buffer, and data is written at one end of the pipeline in sequence, the locations where the other end reads and writes data sequentially are automatically increased. The data is read-only once and then released. When the buffer is full, the read/write process is controlled by the corresponding rules to enter the waiting queue. When an empty buffer has written data or a full buffer has read data, then wake up the write process in the queue to continue reading and writing.

MPs queue read/write rules:
The describe characters FD [0] and FD [1] can be used to describe the two ends of the MPs queue respectively. Note that the two ends of the MPs queue are fixed with tasks. That is, one end can only be used for reading. It is represented by the descriptive word FD [0] And called as the pipeline Reading end. The other end can only be used for writing, which is represented by the descriptive word FD [1, it is called the pipe write end. An error occurs if you try to read data from the write end of the pipeline or write data to the read end of the pipeline. Generally, file I/O functions can be used in pipelines, such as close, read, and write.

Iv. Pipe Data Structure
First, define a file system type: pipe_fs_type.
FS/pipe. c
Static struct file_system_type pipe_fs_type = {
. Name = "pipefs ",
. Get_sb = pipefs_get_sb,
. Kill_sb = kill_anon_super,
};
The pipe_fs_type variable is of the type struct file_system_type used to register a file system with the system.
Pipe interacts with processes in a file-like manner, but there is no corresponding node on the disk, so the efficiency is high. Pipe mainly includes an inode and two file structures-read and write respectively. The first address of pipe is stored in the I _pipe domain of inode pointing to the pipe_inode_info structure. However, note that the pipe inode does not have an image on the disk and only exchanges data in the memory.

Static struct super_block * pipefs_get_sb (struct file_system_type * fs_type,
Int flags, const char * dev_name, void * Data)
{
Return get_sb_pseudo do (fs_type, "pipe:", null, pipefs_magic );
}
For the super generation function.
Include/Linux/pipe. h
# Ifndef _ linux_pipe_fs_ I _h
# DEFINE _ linux_pipe_fs_ I _h

# Define pipefs_magic 0x50495045
Struct pipe_inode_info {
Wait_queue_head_t wait; 1
Char * base; 2
Unsigned int Len; 3
Unsigned int start; 4
Unsigned int readers; 5
Unsigned int writers; 6
Unsigned int waiting_writers; 7
Unsigned int r_counter; 8
Unsigned int w_counter; 9
Struct fasync_struct * fasync_readers; 10
Struct fasync_struct * fasync_writers; 11
};
2 Pipeline wait queue pointer wait
3 kernel buffer base address
4. Current Buffer data volume
6. Reader data volume of the MPs queue
7. Pipeline writer data volume
8. Number of waiting queue readers
9. Number of writers waiting for the queue
11 and 12 are mainly for FIFO

5. MPS queue creation:
Create an MPS queue by calling the pipe system.
Int do_pipe (int * FD)
{
Struct qstr this;
Char name [32];
Struct dentry * dentry;
Struct inode * inode;
Struct file * F1, * F2;
Int error;
Int I, J;

Error =-enfile;
F1 = get_empty_filp (); // assign a file object and obtain the Object Pointer used to read the pipeline.
If (! F1)
Goto no_files;

F2 = get_empty_filp (); // allocate the file object and obtain the Object Pointer used to read the pipeline.
If (! F2)
Goto close_f1;

Inode = get_pipe_inode (); // call get_pipe_inode to obtain the indexing node of the MPs queue type.
If (! Inode) pointer inode.
Goto close_f12;

Error = get_unused_fd (); // obtain the two file descriptors of the current process. In the current
If (error <0) process descriptor file domain, there is an FD domain,
Goto close_f12_inode; // point to the array of file pointers currently opened by the process, array
I = error; the element is a pointer to a file object.

Error = get_unused_fd ();
If (error <0)
Goto close_f12_inode_ I;
J = error;

Error =-enomem;
Sprintf (name, "[% lu]", inode-> I _ino); // generate the object directory dentry,
This. Name = Name;
This. Len = strlen (name); the pointer to the object and the pipeline
This. Hash = inode-> I _ino;/* will go */The index node is connected.
Dentry = d_alloc (pipe_mnt-> mnt_sb-> s_root, & this );
If (! Dentry)
Goto close_f12_inode_ I _j;
Dentry-> d_op = & pipefs_dentry_operations;
D_add (dentry, inode );
F1-> f_vfsmnt = F2-> f_vfsmnt = mntget (pipe_mnt ));
F1-> f_dentry = F2-> f_dentry = DGET (dentry );
F1-> f_mapping = F2-> f_mapping = inode-> I _mapping;

/* Read File */
F1-> f_pos = F2-> f_pos = 0; // set the attribute value for the two file objects used for reading
F1-> f_flags = o_rdonly; f_flage is set to read-only, and f_op is set
F1-> f_op = & read_pipe_fops; Address of the read_pipe_fops structure.
F1-> f_mode = 1;
F1-> f_version = 0;

/* Write File * // set the attribute value for the two file objects used for writing.
F2-> f_flags = o_wronly; f_flage is set to write-only, and f_op is set
The address of the write_pipe_fops structure.
F2-> f_op = & write_pipe_fops;
F2-> f_mode = 2;
F2-> f_version = 0;

Fd_install (I, F1 );
Fd_install (J, F2 );
FD [0] = I; // put two file descriptors into the FD array parameter to return
FD [1] = J;
Return 0;

Close_f12_inode_ I _j:
Put_unused_fd (j );
Close_f12_inode_ I:
Put_unused_fd (I );
Close_f12_inode:
Free_page (unsigned long) pipe_base (* inode ));
Kfree (inode-> I _pipe );
Inode-> I _pipe = NULL;
Iput (inode );
Close_f12:
Put_filp (F2 );
Close_f1:
Put_filp (F1 );
No_files:
Return Error;
}

6. Release of Pipelines
When the pipeline is released, the F-op release domain points to pipe_read_release () and pipe_write_release () in the Read and Write pipelines respectively (). Both functions call release () and decide whether to release the pipe memory page or wake up the pipeline waiting for the queue process.
The following code releases an MPS queue:
Static int pipe_release (struct inode * inode, int decr, int decw)
{Down (pipe_sem (* inode ));
Pipe_readers (* inode)-= decr;
Pipe_writers (* inode)-= decw;
If (! Pipe_readers (* inode )&&! Pipe_writers (* inode )){
Struct pipe_inode_info * info = inode-> I _pipe;
Inode-> I _pipe = NULL;
Free_page (unsigned long) Info-> base );
Kfree (Info );
} Else {wake_up_interruptible (pipe_wait (* inode ));
Kill_fasync (pipe_fasync_readers (* inode), sigio, poll_in );
Kill_fasync (pipe_fasync_writers (* inode), sigio, poll_out );}
Up (pipe_sem (* inode ));
Return 0 ;}

VII. Pipeline read/write
1. read data from the MPs queue:
If the write end of the pipeline does not exist, it is deemed that the data has been read to the end, and the number of read bytes returned by the READ function is 0;
When the write end of the pipeline exists, if the number of bytes requested is greater than pipe_buf, the number of existing data bytes in the pipeline is returned. If the number of bytes requested is not greater than pipe_buf, return the number of data bytes in the MPs Queue (in this case, the data volume in the MPs queue is smaller than the requested data volume), or return the number of bytes in the request (in this case, the data volume in the MPs queue is not smaller than the requested data volume ).
2. Write Data to the MPs queue:
When writing data to an MPS queue, Linux does not guarantee the atomicity of writing data. As soon as the MPs queue buffer has an idle area, the write process tries to write data to the MPs queue. If the read process does not read data from the buffer in the pipeline, the write operation will be blocked.

VIII. Limitations of Pipelines
The main limitations of MPs queue are as follows:
? Only unidirectional data streams are supported;
? It can only be used between unrelated processes;
? No name;
? The buffer of the MPs queue is limited (the MPs queue is in the memory and a page size is allocated to the buffer when the MPs queue is created );
? The pipeline transmits a non-formatted byte stream, which requires that the reader and writer of the pipeline have to specify the data format in advance, for example, how many bytes are counted as a message (or command, or record) and so on.

9. Postscript
After writing this article, I found some shortcomings. Because the Code read and write by the pipeline is too long, the length is not listed in detail. If you have any shortcomings or errors, please correct them. After a period of study on Linux kernel code, open-source programs are often not written by "authoritative" and "experts at home and abroad". They are written by common programmers. However, professional experts can create the wealth that programmers should cherish in a certain domain for a long time. (End)

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.