Two important structures in a Linux character device (file, inode)

Source: Internet
Author: User

For Linux systems, the function call relationship between the general character device and the driver is shown in

Describes the process by which a user-space application invokes a program through a system call. In general, in the driver design, the struct file and struct inode are the two structures.

User space when opening a character device using the open () system call function ( int fd = open ("dev/demo", O_RDWR) ) roughly the following process:

    1. Lookup in virtual file system VFS corresponds to a struct inode node corresponding to a character device
    2. Traverse the character device list (Chardevs array) to find the Cdev object based on the cdev_t device number in the Inod node
    3. Create a struct file object (the system uses an array to manage multiple open devices in a process, each with a second speed character as an array subscript that identifies a device object)
    4. Initializes a struct file object that points the File_operations member in the struct file object to the File_operations member in the struct Cdev object (file->fops = cdev->fops)
    5. Callback File->fops->open function
I. INODE structure

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

The kernel uses the inode struct to represent a file inside the kernel . Therefore, it is different from the struct that represents a file descriptor that is already open (that is, the file structure), and we can use multiple file structures to represent multiple files descriptors for the same file, but all of these file structures are now Must point to only one inode struct .

The inode structure contains a whole bunch of file-related information, but for driver code, we only care about two of these domains:

    1. dev_t I_rdev; Represents the node for 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, which is a pointer to the INODE structure when the Inode node points to a character device file.

Here is the source code:

structInode {structHlist_node I_hash; structList_head i_list; structList_head i_sb_list; structList_head I_dentry; unsignedLongI_ino;    atomic_t I_count; unsignedintI_nlink; uid_t I_uid;//inode owner IDgid_t I_gid;//Inode-owned group IDdev_t I_rdev;//If the device file indicates the device number of the recording deviceU64 i_version; loff_t i_size;//the inode represents a very small#ifdef __need_i_size_ordered seqcount_t i_size_seqcount; #endif     structTimespec I_atime;//Inode last access time    structTimespec I_mtime;//Inode Last Modified time    structTimespec I_ctime;//generation time of InodeUnsignedinti_blkbits;    blkcnt_t i_blocks; unsigned Shorti_bytes;    umode_t I_mode;     spinlock_t I_lock; structMutex I_mutex; structRw_semaphore I_alloc_sem; Const structInode_operations *I_op; Const structFile_operations *I_fop; structSuper_block *I_SB; structFile_lock *I_flock; structAddress_space *i_mapping; structAddress_space I_data; #ifdef Config_quotastructDquot *I_dquot[maxquotas]; #endif      structList_head i_devices; Union {structPipe_inode_info *I_pipe; structBlock_device *I_bdev; structCdev *i_cdev;//if the character device, corresponding to the CDEV structure}; }; 
struct inode{...}

Related operation functions for inode

/*kernel function extracts the device number from the Inode*//*Extract the main device number*/Staticinline unsigned imajor (Const structInode *inode)
{
  returnMAJOR (inode->i_rdev);}/*Extract Secondary device number*/Staticinline unsigned iminor (Const structInode *inode) {returnMINOR (inode->i_rdev);}
Second, the file structure body

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

The file struct indicates an already opened document (the device corresponds to the device file), in fact, each open file in the system has a corresponding struct file struct 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, the struct file is either represented as file, or Filp (meaning "file pointer"), note that file refers to the struct file itself, and FILP is a pointer to the struct body.

Here are a few important members:

1, fmode_t F_mode;

This file mode is fmode_read , fmode_write identifies the file as readable, writable, or both. In the open or IOCTL function, you may need to check this field to confirm the read/write permission of the file, you do not have to directly detect read or write permissions, because the kernel itself needs to detect the permissions when doing OCTL operations.

2, loff_t F_pos;

The location of the current read and 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 it receives a loff_t pointer as its last parameter, their read and write operations update the location of the file without the need to perform the FILP->f_pos operation directly. and

3, unsigned int f_flags;

File flags, such as o_rdonly , o_nonblock , and O_sync . You can also check the O_NONBLOCK flag in the driver to see if there are non-blocking requests. Other signs are less used. It is particularly important to note that read and Write permissions are checked using F_mode instead of F_flog. All scalar definitions in the header file

4, struct file_operations *f_op;

Various actions related to the file. When a file needs to perform various operations quickly, the kernel assigns this pointer as part of its implementation of file opening, reading, and writing functions. Filp->f_op its value has never been saved by the kernel as the next reference, which means you can change the various actions associated with the file, which is very efficient.

The file_operation structure is parsed as follows: Linux character device driver file_operations

5, void *private_data;

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

three, Chardevs array

The previous analysis of the user layer open () mentions that the I_cdev members in the data structure struct inode{...} can find Cdev, and all the character devices are in the Chrdevs array, Chrdevs what exactly?

Let's take a look at the definition of Chrdevs:

#defineChrdev_major_hash_size 255StaticDefine_mutex (Chrdevs_lock);
Static structchar_device_struct {structChar_device_struct *next;//struct-Body pointer    unsignedintMajor//Main device number    unsignedintBaseminor;//Secondary device start number    intMINORCT;//Number of second standby numbers    Charname[ -]; structCdev *cdev;/* would die*/ } *chrdevs[chrdev_major_hash_size];//can only hang 255 characters main device <span style= "font-family:arial, Helvetica, Sans-serif; RGB (255, 255, 255);" > </span>

You can see that the global array Chrdevs contains the elements of the 255 (chrdev_major_hash_size value) of a struct char_device_struct, each corresponding to a corresponding master 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 the array, we can know which device numbers are assigned.

Related functions, (these functions have been described in the previous article, now look back:

 Register_chrdev_region () assigns the specified range of device numbers

Alloc_chrdev_region () dynamic distribution of device range

They are all implemented primarily by calling function __register_chrdev_region () ; Note that these two functions are simply registering the device number! If you want to associate with Cdev, you also call Cdev_add ().

Register_chrdev () Requests the specified device number and registers it in the character device driver model.

What it does is:

    1. Register the device number by calling __register_chrdev_region () to implement the
    2. Assign a Cdev, by calling Cdev_alloc () to implement the
    3. Adding Cdev to the drive model, this step associates the device number with the driver. by calling Cdev_add () to implement the
    4. The cdev of the struct Char_device_struct object created in the first step points to the Cdev assigned in the second step. Since Register_chrdev () is an old interface, this step is not required in the new interface.

Iv. Cdev Structural Body

in the Linux kernel, use struct cdev to describe a character device

V. Access to character device files in the file system

Let's take a look at the process by which the upper application open () calls the system call function

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. So, a list of i_devices and Cdev in the inode of the character device is formed.

First, the system calls open when a character device is opened, and through a series of calls, it is eventually executed to Chrdev_open

(Finally, by calling 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)

What Chrdev_open () can do is summarized as follows:

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

2. Set Inode->i_cdev to point to the found Cdev.

3. Add the inode to the linked list of the cdev->list.

4. Use Cdev's 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. Return

After executing Chrdev_open (), the file object's F_op points to the Cdev ops, and then the read, write, and so on of the device performs the corresponding action Cdev.

Get Process Number:
Asm/current.h
Linux/sched.h
#define Current get_current ()

Get Process Number: Current->pid
Get Process Name: Current->comm

Two important structures in a Linux character device (file, inode)

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.