The Linux driver involves three important kernel data structures: file_operations, file, and inode.
In Linux, The inode structure is used to represent files, while the file structure indicates the description of opened files, because for a single file, there may be many file descriptors, therefore, you may have multiple file structures, but all of them point to a single inode structure.
In the system, access operations on I/O devices are performed through specific entries, which are provided by the driver. Generally, the interfaces driven by these devices are explained to the system by the file_operations structure, which is defined in include/Linux/fs. h.
The file_operations data structure is as follows: (2.6 kernel)
Struct file_operations {
Struct module * owner; // pointer to this module. Generally, this_module
Loff_t (* llseek) (struct file *, loff_t, INT); // modify the current read/write location of the file
Ssize_t (* read) (struct file *, char *, size_t, loff_t *);
// Read data synchronously from the device
Ssize_t (* write) (struct file *, const char *, size_t, loff_t *);
// Send data to the device
INT (* readdir) (struct file *, void *, filldir_t );
// Read directory only. For device files, this field is null.
Unsigned int (* poll) (struct file *, struct poll_table_struct *);
// Round-robin function to determine whether non-blocking read or write operations can be performed currently
INT (* IOCTL) (struct inode *, struct file *, unsigned int, unsigned long );
// Execute the device Io control command
INT (* MMAP) (sturct file *, struct vm_area_struct *);
// Request to map the device memory to the process address space
INT (* open) (struct inode *, struct file *); // open
INT (* flush) (struct file *);
INT (* release) (struct inode *, struct file *); // close
INT (* synch) (struct file *, struct dentry *, int datasync); // refresh the data to be processed
INT (* fasync) (INT, struct file *, INT); // notifies the device that the fasync flag has changed.
INT (* Lock) (struct file *, Int, struct file_lock );
Ssize_t (* readv) (struct file *, const struct iovec *, unsigned long *, loff_t *);
Sszie_t (* writev) (struct file *, const struct iovec *, unsigned long *,
Loff_t *); // read/write of the decentralized clustering type
Ssize_t (* sengpage) (struct file *, struct page *, Int, size_t, loff_t *, INT );
Unsigned long (* get_unmaapped_area) (struct file *, unsigned long, unsigned long );
Long (* fcntl) (int fd, unsigned int cmd, unsigned Arg, struct file * filp );
};
As the kernel continues to upgrade, the file_operations structure will become larger and larger, and different versions will be slightly different.
Generally, the device driver only needs to use the five functions in the blue section above!
Linux Device Files correspond to the hardware one by one. Therefore, you can perform operations on the device files. The implementation of these operations is actually to call some standard systems, such as open (),
Read (), write (), close (), etc. In fact, file_operations is the key data structure that associates system calls with drivers. Each member of this structure corresponds to a system call. When a user process uses a system call to perform read/write operations on the device, these system calls determine the corresponding driver through the device's master device number and sub-device number, then read the corresponding function pointer in file_operations, and then hand over the control to the function to complete the Linux Device Driver.
Struct file provides information about the opened file, which is mainly used by the device file driver corresponding to the file system. The structure is as follows:
Struct file {
Mode_t f_mode; // indicates whether the file is readable or writable, fmode_read or fmode_write
Dev _ t f_rdev; // used for/dev/tty
Off_t f_ops; // current file displacement
Unsigned short f_flags; // file flag, o_rdonly, o_nonblock, and o_sync
Unsigned short f_count; // Number of opened files
Unsigned short f_reada;
Struct inode * f_inode; // structure pointer to inode
Struct file_operations * f_op; // file index pointer
}
And struct device_struct.
The block device and character device management table during system startup is defined in file fs/device. h.
Struct device_struct
{
Const char * Name;
Struct file_operations * fops;
}
Static struct device_struct chrdevs [max_chrdev];
Static struct device_struct blkdevs [max_blkdev];
In fact, the block device table and the character device table use the same data structure. These device tables are also called device switches. The difference is that they define a set of function pointers to manage devices. Here, the system uses file_operations to replace those switches. File Operations are interfaces between the file system and the driver. Special files in the system do not correspond to the two when they are created, only the default file structure and I node Structure of the device are assigned to the device file. The actual definition is implemented only when the device is enabled after the system starts.
Relationship between the three:
Struct file_operations is a field of struct file. When we use system call open () to open a device node struct inode, we will get a file struct file and return a file descriptor, the file descriptor is an integer, which is called a handle. Through an access handle, we can access the device file struct.
File. The descriptor is an integer with special meanings. Special positioning has certain meanings or attributes.