首頁 > 系統教程 > Linux > 詳解Linux設備模型(7)_Class

詳解Linux設備模型(7)_Class

WBOY
發布: 2024-02-13 22:39:19
轉載
1263 人瀏覽過

1. 概述

#在裝置模型中,Bus、Device、Device driver等等都比較好理解,因為它們都對應著實實在在的東西,所有的邏輯都是圍繞著這些實體展開的。然而,本文所要描述的Class則有些不同,因為它是虛擬出來的,只是為了抽象設備的共通性。

詳解Linux設備模型(7)_Class

#舉個例子,一些年齡相仿、需要獲取相似知識的人聚在一起學習,就構成了一個班級(Class)。這個班級可以有自己的名稱(如“295”),但如果離開構成它的學生(Device),它就沒有任何存在意義。另外,班級存在的最大意義是什麼呢?是由老師講授的每一個課程!因為老師只要講一遍,一個班的學生都可以聽到。如果每個學生都在家學習,就要為每個人請一個老師,這樣講授一遍。而講的內容大多是一樣的,這就是極大的浪費。

設備模型中的Class提供了類似的功能。例如,一些相似的Device(學生)需要向使用者空間提供相似的介面(課程)。如果每個裝置的驅動都要實現一遍的話,就會導致核心中存在大量的冗餘程式碼,這就是極大的浪費。所以,Class說了:「我來幫你們實現吧,你們會用就可以了。」

這就是設備模型中Class的功能。再結合內核的註解:A class is a higher-level view of a device that abstracts out low-level implementation details(include/linux/device.h line326),就容易理解了。

2. 資料結構描述

2.1 struct class

struct class是class的抽象,它的定義如下:

   1: /* include/linux/device.h, line 332 */
   2: struct class {
   3:         const char              *name;
   4:         struct module           *owner;
   5:  
   6:         struct class_attribute          *class_attrs;
   7:         struct device_attribute         *dev_attrs;
   8:         struct bin_attribute            *dev_bin_attrs;
   9:         struct kobject                  *dev_kobj;
  10:  
  11:         int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
  12:         char *(*devnode)(struct device *dev, umode_t *mode);
  13:  
  14:         void (*class_release)(struct class *class);
  15:         void (*dev_release)(struct device *dev);
  16:  
  17:         int (*suspend)(struct device *dev, pm_message_t state);
  18:         int (*resume)(struct device *dev);
  19:  
  20:         const struct kobj_ns_type_operations *ns_type;
  21:         const void *(*namespace)(struct device *dev);
  22:  
  23:         const struct dev_pm_ops *pm;
  24:  
  25:         struct subsys_private *p;
  26: };
登入後複製

#其實struct class和struct bus很類似,解釋如下:

name,class的名稱,會在「/sys/class/」目錄下體現。

class_atrrs,該class的預設attribute,會在class註冊到核心時,自動在「/sys/class/xxx_class」下建立對應的attribute檔案。

dev_attrs,該class下每個裝置的attribute,會在裝置註冊到核心時,自動在該裝置的sysfs目錄下建立對應的attribute檔案。

dev_bin_attrs,類似dev_attrs,只不過是二進位類型attribute。

dev_kobj,表示該class下的裝置在/sys/dev/下的目錄,現在一般有char和block兩個,如果dev_kobj為NULL,則預設選擇char。

dev_uevent,當該class下有裝置發生變化時,會呼叫class的uevent回呼函數。

class_release,用於release本身的回呼函數。

dev_release,用於release class內裝置的回呼函數。在device_release介面中,會依序檢查Device、Device Type以及Device所在的class,是否註冊release接口,若有則呼叫對應的release接口release設備指標。

p,和「Linux設備模型(6)_Bus」中struct bus結構一樣,不再說明。

#2.2 struct class_interface

#struct class_interface是這樣的一個結構:它允許class driver在class下有裝置加入或移除的時候,呼叫預先設定好的回調函數(add_dev和remove_dev)。那調用它們做什麼呢?想做什麼都行(例如修改設備的名稱),由具體的class driver實作。

該結構的定義如下:

   1: /* include/linux/device.h, line 434 */
   2: struct class_interface {
   3:         struct list_head        node;
   4:         struct class            *class;
   5:  
   6:         int (*add_dev)          (struct device *, struct class_interface *);
   7:         void (*remove_dev)      (struct device *, struct class_interface *);
   8: };
登入後複製

3. 功能及内部逻辑解析

3.1 class的功能

看完上面的东西,蜗蜗依旧糊里糊涂的,class到底提供了什么功能?怎么使用呢?让我们先看一下现有Linux系统中有关class的状况(这里以input class为例):

root@android:/ # ls /sys/class/input/ -l
lrwxrwxrwx root root 2014-04-23 03:39 event0 -> ../../devices/platform/i2c-gpio.17/i2c-17/17-0066/max77693-muic/input/input0/event0
lrwxrwxrwx root root 2014-04-23 03:39 event1 -> ../../devices/platform/gpio-keys.0/input/input1/event1
lrwxrwxrwx root root 2014-04-23 03:39 event10 -> ../../devices/virtual/input/input10/event10
lrwxrwxrwx root root 2014-04-23 03:39 event2 -> ../../devices/platform/s3c2440-i2c.3/i2c-3/3-0048/input/input2/event2

lrwxrwxrwx root root 2014-04-23 03:39 event8 -> ../../devices/platform/soc-audio/sound/card0/input8/event8
lrwxrwxrwx root root 2014-04-23 03:39 event9 -> ../../devices/platform/i2c-gpio.8/i2c-8/8-0020/input/input9/event9
lrwxrwxrwx root root 2014-04-23 03:39 input0 -> ../../devices/platform/i2c-gpio.17/i2c-17/17-0066/max77693-muic/input/input0

lrwxrwxrwx root root 2014-04-23 03:39 mice -> ../../devices/virtual/input/mice

root@android:/ # ls /sys/devices/platform/s3c2440-i2c.3/i2c-3/3-0048/input/input2/event2/ -l

-r–r–r– root root 4096 2014-04-23 04:08 dev
lrwxrwxrwx root root 2014-04-23 04:08 device -> ../../input2
drwxr-xr-x root root 2014-04-23 04:08 power
lrwxrwxrwx root root 2014-04-23 04:08 subsystem -> ../../../../../../../../class/input
-rw-r–r– root root 4096 2014-04-23 04:08 uevent

root@android:/ # ls /sys/devices/virtual/input/mice/ -l
-r–r–r– root root 4096 2014-04-23 03:57 dev
drwxr-xr-x root root 2014-04-23 03:57 power
lrwxrwxrwx root root 2014-04-23 03:57 subsystem -> ../../../../class/input
-rw-r–r– root root 4096 2014-04-23 03:57 uevent

看上面的例子,发现input class也没做什么实实在在的事儿,它(input class)的功能,仅仅是:

  • 在/sys/class/目录下,创建一个本class的目录(input)
  • 在本目录下,创建每一个属于该class的设备的符号链接(如,把“sys/devices/platform/s3c2440-i2c.3/i2c-3/3-0048/input/input2/event2”设备链接到”/sys/class/input/event2”),这样就可以在本class目录下,访问该设备的所有特性(即attribute)
  • 另外,device在sysfs的目录下,也会创建一个subsystem的符号链接,链接到本class的目录

算了,我们还是先分析一下Class的核心逻辑都做了哪些事情,至于class到底有什么用处,可以在后续具体的子系统里面(如input子系统),更为细致的探讨。

3.2 class的注册

class的注册,是由__class_register接口(它的实现位于”drivers/base/class.c, line 609″)实现的,它的处理逻辑和bus的注册类似,主要包括:

  • 為class結構中的struct subsys_private類型的指標(cp)分配空間,並初始化其中的字段,包括cp->subsys.kobj.kset、cp->subsys.kobj.ktype等等
  • 呼叫kset_register,註冊該class(回憶「Linux裝置模型(6)_Bus」中的描述,一個class就是一個子系統,因此註冊class也是註冊子系統)。過程結束後,在/sys/class/目錄下,就會建立對應該class(子系統)的目錄
  • # 呼叫add_class_attrs接口,將class結構中class_attrs指標所指向的attribute,加入核心。執行完後,在/sys/class/xxx_class/目錄下,就會看到這些attribute對應的檔案

3.3 device註冊時,和class有關的動作

在」Linux裝置模型(5)_device和device driver」中,我們有講過struct device和struct device_driver這兩個資料結構,其中struct device結構會包含一個struct class指標(這從側面說明了class是device的集合,甚至,class可以是device的driver)。當某個class driver向核心註冊了一個class後,需要使用該class的device,透過把自身的class指標指向該class即可,剩下的事情,就由核心在註冊device時處理了。

本節,我們講一下在device註冊時,和class有關的動作:

#device的註冊最終是由device_add介面(drivers/base/core.c)實現了,該介面中和class有關的動作包括:

  • 呼叫device_add_class_symlinks接口,建立3.1小節所描述的各種符號鏈接,即:在對應class的目錄下,建立指向device的符號連結;在device的目錄下,建立名稱為subsystem、指向對應class目錄的符號連結
  • 呼叫device_add_attrs,新增由class指定的attributes(class->dev_attrs)
  • 如果存在對應該class的add_dev回呼函數,呼叫該回呼函數

#」

4. 結束語

#其實在這篇文章結束後,蝸蝸依舊沒有弄清楚class在核心到底是怎麼使用的。不過沒關係,在後續的子系統的分析中(如input子系統、RTC子系統等),我們會看到很多class的使用用例。到時候,再回過頭總結,就會很清楚了。

以上是詳解Linux設備模型(7)_Class的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:lxlinux.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板