织梦CMS - 轻松建站从此开始!

罗索

linux2.6内核文件系统与设备模型

罗索客 发布于 2010-05-06 12:38 点击:次 
Udev 设备文件系统: linux2.6 内核中, devfs 被认为是过时的。
TAG:

Udev设备文件系统:linux2.6内核中,devfs被认为是过时的。

1.udev完全工作在用户态工作,利用设备加入或移除锁发送的热插拔时间(hotplug event)工作。在热插拔时,设备的详细信息会由内核输出到位于/sys的sysfs文件系统,由于udev根据硬件动态更新设备文件,进行设备文件的创建和删除,所以在/dev目录下就会只包含真正存在的设备。Devfs和udev明显区别;采用devfs当一个并不存在的/dev节点被打开适合会自动加载驱动,而udev认为在设备被发现时候才加载驱动模块。

Sysfs文件系统与linux设备模型

Sysfs文件系统:把连接到系统上的设备和总线组织成为一个分级文件,可以由用户空间存取,向用户空间导出内核数据及其他们的属性,sysfs的一个目的就是展示涉笔驱动模型中各组件的层次关系。

设备模型中的关键数据结构:

  1. struct kobject {  
  2.        char                   * k_name;//  
  3.        char                   name[KOBJ_NAME_LEN];//xx对象称  
  4.        struct kref             kref;//对象引用计数  
  5.        struct list_head       entry;// 用于挂接给kobject对象到kset链表  
  6.        struct kobject         * parent;//指向父对象的指针  
  7.        struct kset             * kset;//所属kset的指针  
  8.        struct kobj_type     * ktype;指向对象类型描述符的指针  
  9.        struct dentry          * dentry;//sysfs文件系统中与该对象对应文件节点入口  
  10. };  
  11.  

是构成设备管理能力的核心结构,一个kobject对应于一个sysfs文件系统的一个目录。

Kref成员实现对象应用计数器管理,提供kobject_get(),kobject_put()分别用于增加和减少应用计数器,当引用计数器为0时,该对象使用资源被释放。

Ktype指向kobj_type结构指针,标识该对象类型。

  1. struct kobj_type {  
  2.        void (*release)(struct kobject *);  
  3.        struct sysfs_ops* sysfs_ops;  
  4.        struct attribute** default_attrs;  
  5. }; 

包括了释放kobject占用资源的release()函数,指向sysfs操作的sysfs_ops指针和sysfs文件系统默认属性列表。

  1. struct sysfs_ops {  
  2.        ssize_t (*show)(struct kobject *, struct attribute *,char *);  
  3.        ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);  
  4. }; 

分别用于属性的读和写

一系列的kobject操作函数:

Kobject_init用于初始kobject,设置kobject引用计数器为以,entry指向自身,其所属kset引用计数器加1.

Kobject_add(struct kobject *kobj);//该函数将kobject对象加入linux设备层次,挂接到kobject对象到所属的kset的list链表中,增加kobject引用计数器,在parent指向的目录下创建文件节点,并启动该类型内核对象的hotplug函数。对应有kobject_del()从linux设备层次(hierarchy)中删除kobject对象。

Kobject_register()先调用kobject_init初始化,然后调用kobject_add(),对应相反的是kobject_unregister

2.kset:kobject通过kset组织成为层次化的结构,kset是具有相同类型的kobject的集合。

  1. struct kset {  
  2.   struct subsystem     * subsys;//所在的子系统指针  
  3.   struct kobj_ type     * ktype;//kset对象描述符指针  
  4. struct list_head       list;//用于连接所有object对象的链表头  
  5.  
  6.        struct kobject         kobj;//所以属于该kset的object对象的parent都指向该结构  
  7.  
  8.        struct kset_hotplug_ops * hotplug_ops;//事件操作集  
  9.  
  10. };  

//与kobject相似,linux提供了一系列的函数操作kset,kset_init完成指定的kset初始化,kset_get()和kset_put()分别增加和减少kset对象引用计数器,kset_add()和kset_del()函数把指定的kset对象加入设备层次和从其中删除,kset_register()函数完成kset的注册和kset_unregister函数则完成kset的注销。Kobject被创建或删除时能产生event,kobject所属的kset可以过滤event或者为用户空间添加消息。Kset的uevent_ops成员执行该kset事件集合kset_uevent_ops指针。

3.

struct subsystem {

       struct kset             kset;

       struct rw_semaphore     rwsem;

};//一系列kset的集合,描述一类子系统,如字符设备,块设备等等。每个kset必须属于某个subsystem,设置kset结构中的subsys域指向指定的subsystem可以将kset加入到该subsystem,所有挂接到同一个subsystem的kset共享同一个rwsem信号量,用于同步访问kset中的链表。内核提供类似kset和kobject的函数操作subsystem操作。

 

1.       linux设备模型组件:任一设备都在设备模型中有一个device相对应。

struct device { struct list_head g_list;

        struct list_head node;

        struct list_head bus_list;

        struct list_head driver_list;

        struct list_head intf_list;

        struct list_head children;

        struct device   * parent;

        char    name[DEVICE_NAME_SIZE];

        char    bus_id[BUS_ID_SIZE];

        spinlock_t      lock;

        atomic_t        refcount;

        struct bus_type * bus;

        struct driver_dir_entry dir;

       u32         class_num;

        struct device_driver *driver;

        void            *driver_data;

        void            *platform_data;

        u32             current_state;

        unsigned char *saved_state;

        void    (*release)(struct device * dev); };

Fields ~~~~~~ g_list:     Node in the global device list.

node:       Node in device's parent's children list.

bus_list: Node in device's bus's devices list.

driver_list:   Node in device's driver's devices list.

intf_list:     List of intf_data. There is one structure allocated for each interface that the device supports.

children:      List of child devices.

parent:        *** FIXME ***

name:             ASCII description of device. Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]"

bus_id:           ASCII representation of device's bus position. This field should be a name unique across all devices on the

              bus type the device belongs to.

              Example: PCI bus_ids are in the form of

              <bus number>:<slot number>.<function number>

              This name is unique across all PCI devices in the system.

lock:              Spinlock for the device.

refcount:      Reference count on the device.

bus:        Pointer to struct bus_type that device belongs to.

dir:          Device's sysfs directory.

class_num:     Class-enumerated value of the device.

driver:            Pointer to struct device_driver that controls the device.

driver_data:   Driver-specific data.

platform_data: Platform data specific to the device.

current_state: Current power state of the device.

saved_state:   Pointer to saved state of the device. This is usable by the device driver controlling the device.

release:       Callback to free the device after all references have gone away. This should be set by the allocator of the

              device (i.e. the bus driver that discovered the device).

Device结构体用于描述设备相关的信息设备之间的层次关系,以及设备与总线,驱动的关系。内核提供函数device_resgister()函数将一个新的device对象插入设备模型,并自动在/sys/device下创建一个对应的目录。通常device结构体不单独使用,而包含于更大的机构体中,比如struct pci_dev.驱动程序由device_driver对象描述,对应的机构如下:

struct device_driver {

       const char             *name;

       struct bus_type             *bus;

 

       struct module         *owner;

       const char            *mod_name;   /* used for built-in modules */

 

       int (*probe) (struct device *dev);

       int (*remove) (struct device *dev);

       void (*shutdown) (struct device *dev);

       int (*suspend) (struct device *dev, pm_message_t state);

       int (*resume) (struct device *dev);

       struct attribute_group **groups;

 

       struct dev_pm_ops *pm;

 

       struct driver_private *p;

};//通过内嵌的kobject对象实现引用计数器管理和层次结构组织。Driver_register()用于相设备模型插入新的driver对象,同时在sysfs文件系统中创建相应目录。

 

系统中的总线由struct bus_type描述

Definition

struct bus_type {

char               * name;

       struct subsystem    subsys;//与该总线相关的subsystem

       struct kset             drivers;//所有与该总线相关的驱动程序集合

       struct kset             devices;//所有挂载在该总线上的设备

       struct bus_attribute * bus_attrs;//总线属性

       struct device_attribute    * dev_attrs;//设备属性

       struct driver_attribute    * drv_attrs;//驱动程序属性

       int           (*match)(struct device * dev, struct device_driver * drv);

       int           (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);

int           (*suspend)(struct device * dev, pm_message_t state);

       int           (*resume)(struct device * dev); };

每个bus_type对象都内嵌一个subsystem对象,bus_subsys对象管理系统中所有总线类型的subsystem对象,每个bus_type对象都对应/sys/bus目录下的一个子目录,该目录下都存在两个子目录:devices和drivers(分别对应bus_type机构中的devices和drivers域)

 

 

系统中的设备类由struct class描述,表示一类设备,所有的class对象都属于class_subsys子系统,对应于sysfs文件系统中的/sys/class目录。

/*

 * device classes

 */

struct class {

       const char             *name;

       struct module         *owner;

 

       struct class_attribute             *class_attrs;

       struct device_attribute           *dev_attrs;

       struct kobject                *dev_kobj;

 

       int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);

 

       void (*class_release)(struct class *class);

       void (*dev_release)(struct device *dev);

 

       int (*suspend)(struct device *dev, pm_message_t state);

       int (*resume)(struct device *dev);

 

       struct dev_pm_ops *pm;

       struct class_private *p;

};

struct device_class {

char               * name;

       rwlock_t        lock;

       u32                devnum;

       struct list_head       node;

       struct list_head       drivers;

       struct list_head       intf_list;

       struct driver_dir_entry   dir;

       struct driver_dir_entry   device_dir;

       struct driver_dir_entry   driver_dir;

       devclass_add         add_device;

       devclass_remove           remove_device; };

每个class对象包括一个class——device链表,每个class_device对象表示一个逻辑设备,并通过struct class_device中的dev成员并联一个物理设备。这样,一个逻辑设备总对应一个物理设备,但是一个物理设备却却可能对应多个逻辑设备。

 

属性

在bus,device,driver,class层次上都分别定义了其属性结构体,包括bus_attribute ,driver_attribute, class_device_attribute.这几个结构本质完全相同

 

udev组成:设计目标:

1.       用户空间中执行

2.       动态建立/删除设备文件

3.       允许每个人都不关心主/次设备号

4.       提供LSB标准名称

5.       如果需要,提供固定的名称

Udev由下面3部分分割计划发展,namedev,libsysfs,udev,namedev为设备命名子系统,libsysfs提供访问sysfs文件系统从中获取消息的标准接口,udev提供/dev设备节点文件的动态创建和删除策略。

原理:内核检测到系统新设备后,内核在sysfs文件系统中为新设备生产记录并导出设备信息及其所发生的事件。Udev获取内核导出信息,调用namedev决定设备指定名称,udev调用libsysfs决定应该为该设备的是被文件指定主/次设备号,并用分析获取设备名称和主/次设备号创建/dev设备文件。

Namedev规则:

1.       标签/序号:检查设备是否有唯一的识别标号。

2.       设备设备号:进一步检查总线设备编号,如果找到规则,那么规则中的名字被使用

3.       总线上的拓扑:当设备在总线位置匹配用户指定规则,则使用该该规则指定名称。

4.       替代名称:内核提供的名称匹配指定的替代字符串时,就会使用替代字符串指定的名称。

5.       内核提供的名称:以上步骤规则没有提供,缺省的内核规则将被指定给该设备。

(songok2007)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201005/9344.html]
本文出处:CSDN博客 作者:songok2007
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容