随笔 - 303  文章 - 883  trackbacks - 0
<2008年5月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

欢迎光临! 
闲聊 QQ:1074961813

随笔分类(357)

我管理的群

公共blog

  • n维空间
  • Email : java3d@126.com 群 : 12999758

参与管理的论坛

好友的blog

我的其他blog

朋友的网站

搜索

  •  

最新评论

 做新男人

年纪大的人通常会有一种感觉(实际上我还不算大),那就是年轻一代和自己的思想往往会有一些出入,小弟在这里发表下个人拙见,如有看完不爽者请谅解:现在网上年轻一代不是正流行非主流文化嘛!对于一些老人家,往往喜欢对这些现象品头论足,说起来这时代发展就这样呗,想想我们当年,嘿嘿,就我而言吧!彻底的保守派,在很多年轻人看来,从思想或行动上看,完全是个古董那种。但俺也有自己的苦衷,一方面父母管得严,一方面自己生活的环境接触的人就这样,有什么办法呢?于是我选择认命,幸运的是到目前为止,活得还算潇洒,嘿嘿(有点自恋了)。但啊,这时代究竟是时代啊!某一天又出来个新主流了,有人出生的地方,再新的思想就总会有过时的时候。中国有句话说得响亮:“与时俱进”,个人觉得挺有道理,社会生产力发展着,人的需求也在发生变化,哪个时候,没学会玩电脑就算文盲,是吧?这个女人啊!也一样,需求也是越来越丰富啊!市场经济,有需求就会有提供,做新男人,也成了一种新时尚。话是这么说,但不管如何始终还是个男人,这点还没变。

据说在Linux 2.6.18版本的内核之后,出现了一种新的管理设备文件的方法,叫udevuserspace device management)取代我们之前看到的那种devfs管理方式。(这个我也是今天晚上有人告诉,我才知道的,悲哀的很,要知道孤陋寡闻的人是很容易被淘汰的~~怕怕,于是上官网look了下,搞了这个文章算是知识补充吧!),udev的官方文档对它做了如下定义:udev是一种用户空间上的应用程序,它动态地为位于/dev下的当前正被使用的设备,提供一个唯一的入口,udev将取代devfs。关于udev的优势,网上大把资料,试问,哪个东西出来的时候没吹上一车呢,自己seesee,不说也罢!

    下面是一个是一个完整的usb驱动,有人要问了,你小子怎么老来usb,换个其他的,可以不?嘿嘿,对usb太情有独钟了,一想到驱动,总是到它。

与前面所说的devfs在使用上是有所区别的,结构体、使用的函数和实现步骤都存在差异,所谓差异就是说它们还是有一些相似之处的,新男人也还是男人这点还没变。在\linux-2.6.16.20\include\linux\device.h中做如下定义:

struct class {

    const char    * name;

    struct module     * owner;

 

    struct subsystem  subsys;

    struct list_head  children;

    struct list_head  interfaces;

    struct semaphore  sem;   /* locks both the children and interfaces lists */

 

    struct class_attribute      * class_attrs;

    struct class_device_attribute   * class_dev_attrs;

 

    int (*uevent)(struct class_device *dev, char **envp,

              int num_envp, char *buffer, int buffer_size);

 

    void   (*release)(struct class_device *dev);

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

};

 

struct class_device {

    struct list_head  node;

 

    struct kobject       kobj;

    struct class      * class;   /* required */

    dev_t         devt;      /* dev_t, creates the sysfs "dev" */

    struct class_device_attribute *devt_attr;

    struct class_device_attribute uevent_attr;

    struct device     * dev;     /* not necessary, but nice to have */

    void          * class_data; /* class-specific data */

    struct class_device  *parent;   /* parent of this child device, if there is one */

 

    void   (*release)(struct class_device *dev);

    int (*uevent)(struct class_device *dev, char **envp,

              int num_envp, char *buffer, int buffer_size);

    char   class_id[BUS_ID_SIZE];   /* unique to this class */

};

对特定的设备使用特定的结构,下面两个结构来自\linux-2.6.16.20\include\linux\usb.h

struct usb_interface {

    /* array of alternate settings for this interface,

     * stored in no particular order */

    struct usb_host_interface *altsetting;

 

    struct usb_host_interface *cur_altsetting;    /* the currently

                   * active alternate setting */

    unsigned num_altsetting; /* number of alternate settings */

 

    int minor;        /* minor number this interface is

                   * bound to */

    enum usb_interface_condition condition;       /* state of binding */

    struct device dev;       /* interface specific device info */

    struct class_device *class_dev;

};

 

struct usb_class_driver {

    char *name;

    struct file_operations *fops;

    int minor_base;

};

 

在创建的时候要使用到以下函数,它们在\linux-2.6.16.20\include\linux\device.h中定义如下:

extern struct class *class_create(struct module *owner, char *name);//创建一个类,返回一个class

extern void class_destroy(struct class *cls);//销毁一个类

extern struct class_device *class_device_create(struct class *cls,

                     struct class_device *parent,

                     dev_t devt,

                     struct device *device,

                     char *fmt, ...)

                  __attribute__((format(printf,5,6)));//为类创建一个类设备,返回一个class_device

extern void class_device_destroy(struct class *cls, dev_t devt);//销毁一个类设备

 

使用过程可以是这样的(注意:这里做了省略处理):

static struct class *usb_class;

 

int usb_major_init(void)

{

    usb_class = class_create(THIS_MODULE, "usb");

}

 

void usb_major_cleanup(void)

{

    class_destroy(usb_class);

}

 

int usb_register_dev(struct usb_interface *intf,//class_device为参

            struct usb_class_driver *class_driver)

{

    intf->class_dev = class_device_create(usb_class, NULL,

                      MKDEV(USB_MAJOR, minor), //以主设备号和次设备号为参

                       &intf->dev, "%s", temp);

}

 

EXPORT_SYMBOL(usb_register_dev);

 

void usb_deregister_dev(struct usb_interface *intf,

           struct usb_class_driver *class_driver)

{

   class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));

}

 

EXPORT_SYMBOL(usb_deregister_dev);

 

于是对于udev我们又可以得到一个省口水的图:

 

Udev设备管理方式

Devfs设备管理方式

包含必要的头文件

包含必要的头文件

填充file_operations

填充file_operations

创建usb_class

填充usb_driver

register\deregister
+

class_device_create\ class_device_destroy

usb_register\usb_deregister

EXPORT_SYMBOL

module_init\ module_exit


下面给出一个完整的代码

来自:\linux-2.6.16.20\drivers\usb\core\file.c

#include <linux/config.h>

#include <linux/module.h>

#include <linux/spinlock.h>

#include <linux/errno.h>

#include <linux/usb.h>

 

#include "usb.h"

 

#define MAX_USB_MINORS   256

static struct file_operations *usb_minors[MAX_USB_MINORS];

static DEFINE_SPINLOCK(minor_lock);

 

static int usb_open(struct inode * inode, struct file * file)

{

    int minor = iminor(inode);

    struct file_operations *c;

    int err = -ENODEV;

    struct file_operations *old_fops, *new_fops = NULL;

 

    spin_lock (&minor_lock);

    c = usb_minors[minor];

 

    if (!c || !(new_fops = fops_get(c))) {

       spin_unlock(&minor_lock);

       return err;

    }

    spin_unlock(&minor_lock);

 

    old_fops = file->f_op;

    file->f_op = new_fops;

    /* Curiouser and curiouser... NULL ->open() as "no device" ? */

    if (file->f_op->open)

       err = file->f_op->open(inode,file);

    if (err) {

       fops_put(file->f_op);

       file->f_op = fops_get(old_fops);

    }

    fops_put(old_fops);

    return err;

}

 

static struct file_operations usb_fops = {

    .owner =   THIS_MODULE,

    .open =       usb_open,

};

 

static struct class *usb_class;

 

int usb_major_init(void)

{

    int error;

 

    error = register_chrdev(USB_MAJOR, "usb", &usb_fops);

    if (error) {

       err("unable to get major %d for usb devices", USB_MAJOR);

       goto out;

    }

 

    usb_class = class_create(THIS_MODULE, "usb");

    if (IS_ERR(usb_class)) {

       error = PTR_ERR(usb_class);

       err("class_create failed for usb devices");

       unregister_chrdev(USB_MAJOR, "usb");

       goto out;

    }

 

out:

    return error;

}

 

void usb_major_cleanup(void)

{

    class_destroy(usb_class);

    unregister_chrdev(USB_MAJOR, "usb");

}

 

int usb_register_dev(struct usb_interface *intf,

            struct usb_class_driver *class_driver)

{

    int retval = -EINVAL;

    int minor_base = class_driver->minor_base;

    int minor = 0;

    char name[BUS_ID_SIZE];

    char *temp;

 

#ifdef CONFIG_USB_DYNAMIC_MINORS

    minor_base = 0;

#endif

    intf->minor = -1;

 

    dbg ("looking for a minor, starting at %d", minor_base);

 

    if (class_driver->fops == NULL)

       goto exit;

 

    spin_lock (&minor_lock);

    for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {

       if (usb_minors[minor])

           continue;

 

       usb_minors[minor] = class_driver->fops;

 

       retval = 0;

       break;

    }

    spin_unlock (&minor_lock);

 

    if (retval)

       goto exit;

 

    intf->minor = minor;

 

    /* create a usb class device for this usb interface */

    snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);

    temp = strrchr(name, '/');

    if (temp && (temp[1] != 0x00))

       ++temp;

    else

       temp = name;

   intf->class_dev = class_device_create(usb_class, NULL,

                      MKDEV(USB_MAJOR, minor),

                      &intf->dev, "%s", temp);

    if (IS_ERR(intf->class_dev)) {

       spin_lock (&minor_lock);

       usb_minors[intf->minor] = NULL;

       spin_unlock (&minor_lock);

       retval = PTR_ERR(intf->class_dev);

    }

exit:

    return retval;

}

EXPORT_SYMBOL(usb_register_dev);

 

void usb_deregister_dev(struct usb_interface *intf,

           struct usb_class_driver *class_driver)

{

    int minor_base = class_driver->minor_base;

    char name[BUS_ID_SIZE];

 

#ifdef CONFIG_USB_DYNAMIC_MINORS

    minor_base = 0;

#endif

 

    if (intf->minor == -1)

       return;

 

    dbg ("removing %d minor", intf->minor);

 

    spin_lock (&minor_lock);

    usb_minors[intf->minor] = NULL;

    spin_unlock (&minor_lock);

 

    snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);

    class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));

    intf->class_dev = NULL;

    intf->minor = -1;

}

EXPORT_SYMBOL(usb_deregister_dev);


    从这篇文我们发现,技术是不断变化的,换句话说,女人是善变的感情动物,请不要误会,是感情动物:意为善于使用感情作为武器;而绝不是多情,多情是用来形容男人的嘛!对不?呵呵,胡说八道了吧~~
    到这里我们还没说这些要怎么安装配置呢,下个文章见吧!



地震让大伙知道:居安思危,才是生存之道。
posted on 2008-05-03 09:24 小寻 阅读(5167) 评论(4)  编辑  收藏 所属分类: kernel

FeedBack:
# re: 如何编写Linux 驱动程序(四) 2008-05-15 11:44 晕翻
看完你写的"驱动没什么新鲜玩意儿",我在想,LDD那本书居然还在出版,让我非常疑惑.仅仅填几个结构就是驱动程序了啊....怎么连写个积存器的动作都没....  回复  更多评论
  
# re: 如何编写Linux 驱动程序(四) 2008-05-15 17:50 幻想~@@~
        寄存器是有的吧! 感觉写驱动就是做填充动作,并发、I/O控制大多由OS内核完成,听高手说写驱动就是内核API 嘿嘿!
       你刚刚所说的是底层驱动是接近于裸跑的那种吧~~~ 这部分是系统刚启动的时候,硬件初始化阶段完成的,之后这些就交给OS管理了,PC机上这部分内容一部分被包含在BIOS里,一部分包含在OS里。
        比如,在linux 2.6.×源代码中每种体系结构的CPU“arch\(CPU类型)\boot”都有这部分的启动代码,其原理与0.11差不多,不同在于o.11支持的CPU只有X86,所以,boot代码只有"/boot"下,对X86平台而言,这部分的代码对CPU的寄存器,内存(中断、分页),i/o做了简单的初始化,接着系统做了实虚模式转换,硬件资源交与OS内核管理,所以在这种情况下,一切都驱动都是通过注册到内核来实现的,当你填充这些数据结构时,系统会在必要时调用,用户这个时候通过file_operation结构实现,以文件方式管理硬件设备。当然有时候,我们需要在驱动中加入自己的数据结构并对硬件(寄存器等)做初始化。
       如果你对这些内容感兴趣,可以找u-boot或vivi 等bootloader看看,在嵌入平台这部分被分开了,它们不但负责硬件初始化,还负责内核下载,调试等功能。事实上,上面给的驱动是不完全的,非典型的,只是一个简单的介绍,如果要做详细道底层的介绍,我还需要一段时间做准备,写得太离谱的话对初学者来说,是致命的,还有我感觉ldd写得相当不错,可能我比较SB吧,似乎每句话都蕴含深刻的含义!为确保无误的理解,读得很慢。下来我会对如何安装这些驱动和一些细节的东西做尽量详细介绍~~~ 最近比较多事情,所以没赶上
  回复  更多评论
  
# re: 如何编写Linux 驱动程序(四) 2008-10-29 10:15 liwensir
我编译《linux高级程序设计》第9章中的“plp_kmen.c”示例模块时,提示有如下错误,书中是基于2.6.15,我内核树版本为2.6.27,
...
在函数 ‘plp_kmem_init’ 中:
/home/lwxiao/mymodule/9_plp_kmem/plp_kmem.c:193: 错误:隐式声明函数 ‘class_device_create’
/home/lwxiao/mymodule/9_plp_kmem/plp_kmem.c:
在函数 ‘plp_kmem_exit’ 中:
/home/lwxiao/mymodule/9_plp_kmem/plp_kmem.c:212: 错误:隐式声明函数 ‘class_device_destroy’
...

我查过 device.h 头文件,从2.6.15到2.6.27,这两个函数已经改过了,
class_device_create 这个函数在2.6.27的device.h头中已经没有了,不知道替换函数是哪个
class_device_destroy 这个函数还在,但参数已经变了

由于本人水平太菜,实在不知道如何修改示例,让其能成功编译,
哪位能提示下,不甚感激  回复  更多评论
  
# re: 如何编写Linux 驱动程序(四) 2008-10-29 22:34 小寻
根据你所提供的信息,我在2.6.27内核里找到与class_device_create和class_device_destroy对应的两句代码。
 intf->usb_dev = device_create_drvdata(usb_class->class&intf->dev,
           MKDEV(USB_MAJOR, minor), NULL,
           
"%s", temp);

device_destroy(usb_class
->class, MKDEV(USB_MAJOR, intf->minor));
不知能否帮助你解决目前遇到的问题?
  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: