Chapter 3 Char Drivers
Char drivers, block drivers, network drivers, the goal of this part is to understand and write a complete char device driver. The first step of driver writing is defining the capabilities the driver will offer to user programs.
1. Data structures
Most of the fundamental driver operations involve three important kernel structures, called file_operations, file, and inode. We’ll take a quick look at each of them.
File Operations
We have some device numbers for our use, file_operations would connect any of our driver’s operations to those numbers. Each open file, represented by a file structure, is associated with its own set of functions(f_op pointing to a file_operations structure). These operations are mostly in charge of implementing the system calls and are therefore, named open, read, and so on.
Book example for scull device driver:
1
2
3
4
5
6
7
8
9
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
File structure
A struct file is a kernel structure that never appears in user programs. The file structure represents an open file. It is created by the kernel on open and is passed to any function that operates on the file, until the last close. Notice, in the kernel sources, file refers to the structure and filp to a pointer to the structure.
inode structure
The inode structure is used by the kernel internally to represent files. Thus it is different from the file structure that represents an open file discriptor. There can be multiple file structures representing multiple open descriptors on a single file, but they all point to a single inode structure. As illustrated in this figure, cited from here, we will come back to this topic later when it comes to Unix File Systems design.
The inode structure contains a great deal of information about the file. Only two fields of this structure are of concerns for writing driver code:
- dev_t i_rdev;
For inode that represents device files, this field contains the actual device number. - struct cdev *i_cdev;
struct cdev represents char devices in kernel.
2. Char Device Registration
Before the kernel invokes your device’s operations, you must allocate and register one or more of these structures.
- To obtain a standalone cdev structure at runtime, we can do this:
1 2
struct cdev *my_cdev = cdev_alloc( ); my_cdev->ops = &my_fops;
- If in a case that you want to embed the cdev structure within a device-specific structure of your own, you can use:
1 2
void cdev_init(struct cdev *cdev, struct file_operations *fops); int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
TBD: ch03 P56
Copyright: all contents are from Linux Device Driver3e(LDD).