首页 理论教育字符设备核心结构与操作

字符设备核心结构与操作

【摘要】:下面介绍字符设备的框架,字符设备的核心数据结构是cdev,具体内容如下:从相应的属性中可见,以上的需求都可以通过该结构进行管理。另外在内核中针对字符设备和块设备类型设计了统一的设备驱动管理实体的管理框架,主要的数据结构如下:其中dev为驱动管理的起始设备号,range为管理的范围,data对字符设备驱动来说就是指向cdev。使用设备的操作都是由各种类型的驱动框架提供,相应的会调用驱动具体的接口函数。

下面介绍字符设备的框架,字符设备的核心数据结构是cdev,具体内容如下:

从相应的属性中可见,以上的需求都可以通过该结构进行管理。

1ᤫ生命周期管理

首先,在字符设备框架中,生命周期管理是通过kobj进行的,相应的管理已经通过字符设备框架进行封装,并通过对外的接口统一提供相关功能。包含生命周期管理的字符设备框架对外接口如下:

cdev_get设计成内部使用接口,在文件打开时通过chrdev_open进行调用,这样可以保证引用计数的增加,从而保证不被释放。

下面来看看在cdev生命周期结束时的操作:

为什么会有两个很接近的操作呢?这是由于对cdev的创建分别有静态地创建cdev_init和动态地创建cdev_alloc两种,对应用生命周期结束同样有两种、静态使用cdev_default_release、动态使用cdev_dynamic_release。动态比静态增加了释放内存的操作。但是cdev_purge的工作是什么呢?在需求讨论的时候提到了字符设备是对用户开放使用的,这里设备的生命周期结束时一般是驱动释放操作,相应的VFS中代表实际文件inode的属性就应该调整,该函数就是将inode与cdev的关联关闭,后续的打开设备文件操作会重新加载设备驱动,这样才能保证系统的正确性。

2ᤫ设备分类管理

对设备的分类和具体设备的管理,系统通过设备号来进行,设备号是具体设备的类型和实体的综合,与设备一一对应,由于通过设备号进行设备管理通用的方式,同样适合于块设备,而不同的设备对设备号的管理方式会有差别,所以各自进行单独的设备号管理。

对抽象设备实体如cdev的管理,从设计的角度和设备号分离灵活性更高考虑,将二者进行分离管理。

下面详细分析设备号管理,对字符设备的设备号进行管理的核心实体是char_device_struct,详细内容如下:

字符设备分类比较特殊,并不是只通过主设备号来进行分类的,允许将主设备管理的子设备号分开表示不同类型的设备,作为主类型下面的子类型,每种类型有自己的驱动,char_device_struct就是用来进行这种分类管理以及和驱动绑定的。可见其中通过major主设备号,basemonor基本的子设备号以及minorct子设备数目来表示所管理的设备。相应管理的底层函数是在__register_chrdev_region中,相应的接口如下:

如果major设置为0,则进行主设备号的动态分配。相应的系统也提供静态申请设备号和动态申请设备号两个接口,分别如下:

其中register_chrdev_region为静态申请主设备号,alloc_chrdev_region为动态分配主设备号。

3ᤫcdev实体管理(www.chuimin.cn)

对字符设备来说,由于其主要为用户直接使用,而没有与内核中除VFS外的其他模块关联,所以设计时将cdev既作为对上层VFS的接口也作为对下层驱动框架的接口,来进行统一管理。另外在内核中针对字符设备和块设备类型设计了统一的设备驱动管理实体的管理框架,主要的数据结构如下:

其中dev为驱动管理的起始设备号,range为管理的范围,data对字符设备驱动来说就是指向cdev(也作为设备驱动管理实体)。

相应的内核提供添加和查找的功能,接口分别如下:

具体的由kobj_map负责添加,由kobj_lookup负责查找。

字符设备为了底层设备框架开发方便将添加接口封装为cdev_add以便调用,细节如下:

从代码中可见,其直接调用kobj_map来实现功能。

4ᤫ字符设备驱动注册流程

对字符设备驱动来说,由于其管理的设备号和管理实体cdev是分开管理的,所以字符设备驱动的注册流程是:首先进行所管理的设备号的申请(可以静态申请也可以动态申请);然后是管理实体cdev的申请(可以静态初始化和动态申请);最后通过cdev_add加入进行统一管理即可。新的字符设备驱动都是采用这种方式注册。

对于字符设备驱动的注册,老的内核使用register_chrdev进行,系统需要兼容老的内核,所以提供了接口函数__register_chrdev,而register_chrdev就是简单地调用__register_chrdev,下面通过__register_chrdev来了解新的注册过程。

驱动注册之后,就等待应用程序打开并使用相应的设备了。使用设备的操作都是由各种类型的驱动框架提供,相应的会调用驱动具体的接口函数。

5ᤫ设备操作的重载

字符设备作为上层的抽象设备,要担负起操作重载的工作,这部分工作是在VFS中完成的,接下来看看具体的实现:

重载对用户来说是不可见的,用户并没有感受到相应的重载过程。这样实现也是满足设备层次管理的需要。