驱动中的类class和节点

2019年3月12日10:56:48 发表评论 4 views

一个类是一个设备的高级视图, 它抽象出低级的实现细节. 驱动可以见到一个SCSI 磁盘或者一个 ATA 磁盘, 在类的级别, 它们都是磁盘. 类允许用户空间基于它们做什么来使用设备, 而不是它们如何被连接或者它们如何工作.

几乎所有的类都在 sysfs 中在 /sys/class 下出现. 因此, 例如, 所有的网络接口可在 /sys/class/net 下发现, 不管接口类型. 输入设备可在 /sys/class/input 下, 以及串行设备在 /sys/class/tty. 一个例外是块设备, 由于历史的原因在 /sys/block. 

早期的Linux内核(版本2.4之前)并没有实现一个统一的设备模型,设备节点的创建一般是mknod命令手动创建或利用devfs文件系统创建。早期 的Linux发行版一般会采用手动创建的方式预先把通常用到的节点都创建出来,而嵌入式系统则会采用devfs的方式。起初Linux2.6 内核还支持devfs,但从2.6.18开始,内核完全移除了devfs系统而采用的udev的方式动态的创建设备节点。因此,新的Linux发行版都采 用udev的方式管理设备节点文件。     udev 依靠所有通过 sysfs 输出给用户空间的设备信息, 并且依靠被 /sbin/hotplug 通知有设备添加或去除. 策略决策, 例如给一个设备什么名子, 可在用户空间指定, 内核之外. 这保证了命名策略被从内核中去除并且允许大量每个设备名子的灵活性.

设定class的好处:设备驱动一般在注册的时候都会调用此类class的一些函数,主要作用就是在sys目录里面创建一些节点,比如cd到/sys /class下面可以看到这一类的设备,与这个相关的就是一些kobjects。当然对于一个新设备,可以注册进一个class也可以不注册进去,如果存 在对应class的话注册进去更好。

从linux内核2.6的某个版本之后,devfs不复存在,udev成为devfs的替代。相比devfs,udev有 很多优势,在此就不罗嗦了,提醒一点,udev是应用层的东东,不要试图在内核的配置选项里找到它;加入对udev的支持很简单,以作者所写的一个字符设 备驱动为例,在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用 class_device_create创建对应的设备。大致用法如下:
struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);
class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, “my_device”);

这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备文件

class_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class *class_create(struct module *owner, const char *name)
    class_create - create a struct class structure
    @owner: pointer to the module that is to "own" this struct class
    @name: pointer to a string for the name of this class.
在/sys/class/下创建类目录

class_device_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class_device *class_device_create(struct class        *cls,
                                         struct class_device *parent,
                                         dev_t               devt,
                                         struct device       *device,
                                         const char          *fmt, ...)

    class_device_create - creates a class device and registers it with sysfs
    @cls: pointer to the struct class that this device should be registered to.
    @parent: pointer to the parent struct class_device of this new device, if any.
    @devt: the dev_t for the char device to be added.
    @device: a pointer to a struct device that is assiociated with this class device.
    @fmt: string for the class device's name

不同的版本上述函数有些修改,使用前要先查看下linux-2.6.30.4/include/linux/device.h里的函数声明,Linux2.6.30,里面就没有class_device_create和class_device_destroy函数,而直接使用device_create和device_destroy。

关于驱动中节点的理解:

首先,类unix系统对设备的访问都是基于文件形式的。在类unix系统中,你要访问一个硬件设备。一般和访问一个普通文件差不多。因此,/dev下的设备节点就被作为这样的一类特殊文件来存在。在驱动程序中同样需要实现各种文件的操作调用,如open,release,read,write,ioctl等。应用程序通过
open("/dev/xxx",O_RDWR)这样的代码来打开设备。驱动程序通过这样的节点向应用程序提供各种服务:如read,write,ioctl等 。

1、驱动程序里面的函数在一般情况下,应用程序是调用不到的。它被隐藏在VFS(虚拟文件系统)的后面。

2、由于存在了VFS。所以,linux下的文件(包括各种设备)都是可以被多个应用程序打开的,从而也可以被多个应用程序使用。

3、对于存在临界资源的设备,一般在驱动程序中需要对临界资源进行保护。从而使得多个应用程序或进程能安全的操作设备。

4、正是引入了VFS这个架构,使得在linux下对设备的访问方法基本相同。例如:向屏幕画图可以用write()系统调用。而向串口写入数据也可以用write()系统调用。

  • yiisaa
  • 这是我的微信扫一扫
  • weinxin
  • zhengweiqiangcom
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: