Detailed explanation of linux character device driver framework

Related concepts

kernel module

The ko file is in ELF (Excutable And Linking Format) format in terms of data organization, and is a common relocatable object file. This type of file contains code and data and can be used to link into executable files or shared object files. Static link libraries can also be classified into this category.

Module loading and unloading

load

First, insmod will read the .ko module into a piece of memory in user space through the file system, and then execute the system call

sys_init_module() parses the module, relocates the code to a suitable location, and executes the init operation of ko.

uninstall

Enter the command rmmod, and finally need to call sys_delete_module in the system kernel

to implement.

The specific process is as follows: first pass in the name of the module to be uninstalled from the user space, find the pointer of the module to be uninstalled according to the name, ensure that the module we want to uninstall is not dependent on other modules, and then find the exit function of the module itself to realize the uninstallation.

Device No

dev_t is used to indicate the device number, dev_t is a 32-bit number, where the upper 12 bits represent the main device number,

The lower 20 bits represent the minor device number

//Get the main device number of the device according to the device number of the device

#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))

// Extract the minor device number of the device

#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))

//Merge the primary and secondary device numbers into a device number

#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))

cdev

Use the major device number as the cdev_map number, and use the hash function f(major)=major%255 to calculate the subscript of the group number (the hash function is used to distribute the linked list nodes in each array element as evenly as possible to improve query efficiency); each major device number can contain a series of character device nodes with different minor device numbers. If the major device number conflicts, the linked list nodes are sorted with the minor device number as the comparison value.

character driven framework

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)

动态分配count个设备号,设备名为name

cdev_init(struct cdev *cdev, const struct file_operations *fops)

关联字符设备结构体cdev与文件操作结构体file_operations

cdev_add(struct cdev *p, dev_t dev, unsigned count)

添加count个设备至cdev_map散列表中

也可使用register_chrdev一步到位

此时当使用时,需要使用mknod命令创建一个设备节点。当然,也可以先创建类(表示一种类型的设备、/sys/class目录下创建一个新文件夹),再在类下创建设备(/sys/class/new_class/new_device),这样系统便会自动创建设备节点。实际上就是创建了一个设备节点 inode 结构体 ,表示一个具体设备文件(操作这个文件就相当于操作设备,操作的地址是设备寄存器地址)

对于一个LED设备,sysfs可以有两个节点来描述该外设:

1、/sys/class/led_class目录下的节点。这是从high level角度看该LED设备的接口。这里我们可以把一个属于LED设备的属性放到这个目录下,例如:LED颜色、闪烁的频率、占空比等,只要是led class,任何设备都是有这些属性的(无论是接到platform bus还是接到I2C bus)。

2、/sys/devices/virtual/led_class目录下的节点。这个节点是和物理拓扑有关了。其实对于device_create(哪一类设备, 物理拓扑参数,…) 而言,如果你不传递物理拓扑参数(传入NULL),那么设备模型会统一放到virtual的目录下。这个目录保存的属性文件和/sys/class/led_class目录下的是不一样的,这里的属性文件更多的是关注作为某个总线外设的属性。我们可以把这个LED变得复杂些,例如是一个USB接口的LED设备(当然,实际上我是没有见过这样的设备,呵呵~~最多是I2C的LED设备),这时候,这个目录下就会保存这样的属性文件:该设备有多少个endpoint、interface的数目,类别等,而这些属性是和USB总线有直接的关系。

sysfs中所有的目录以及目录下的文件都对应内核中的一个struct kobj实例。

bus目录中所有的子目录都对应内核中的一个struct bus_type实例。

class目录中所有的子目录对应内核中的一个struct class实例

devices目录中的所有目录以及子目录都对应一个struct device实例

Guess you like

Origin blog.csdn.net/qq_52353238/article/details/129440056