Linux character device driver structure (iii)--file, inode structure and Chardevs array and other related knowledge analysis __linux

Source: Internet
Author: User

We studied the character device structure Cdev Linux character device driver Development (i)--character device drive structure (upper) below continue to learn several important data structures of character devices.

First look at the following diagram, which is the virtual file system in Linux, general device files and device driver values between the function call relationship;



The above diagram shows a process by which an application invokes a character device driver, and in general, the design of the device driver concerns the two structures of file and Inode

User space uses the open () function to open a character device FD = open ("/dev/hello", O_RDWR), which calls two data structures struct inode{...} With struct file{...} , both are at the virtual file system VFS, and the following two data structures are parsed:


One, file structure body

in device drivers, this is also a very important data structure, it must be noted that here the file and the user space program in the file pointer is different, user space file is defined in the C library, never appear in the kernel. struct file, however, is the data structure in the kernel , so it does not appear in the user-level program.

The file structure indicates an already open document (the device corresponds to a device file). In fact, each open file in the system has a corresponding struct file structure in the kernel space, which is created by the kernel when the file is opened and passed to any function that operates on the file until the file is closed. If the file is closed, the kernel releases the corresponding data structure.

In the kernel source code, struct file is either represented as file, or Filp (meaning "file pointer"), note that the file refers to the struct file itself, and FILP is the pointer to the struct body.

Here are a few important members:

A--fmode_t f_mode;

This file pattern is Fmode_read, Fmode_write recognizes that the file is readable, writable, or both. You may need to check this field in the open or IOCTL function to confirm read/write access to the file, and you do not have to detect read or write permissions directly, because the kernel itself needs to detect its permissions when you perform OCTL operations.

B--loff_t f_pos;

The location of the current read-write file. is 64 bits. If you want to know where the current file is located, the driver can read the value without changing its position. For Read,write, when they receive a loff_t pointer as their last parameter, their read-write operation is the location of the update file, without the need to perform the FILP->f_pos operation directly. The purpose of the Llseek method is to change the location of the file.

C--unsigned int f_flags;

File flags, such as O_rdonly, O_nonblock, and O_sync. In the driver you can also check the O_NONBLOCK flag to see if there are non-blocking requests. Other signs are less used. In particular, read and write permissions are checked by using F_mode rather than f_flog. All scalars are defined in the header file.

D--struct file_operations *f_op;

Various operations related to the file. The kernel assigns this pointer as part of its ability to open, read, and write files when a file needs to be quickly manipulated. Filp->f_op its value is never saved by the kernel as the next reference, which means you can change the various operations associated with the file, which is very efficient.

The file_operation structure is resolved as follows: Linux character device driver architecture (IV.) knowledge analysis of--file_operations structure

e--void *private_data;

The open system call sets this pointer to a null value before the drive calls the open method. You can be very free to make it your own data field or whatever it is, for example, you can point it to a allocated data, but you must remember to release the memory space of the data before the file struct is destroyed by the kernel. Private_data is useful for saving various state information during a system call.



Second, the inode structure body

The VFS inode contains information such as file access rights, owner, group, size, build time, access time, last modified time, and so on. It is the most basic unit of Linux management file system, and it is also a bridge for file system to connect any subdirectories and files.

The kernel uses the inode structure to represent a file inside the kernel . Therefore, it is different from the structure (that is, the file structure) that represents an open file descriptor, and we can represent multiple file descriptors of the same file using multiple files structures, but at this point all of these file structures are You must point only to an inode structure body .

The inode structure contains a large stack of file-related information, but as far as the driver code is concerned, we only care about the two domains:

(1) dev_t I_rdev;

Represents the node of a device file, which actually contains the device number.

(2) struct Cdev *i_cdev;

struct Cdev is an internal structure of the kernel that is used to represent a character device, and when the Inode node points to a character device file, this field is a pointer to the INODE structure.

The following is the source code:

struct Inode {struct Hlist_node i_hash;
 struct List_head i_list;
 struct List_head i_sb_list;
 struct List_head i_dentry;
 unsigned long I_ino;
 atomic_t I_count;
 unsigned int i_nlink;
 uid_t i_uid;//inode owner ID gid_t i_gid;//inode The owning group ID dev_t If the device file indicates the device number of the recording device i_rdev;//U64;
Loff_t I_size;//inode represents a large number of small #ifdef __need_i_size_ordered seqcount_t i_size_seqcount; #endif struct Timespec I_atime;//inode last access time struct Timespec I_mtime;//inode last modified time struct Timespec i_ctime;//in
 The generation time of ode is unsigned int i_blkbits;
 blkcnt_t i_blocks;
 unsigned short i_bytes;
 umode_t I_mode; 
 spinlock_t I_lock;
 struct Mutex I_mutex;
 struct Rw_semaphore I_alloc_sem;
 const struct Inode_operations *i_op; 
 const struct File_operations *i_fop;
 struct Super_block *i_sb;
 struct File_lock *i_flock;
 struct Address_space *i_mapping;
struct Address_space i_data;
#ifdef config_quota struct Dquot *i_dquot[maxquotas];
 #endif struct List_head i_devices;
Union {  struct Pipe_inode_info *i_pipe;
  struct Block_device *i_bdev; struct Cdev *i_cdev;//If the character device, corresponding to the Cdev structural body};


three, Chardevs array

As can be seen from the diagram, the I_cdev members in the inode{...} can find cdev through the data structure, and all the character devices are in the Chrdevs array struct

Now let's look at the definition of Chrdevs:

#define CHRDEV_MAJOR_HASH_SIZE 255
static Define_mutex (chrdevs_lock);

static struct Char_device_struct {
	struct char_device_struct *next;//struct body pointer
	unsigned int major;              Main equipment number
	unsigned int baseminor;          Secondary equipment starting number
	int minorct;                     Zeper number
	char name[64];
	struct Cdev *cdev; /* would die
/} *chrdevs[chrdev_major_hash_size];      can only hang 255 characters master device <span style= "font-family:arial, Helvetica, Sans-serif; Background-color:rgb (255, 255, 255); > </span>

You can see that the global array Chrdevs contains 255 (chrdev_major_hash_size value) struct char_device_struct elements, each corresponding to a corresponding main device number.

If a device number is assigned, a struct Char_device_struct object is created and added to the Chrdevs, so that by Chrdevs an array, we can know which device numbers are assigned.


Related functions, which have been introduced in the previous article, and now look back:

 register_chrdev_region () assigns the specified device number range

alloc_chrdev_region () dynamically allocating device range

They are mostly done by calling the function __register_chrdev_region () , and note that these two functions are just registered device numbers! If you want to associate with Cdev, you will also call Cdev_add ().

Register_chrdev () Requests the specified device number and registers it with the character device-driven model.

The thing it does is:

A--registers the device number, by calling __register_chrdev_region () to implement

B-Assign a Cdev, by calling Cdev_alloc () to implement

C-Add Cdev to the drive model, which associates the device number with the driver. by calling Cdev_add () to implement the

D--Points the cdev of the struct Char_device_struct object created in the first step to the Cdev assigned in the second step. Since Register_chrdev () is an old interface, this step is not required in the new interface.


Four, Cdev structure body

In Linux character device-driven development (i)-Character device drive structure (above) has parsing.


V. Access to character device files in the file system

Let's look at the process of applying open () to call a system call function at the upper level

For a character device file, its Inode->i_cdev points to the character-driven object Cdev, and if I_cdev is NULL, the device file is not opened.

Because multiple devices can share the same driver. Therefore, the list of i_devices and Cdev in the inode of the character device is composed of a linked list


First, the system calls open when a character device is opened, through a series of calls, which eventually executes to the Chrdev_open

(eventually by calling to the. Open in Def_chr_fops, and Def_chr_fops.open = Chrdev_open. This series of call procedures, this article is not discussed)

 int Chrdev_open (struct inode * inode, struct file * Filp)

The Chrdev_open () can be summed up as follows:

1. According to the device number (Inode->i_rdev), find the corresponding driver in the character device drive model, which is implemented by Kobj_lookup (), and Kobj_lookup () returns the kobject of the corresponding driver Cdev.

2. Set Inode->i_cdev, pointing to the found Cdev.

3. Add the Inode to the Cdev->list list.

4. Use Cdev Ops to set the F_op of the file object

5. If the Open method is defined in OPS, the Open method is called

6. Returns

After Chrdev_open (), the f_op of the file object points to the ops of the Cdev, so that after the read, write, and so on of the device, the corresponding operation of Cdev is performed.



Related Article

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.