Chinaunix首页 | 论坛 | 博客
  • 博客访问: 256748
  • 博文数量: 52
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1538
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-24 07:45
个人简介

生活就像海洋,只有意志坚强的人,才能到达彼岸。

文章存档

2013年(52)

分类: LINUX

2013-08-24 14:36:39

一、Kobject&Kset

1>sysfs文件系统:ram-based,给用户展示内核的数据结构、属性、以及它们之间的关系。

    Linux2.6内核引入了sysfs文件系统。sysfs被看成是与proc同类别的文件系统。sysfs把连接在

系统上的设备和总线组织成分级的文件,使其从用户空间可以访问到。

    sysfs被加载在/sys/目录下,它的子目录包括:

    block:在系统中发现的每个块设备在该目录下对应一个子目录。没个子目录中又包含一些属性

文件,它们描述了这个块设备的各方面属性,如:设备大小。(loop块设备是使用文件来模拟的)。

    bus:在内核中注册的每条总线在该目录下对应一个子目录,如:ide pci scsi usb pcmcia

其中每个总线目录内又包含两个子目录:devices和drivers,devices目录包含了在整个系统中发现

的属于该总线类型的设备,drivers目录包含了注册到该总线的所有驱动。

    class:将设备按照功能进行的分类,如/sys/class/net目录下包含了所有网络接口。

    devices:包含系统所有的设备

    kernel:内核的配置参数

    module:系统中所有模块的信息

    firmware:系统中的固件

    fs:描述系统中的文件系统

    power:系统中电源选项

2>Kobject

    Kobject实现了基本的面向对象管理机制,是构成Linux2.6设备模型的核心结构。它与sysfs文件

系统紧密相连,在内核中注册的每个kobject对象对应sysfs文件系统中的一个目录。

1、初始化kobject结构
    void kobject_init(struct kobject* kobj)

2、将kobject对象注册到Linux系统
    int kobject_add(struct kobject* kobj)

3、初始化kobject,并将其注册到linux系统
    int kobject_init_and_add(struct kobject* kobj,struct kobj_type* ktype,struct kobject* parent,const char* fmt,...)

4、从Linux系统中删除kobject对象
void kobject_del(struct kobject* kobj)

5、将kobject对象的引用计数加1,同时返回该对象指针。
struct kobject* kobject_get(struct kobject* kobj)

6、将kobject的对象引用减1,如果引用计数降为0,则调用release方法释放kobject对象。
void kobject_put(struct kobject* kobj)

kobject的ktype成员是一个指向kobj_type结构指针,该指针中记录了kobject对象的一些属性。

struct kobj_type{
    void(*release)(struct kobject* kobj);
    struct sysfs_ops* sysfs_ops;
    struct attribute** default_attrs;
}
release:用于释放kobject占用的资源,当kobject的引用计数为0时被调用。

struct attribute{
    char* name;
    struct module* owner;
    mode_t mode;
}
struct attribute(属性):对应于kobject的目录下的文件,name成员就是文件名。

struct sysfs_ops{
    ssize_t(*show)(struct kobject*,struct attribute*,chat*);
    ssize_t(*store)(struct kobject*,struct attribute*,const char*,size_t);
};
show:当用户读属性文件时,该函数被调用,该函数将属性值存入buffer中返回给用户态;
store:当用户写属性文件时,该函数被调用,用于存储用户传入的属性值。

2>kset
    kset是具有相同类型的kobject的集合,在sysfs中体现成一个目录,在内核中用kset数据结构表示,定义为:

struct kset{
    struct list_head list;//连接kset中所有kobject的链表头
    spinlock_t list_lock;
    struct kobject kobj;//内嵌的kobject
    struct kset_uevent_ops* uevent_ops;//处理热插拔事件的操作集合
}

int kset_register(struct kset* kset)   在内核中注册一个kset

void kset_unregister(struct kset* kset)  从内核中注销一个kset

热插拔事件:在Linux系统中,当系统配置发生变化时,如:添加kset到系统;移动kobject,一个通

知会从内核空间发送到用户空间这就是热插拔事件。热插拔事件会导致用户空间相应的处理程序被

调用,这些处理程序会通知加载驱动程序,创建设备节点等来响应热插拔事件。

操作集合

struct kset_uevent_ops{
    int(*filter)(struct kset* kset,struct kobject* kobj);
    const char* (*name)(struct kset* kset,struct kobject* kobj);
    int(*uevent)(struct kset* kset,struct kobject* kobj,struct kobj_uevent_env* env);
}

当kset所管理的kobject和kset状态发生变化时(如被加入,移动),这三个函数将被调用。这三个

函数的功能是:

filter:决定是否将事件传递到用户空间。如果filter返回0,将不传递事件。

name:用于将字符串传递给用户空间的热插拔处理程序。

uevent:将用户空间需要的参数添加到环境变量中。

二、设备驱动模型

设备模型元素:总线、驱动、设备

1>总线:总线是处理器设备之间的通道,在设备模型中,所有的设备都通过总线相连,甚至是内部

的虚拟“platform”总线。在linux设备模型中,总线由bus_type结构表示,定义

1、总线的注册使用:
    bus_register(struct bus_type* bus)
若成功,新的总线将被添加进系统,并可在sysfs的/sys/bus下看到。

2、总线的删除使用:
void bus_unregister(struct bus_type* bus)

3、总线方法

int(*match)(struct device* dev,struct device_driver* dev)
当一个新设备或者驱动被添加到这个总线时,该方法被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零值。

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

在为用户空间产生热插拔事件之前,这个方法允许总线添加环境变量。

4、总线属性:

总线属性由结构bus_attribute描述,定义如下:

struct bus_attribute{
    struct attribute attr;
    ssize_t(*show)(struct bus_type*,char* buf);
    ssize_t(*store)(struct bus_type*,const char* buf,size_t count);
}

创建属性:int bus_create_file(struct bus_type* bus,struct bus_attribute* attr)

删除属性:void bus_remove_file(struct bus_type* bus,struct bus_attribute* attr)

2>设备:Linux系统中的每个设备由一个struct device描述

1、注册设备:int device_register(struct device* dev)

    注销设备:void device_unregister(struct device* dev)

    一条总线也是个设备,也必须按设备注册

2、设备属性:设备属性由struct device_attribute描述:
struct device_attribute
{
    struct attribute attr;
    ssize_t(*show)(struct device* dev,struct device_attribute* attr,char* buf)
    ssize_t(*store)(struct device* dev,struct device_attribute,const char* buf,size_count);
}
创建属性
    int devie_create_file(struct device* device,struct device_attribute* entry)

删除属性:
    void device_remove_file(struct device* dev,struct device_attribute* attr)


3>驱动:驱动程序由struct device_driver描述:其中有一个很重要的成员是int(*probe)(struct device* dev).

1、注册驱动
    int driver_register(struct device_driver* drv)

2、注销驱动
    void driver_unregister(struct device_driver* drv)

3、驱动属性使用struct driver_attribute来描述:
struct driver_attribute{
    struct attribute attr;
    ssize_t(*show)(struct device_driver* drv,char* buf);
    ssize_t(*store)(struct device_driver* drv,const char* buf,size_t count);
}

4、创建属性
    int driver_create_file(struct device_driver* drv,struct driver_attribute* attr)

5、删除属性
    void driver_remove_file(struct device_driver* drv, struct driver_attribute* attr)    

三、Platform驱动程序

Platform总线是linux2.6内核加入的一种虚拟总线。platform机制本身使用并不复杂,由两部分组

成:platform_deviceplatform_driver,platform驱动与传统的设备驱动模型相比,优势在于

platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序使用这些资源时使用统一

的接口,这样提高了程序的可移植性。

1>工作流程:通过platform机制开发底层设备驱动的流程如下:

    1、定义platform_device
    
    2、注册platform_device

    3、定义platform_driver

    4、注册platform_driver

2>平台设备描述:

    平台设备使用struct platform_device来描述:
struct platform_device{
    const char* name;//设备名
    int id;//设备编号,配合设备名使用
    struct device dev;
    u32 num_resources;
    struct resource* resource;//设备资源
}

struct platform_device的分配使用:

struct platform_device* platform_device_alloc(const char* name,int id)

参数:
    name:设备名
    id:设备id,一般为-1

3>平台设备注册

int platform_device_add(struct platform_device* pdev)

4>设备资源
    平台设备资源使用struct resource来描述:
struct resource{
    resource_size_t start;//资源的起始物理地址
    resource_size_t end;//资源的结束物理地址
    const char* name;//资源的名称
    unsigned long flags;//资源的类型,比如MEM,IO,IRQ类型
    struct resource *parent,*sibling,*child;//资源链表指针
}

5>获取资源
    struct resource* platform_get_resource(struct platform_device* dev,unsigned int type,unsigned int num)

参数:
    dev:资源所属的设备
    type:获取的资源类型
    num:获取的资源数

6>平台驱动描述
    平台驱动使用struct platform_driver描述。
平台驱动注册使用函数:
    int platform_driver_register(struct platform_driver*)
阅读(2456) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~