Linux environment process communication

xiaoxiao2021-03-06  40

Linux environment process communication

- Research on the working mechanism of unknown pipeline

Author: Cao to

introduction

Linux is one of the best ways to operate and improve programming levels as an open source operating system.

A good program is like a good music, the perfect, clever. Open source programs are verified by countless people, this article will be linux-kernel-

2.6.5

Explain the working mechanism of PIPE as an example.

First, classification of inter-process communication

Most large programs involve some form of process communication, a larger application design "fragment" that can communicate with each other, thereby dividing a task to multiple processes. There are three ways to communicate between processes:

Pipe (PIPE)

Socket (socket)

System V IPC mechanism

The pipeline mechanism has been provided in the early days of UNIX development, it is quite good in the data transfer between the two processes on this machine; the socket is in BSD (Berkeley Software Development), and now the application is quite The extensive; and the System V IPC mechanism The Unix System V version appears.

Second, the working mechanism

The pipe is divided into PIPE (unknown pipeline) and FIFO (named pipe), which are all written data in one end of the pipeline through the core buffer, and sequentially read the data read and write in the other end. It is automatically increased, and the data is read only once, followed by it. When the buffer is full, the read / write process is controlled by the corresponding rule, and when the space buffer has a write data or a full buffer, the write process in the waiting queue continues to read and write. .

Pipe reading and writing rules:

At both ends of the pipe can be described by describing the word FD [0] and FD [1], it is important to note that the end of the pipe is fixed. On one end, only one end can only be read, represented by the description word FD [0], referred to as a pipe reading end; the other end can only be written, represented by the descriptor FD [1], referred to as a pipeline. If you try to read data from the pipeline, you will cause an error to occur. The I / O function of the general file can be used for pipes such as Close, Read, Write, and more.

Fourth, PIPE data structure

First, you want to define a file system type: PIPE_FS_TYPE.

[code] fs / pipe.c

Static struct file_system_type pipe_fs_type = {

.name = "pipefs",

.get_sb = pipefs_get_sb,

.kill_sb = kill_anon_super,

}; [/ code]

Variable PIPE_FS_TYPE The type is Struct File_System_Type to register a file system to the system.

PIPE interacts with the process in a similar file, but there is no corresponding node on the disk, so it is high. PIPE mainly includes an inode and two File structures - used for read and write, respectively. The PIPE buffer first address is stored in the I_PIPE field of Inode points to the PIPE_INODE_INFO structure. However, pay attention to the PIPE inode does not have an image on the disk, and only exchange data in 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 (FS_TYPE, "PIPE:", NULL, PIPEFS_MAGIC);

The superfine 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 ready; 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 waiting queue pointer Wait

3 core buffer base base base base base Base

4 Current data volume

6 Pipe reader data

7 Pipeline writer data

8 waiting for the number of readers in the queue

9 Waiting for the number of queues

11, 12 mainly for FIFO

V. Creation of pipelines:

Create a pipe through the PIPE system call.

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 file objects to get file object pointers for reading pipes

IF (! f1)

Goto no_files;

F2 = GET_EMPTY_FILP (); // Assign file object to get file object pointer for reading pipeline

IF (! f2)

Goto close_f1;

Inode = get_pipe_inode (); call get_pipe_inode to get an index node of the pipe type

IF (! inode) pointer inode.

Goto close_f12;

Error = GET_UNUSED_FD (); two file descriptors for the current process. In the current

In the process descriptor File field of the IF (Error <0) process, there is an FD domain,

Goto close_f12_inode; pointing to the process of file pointer, array

i = error; element is a pointer to the file object.

Error = GET_UNUSED_FD ();

Error <0)

Goto close_f12_inode_i; j = error;

Error = -enomem;

Sprintf (Name, "[% lu]", inode-> i_ino); generates an object directory Dentry,

THIS.NAME = Name; and passing the above two texts

this.len = strlen (name); pointer to the object and pipeline

This.hash = inode-> i_ino; / * WILL Go * / 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 (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 to read

F1-> f_flags = o_rdonly; f_flage is set to read-only, F_OP is set to

F1-> f_op = & read_pipe_fops; address of the read_pipe_fops structure.

F1-> f_mode = 1;

F1-> f_version = 0;

/ * WRITE File * / sets the value of the attribute value for the two file objects used

F2-> f_flags = o_wronly; f_flage is set to write, f_op set to

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 parameter FD array returns

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 pipeline

When the pipe is released, the Release field of F-OP is pointing to PIPE_REELEASE () and PIPE_WRITE_RELEASE () in the reading conduit and writing pipe. Both the two functions call release (), and decide whether to release the PIPE memory page or wake up the process of waiting for the queue of the tube. The following is the code released by the pipe:

Static int pipe_release (struct inode * inode, int dec, 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;}

Seven, the reading and writing of the pipeline

1. Read data from the pipe:

If the write end of the pipe does not exist, it is considered that the end of the data has been read, and the number of readout bytes returned by the read function is 0;

When the write end of the pipe is present, if the number of bytes of the request is greater than the PIPE_BUF, return the existing data byte number in the pipe, if the number of bytes requested is not greater than PIPE_BUF, then return to the existing data byte in the pipe ( At this time, the amount of data in the pipe is less than the amount of data requested); or returns the number of bytes of the request (at this time, the amount of data in the pipe is not less than the requested data).

2. Write data to the pipe:

When writing data in the pipe, Linux will not guarantee the written atomicity, the pipe buffer has an idle area, and the writing process will try to write data to the pipe. If the read process does not read the data in the pipe buffer, the write operation will be blocked.

Eight, the limitations of pipeline

The main limitations of the pipeline are reflected in it:

Only unidirectional data flow;

Can only be used between processes with a relative relationship;

no name;

The buffer of the pipeline is limited (the pipeline is present in memory, and when the pipe is created, the buffer allocates a page size);

The pipe is transmitted is unformatted by no format, which requires the reader of the pipe and the write party necessary to set the format of the data in advance, such as how many bytes are counted as a message (or command, or record), and the like.

Nine, postscript

After writing this article, some of them are found. Due to the length of the code read and written is too lengthy, the space is not listed in the unity. There is a shortage and mistakes, please ask the teachers to correct. Through a period of study of Linux kernel code, open source procedures often are not written by "authoritative", "experts" at home and abroad ", which written by an ordinary programmer. But professionalism, long-term concentration in a certain field can create the wealth that the programmer should cherish.

Special thanks to my partner Zhou Xin and Zhang Bo's strong support and help.

Ten, reference materials

"Code Reading Method and Practice" (Greece) Diomidis Spinellis Zhao Xueliang

Tsinghua University Press

"Linux core guidance" Li Shanping Chen Wenzhi

Zhejiang University Press

"Linux program design authority guide" Yu Xiang Chen Xiangyang Fang Han

Mechanical Industry Press

IBM DeveloperWorks China website

转载请注明原文地址:https://www.9cbs.com/read-72937.html

New Post(0)