精华内容
下载资源
问答
  • 总线 设备 驱动

    2021-01-02 15:27:01
    2.linux的/sys目录下就是包含系统中总线设备还有驱动等相关信息 [root@yj423 /sys]#ls block class devices fs module bus dev firmware kernel power block:块设备 bus:系统中的总线 class: 设备类型,比如...

    总线和设备

    总线是把多个同类型的设备连接起来的一组信号线。
    在这里插入图片描述
    设备就是有某种接口的硬件,驱动就是控制驱动设备的程序(软件)。

    2.linux的/sys目录下就是包含系统中总线,设备还有驱动等相关信息

    [root@yj423 /sys]#ls
    block     class     devices   fs        module
    bus       dev       firmware  kernel    power
    block:块设备
    bus:系统中的总线
    class: 设备类型,比如输入设备
    dev:系统中已注册的设备节点的视图,有两个子目录char和block。
    devices:系统中所有设备拓扑结构视图
    fireware:固件
    fs:文件系统
    kernel:内核配置选项和状态信息
    module:模块
    power:系统的电源管理数据
    

    3.总线,设备,驱动

    一条总线下面会有很多的设备和相应的驱动,当有新设备加入时,总线负责为该设备查找(匹配)对应的驱动,如果找到了,就会有相应的驱动来驱动这个设备。
    在这里插入图片描述
    在/sys下面有一个bus子目录里面,所有支持的总线在该目录下有其子目录
    比如:pci,spi,i2c等
    在这里插入图片描述
    每种总线下面都有deivces和drivers两个子目录,里面是各种总线下的设备和驱动。当有新设备加入时,总线负责给他查找驱动。
    在这里插入图片描述

    4.如何在/sys/bus下面创建自己的总线,驱动和设备

    /sys下的目录是struct kobject,而总线,设备,驱动都是目录,所以从原始角度来说,就是要在/sys/bus创建新的目录和文件,总线,设备和驱动都是从kobject派生出来的。
    内核中用struct bus_type来表示总线
    struct device来表示设备
    struct device_driver来表示驱动

    创建虚拟总线

    #include<linux/init.h>
    //当总线上有新设备或驱动时,调用本函数来进行匹配,如果匹配成功,就返回1
    static int vbus_match(struct device *dev,struct device_driver *drv)
    {
    	return 1;
    }
    //内核中用bus_type的对象来代表一条总线
    static struct bus_type vbus ={
    	.name = "vbus",     //总线名字,显示在/sys/bus下面
    	.match=vbus_match,  //匹配函数,负责匹配驱动和设备
    }
    EXPORT_SYMBOL(vbus);//将该符号导出,其他的模块才能使用
    static int __init vbus_init(void)
    {
    	//注册vbus总线
    	return bus_register(&vbus);
    }
    static void __exit vbus_exit(void)
    {
    	//注销总线
    	bus_unregister(&vbus);
    }
    module_init(vbus_init);
    module_exit(vbus_exit);
    MODULE_LICENSE("GPL");
    

    创建驱动

    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/devices.h>
    //声明一下,这个模块要用到vbus,如果没有vbus就不能加载模块,这说明了一种依赖关系,vdrv依赖于vbus,必须保证系统中有vbus才能加载vdrv,因此要先加载总线。
    extern struct bus_type vbus;
    //内核中用device_driver来表示驱动,name是显示在/sys/bus/vbus/drivers/vdrv下面的
    static struct device_driver vdrv = {
     	.name = "vdrv",
     	.bus = &vbus,
    }
    static int __init vdrv_init(void)
    {
    	return driver_register(&vdrv);
    }
    static void __exit vdrv_exit(void)
    {
    	driver_unregister(&vdrv);
    }
    module_init(vdrv_init);
    module_exit(vdrv_exit);
    MODULE_LICENSE("GPL");
    

    创建虚拟设备

    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/devices.h>
    //声明一下,这个模块要用到vbus,
    extern struct bus_type vbus;
    //内核中用device来表示驱动
    static struct device vdev = {
     	.init_name = "vdev",
     	.bus = &vbus,
     	.release=vdev_release, //关闭设备
    };
    static int __init vdrv_init(void)
    {
    	return device_register(&vdev);
    }
    static void __exit vdev_exit(void)
    {
    	device_unregister(&vdev);
    }
    module_init(vdev_init);
    module_exit(vdev_exit);
    MODULE_LICENSE("GPL");
    

    我们先加载总线,才能加载总线上的驱动或设备,也就是说设备和驱动依赖于总线。
    make modules_install安装模块
    depmod更新模块的依赖信息
    安装以后就可以用modprobe来加载卸载了
    /lib/modules/版本号/modules.dep这个文件记录了系统中的模块以及他们之间的依赖关系。

    展开全文
  • 总线设备驱动

    2014-05-29 15:22:56
    设备模型之二 总线设备驱动   2012-04-19 一、概要分析  Linux设备模型中三个很重要的概念就是总线、设备和驱动,即bus,device和driver。它们分别对应的数据结构分别为struct bus_type,struct device和...

    设备模型之二 总线设备驱动                          

               2012-04-19

    一、概要分析
         Linux设备模型中三个很重要的概念就是总线、设备和驱动,即bus,device和driver。它们分别对应的数据结构分别为struct bus_type,struct device和struct device_driver。
        总线是处理器与一个或多个设备之间的通道,在设备模型中,所有的设备都通过总线相连。在最底层,Linux系统中的每一个设备都用device结构的一个实例来表示。而驱动则是使总线上的设备能够完成它应该完成的功能。

        在系统中有多种总线,如PCI总线、SCSI总线等。系统中的多个设备和驱动是通过总线让它们联系起来的。在bus_type中两个很重要的成员就是 struct kset drivers和struct kset devices【 在2.6.32.2中已被 struct bus_type_private 结构包含 】。它分别代表了连接在这个总线上的两个链,一个是设备链表,另一个则是设备驱动链表。也就是说,通过一个总线描述符,就可以找到挂载到这条总线上的设备,以及支持该总线的不同的设备驱动程序。

    1.1 bus_type 相当于一个容器,是device 和device_driver 的管理机构,它  

    包含了一个device 集合(kset)和一个device_driver 集合(kset),分别表 

    示挂在这个总线下的所有设备和所有设备驱动程序。

    1.2 device_driver 挂在某个bus_type 下面,包含了一个device 集合(kset),

    表示这个驱动程序操作(或控制)的所有设备。device_driver 还包含一个 

    bus_type 指针,表示驱动程序所在的总线。

    1.3 device 挂在某个bus_type 下面,包含了一个device_driver 指针,表示   

    这个设备对应的设备驱动程序。device 还包含一个bus_type 指针,表示 

    设备所在的总线。需要说明的是,一个实际的总线在设备驱动模型中是用两 

    个结构表示的:bus_type 和device。bus_type 代表总线类型,出现在

    /sys/bus/目录下;device 代表总线设备,出现在/sys/devices/录下,

    表明实际的总线本质上是一种设备。


    1.2 总线、设备与驱动的绑定
        在系统启动时,它会对每种类型的总线创建一个描述符,并将使用该总线的设备链接到该总线描述符的devices链上来。也即是说在系统初始化时,它会扫描连接了哪些设备,并且为每个设备建立一个struce device变量,然后将该变量链接到这个设备所连接的总线的描述符上去。另一方面,每当加载了一个设备驱动,则系统也会准备一个struct device_driver结构的变量,然后再将这个变量也链接到它所在总线的描述符的drivers链上去。       
        对于设备来说,在结构体struct device中有两个重要的成员,一个是struct bus_type *bus,另一个是struct device_driver *driver。bus成员就表示该设备是链接到哪一个总线上的,而driver成员就表示当前设备是由哪个驱动程序所驱动的。对于驱动程序来说,在结构体struct device_driver中也有两个成员,struct bus_type *bus和struct list_head devices,这里的bus成员也是指向这个驱动是链接到哪个总线上的,而devices这个链表则是表示当前这个驱动程序可以去进行驱动的那些设备。一个驱动程序可以支持一个或多个设备,而一个设备则只会绑定给一个驱动程序。
         对于device与device_driver之间建立联系的方式,主要有两种方式。第一种,在计算机启动的时候,总线开始扫描连接在其上的设备,为每个设备建立一个struct device变量并链接到该总线的devices链上,然后开始初始化不同的驱动程序,驱动程序到它所在的总线的devices链上去遍历每一个还没有被绑定给某个驱动的设备,然后再查看是否能够支持这种设备,如果它能够支持这种设备,则将这个设备与这个驱动联系起来。即,将这个设备的device变量加到驱动的devices链上,同时让struct device中的device_driver指向当前这个驱动。第二种则是热插拔。也即是在系统运行时插入了设备,此时内核会去查找在该bus链上注册了的device_driver,然后再将设备与驱动联系起来。

    1.3 Question:

    a)设备与驱动根据什么规则联系起来?

    b)驱动程序/设备如何找到总线设备的?

    以后内容采用 2.6.32.2 内核,有一些跟以前不一样。以后采用使用方法形式来说明:(例子在device_module文件夹中)总线设备驱动操作方法非常的类似,我主要以bus进行说明而已。设备和驱动主要按照bus方法进行操作即可。

    二、总线bus

    第一步:定义数据结构

    【NOTE】很少 bus_type 成员要求初始化; 大部分由设备模型核心处理. 但是, 我们确实不得不指定总线的名子, 以及任何伴随它的方法。

    头文件:

    #include <linux/device.h>

    struct bus_type {

      const char*name;            /*总线名称*/

      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 (*uevent)(struct device *dev, struct kobj_uevent_env *env);

      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);

      const struct dev_pm_ops *pm;

      struct bus_type_private *p;            /*总线类型的私有数据*/         

    };

    struct bus_type_private {

      struct kset subsys;                  /*与该总线相关的子系统*/

      struct kset *drivers_kset;           /*总线驱动程序的KSET*/

      struct kset *devices_kset;           /*挂载在总线上的设备KSET*/

      struct klist klist_devices;          /*挂载在总线上的设备链表*/   

      struct klist klist_drivers;           /*驱动程序链表*/

      struct blocking_notifier_head bus_notifier;

      unsigned int drivers_autoprobe:1;

      struct bus_type *bus;

    };

    Q1:后来注册的设备\驱动如何添加到 struct kset *devices_kset 、struct kset *drivers_kset?

    Q2:后来注册的设备\驱动如何寻找到总线?

     

    第二步:实现总线方法

       int (*match)(struct device *device, struct device_driver *driver);  

       这个方法被调用, 大概多次, 无论何时一个新设备或者驱动被添加给这个总线. 它应当返回一个非零值如果给定的设备可被给定的驱动处理. (我们马上进入设备和 device_driver 结构的细节). 这个函数必须在总线级别处理, 因为那是合适的逻辑存在的地方; 核心内核不能知道如何匹配每个可能总线类型的设备和驱动. 

    int (*uevent) (struct device *device, char **envp, int num_env p, char *buffer, int buffer_size);  

    这个模块允许总线添加变量到环境中, 在产生一个热插拔事件在用户空间之前。

    第三步:注册总线

    int bus_register(struct bus_type *bus); 

    注册总线一定要检查其返回值,可能会注册失败。

    /*退出时注销总线*/

    void bus_unregister(struct bus_type *bus);  

    第四步:创建总线属性文件==>用于与空间进行交互

    Q:如何将传送进去的 buf 跟内核交互==>读出的buf 哪里来,写入的 buf 要到哪里去?

    struct bus_attribute {

      struct attribute attr;

      ssize_t (*show)(struct bus_type *bus, char *buf);

      ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);

    };

    #define BUS_ATTR(_name, _mode, _show, _store) \

      struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)

     

      int bus_create_file(struct bus_type *bus, struct bus_attribute *attr);

     /*删除属性文件*/

      void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr);  

     

    三、设备device

    #include <linux/device.h>

    struct device {

      struct device*parent;       /*父设备*/

      struct device_private *p;       /*设备结构的私有数据*/

      struct kobject kobj;              /*kobject对象*/

      const char*init_name;     /*设备初始化名字替换了 bus_id */

      struct device_type *type;   /*设备方法==>类似于 kobject_ktype*/ 

      struct semaphore sem;       /*信号量*/

      struct bus_type*bus;  /*设备所在的总线*/

      struct device_driver *driver;/*该设备的驱动,怎样跟驱动匹配呢?*/

      void *platform_data;       /*平台总线私有数据*/

      struct dev_pm_info power;

    #ifdef CONFIG_NUMA

       int numa_node; /* NUMA node this device is close to */

    #endif

       u64 *dma_mask; /* dma mask (if dma'able device) */

       u64 coherent_dma_mask;

       struct device_dma_parameters *dma_parms;

       struct list_head dma_pools; /* dma pools (if dma'ble) */

       struct dma_coherent_mem *dma_mem; 

       struct dev_archdata archdata;

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

       spinlock_t devres_lock;

       struct list_head devres_head;

       struct klist_node knode_class;

       struct class *class;

       const struct attribute_group **groups;

       void(*release)(struct device *dev); /*为何必须有呢?没有行吗*/

    };

    struct device_private {

       struct klist klist_children;

       struct klist_node knode_parent;

       struct klist_node knode_driver;

       struct klist_node knode_bus;

       void *driver_data;                   /*我们所关心的数据*/

       struct device *device;

    };

    Q1:利用结构中的kobject 跟 kset 进行关联。

    Q2:在进行设备注册时,就将设备添加到总线中去,利用bus_add_device(dev) 实现的。

    大家可以去 drivers/base/core.c 看源代码
    int device_register(struct device *dev)
    {
        device_initialize(dev);               //初始化设备
        return device_add(dev);              //添加设备
    }

    void device_initialize(struct device *dev)
    {

        /*

         *设置设备的kobject所属集合,利用了kobject 挂载到devices_kset其  

         *实在第一层,sys/devices/... 而在sys/bus/xxx 目录下是个链接文件
         */
        dev->kobj.kset = devices_kset;             

    kobject_init(&dev->kobj, &device_ktype);    //初始化设备的kobject 

    INIT_LIST_HEAD(&dev->dma_pools);//初始化设备的DMA池,用于传大数
        mutex_init(&dev->mutex);                 //初始化互斥锁
        lockdep_set_novalidate_class(&dev->mutex);
        spin_lock_init(&dev->devres_lock);     //初始化自旋锁,用于同步子设备链表
        INIT_LIST_HEAD(&dev->devres_head);      //初始化子设备链表头
        device_pm_init(dev);
        set_dev_node(dev, -1);
    }

    int device_add(struct device *dev)
    {
           ...             
         error = device_private_init(dev);       //初始化设备的私有成员
          ...
         parent = get_device(dev->parent);         //增加父设备kobject的引用
         setup_parent(dev, parent);             //设置该设备kobject父对象
          ...
         error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //将设备kobject添加进父对象设备模型

          ... 
         error = bus_add_device(dev);          //将设备添加进总线中

    ...
          bus_probe_device(dev);            //现在该为设备在总线上寻找合适的驱动了
        ...
    }
        到了这里就将上面的几个问题给解决了,这对于驱动也是类似的在这里就总结一下一个设备添加和删除过程:当在总线上添加(或删除)设备时,会依次遍历总线上的所有驱动程序,调用总线定义的match()方法检查要加入(或删除)的设备是否和驱动程序“匹配”,如果匹配成功,则对设备调用总线或驱动程序中定义的probe(或remove)方法。添加设备时产生KOBJ_ADD uevent,删除设备时产生KOBJ_REMOVE uevent。

    设备添加流程:

    device_register(dev)->device_add(dev)-> kobject_uevent(KOBJ_ADD)

    device_add(dev)->bus_attach_device(dev)->device_attach(dev)

    ->__device_attach(drv,dev)->bus_type():match(dev,drv)

    then ->driver_probe_device()->really_probe()

    ->bus_type:probe()或device_driver:probe()

    设备删除

    device_unregister(dev)->device_del(dev)->bus_remove_device(dev)

    ->device_release_driver(dev) ->__ device_release_driver(dev)

    ->bus_type:remove()或device_driver:remove()

    device_del(dev)->kobject_uevent(KOBJ_REMOVE) 

     四、驱动driver

     (1)添加驱动程序
     driver_register(drv)-> bus_add_driver (drv)-> driver_attach(drv)
     ->__driver_attach(dev,drv) ->bus_type():match(dev,drv) then
    ->driver_probe_device()->really_probe()->bus_type:probe() device_driver:probe()

     driver_register(drv)-> kobject_uevent(KOBJ_ADD)
     (2) 驱动程序删除
      driver_unregister(dev)->bus_remove_driver(drv)-> driver_detach(drv)
     ->__ device_release_driver(dev) [dev-drv 管理的所有设备]
     ->bus_type:remove() 或device_driver:remove()
     

    五、内嵌的设备和驱动 【linux设备驱动程序第三版】
         设备结构包含设备模型核心需要的来模型化系统的信息. 大部分子系统, 但是, 跟踪关于它们驻留的设备的额外信息. 结果, 对设备很少由空设备结构所代表; 相反, 这个结构, 如同 kobject 结构, 常常是嵌入一个更高级的设备表示中. 如果你查看 struct pci_dev  的定义或者 struct usb_device 的定义, 你会发现一个 struct device 埋在其中. 常常地, 低层驱动甚至不知道 struct device, 但是有例外. lddbus 驱动创建它自己的设备类型( struct ldd_device ) 并且期望单独的设备驱动来注册它们的设备使用这个类型. 它是一个简单结构: 

    struct ldd_device { 

     char *name; 

     struct ldd_driver *driver; 

     struct device dev;  

    };  

    #define to_ldd_device(dev) container_of(dev, struct ldd_device, dev);  

    这个结构允许驱动提供一个实际的名子给设备( 这可以清楚地不同于它的总线 ID, 存储于设备结构) 以及一个这些驱动信息的指针. 给真实设备的结构常常还包含关于供应者信息, 设备型号, 设备配置, 使用的资源, 等等. 可以在 struct pci_dev (<linux/pci.h>) 或者 struct usb_device (<linux/usb.h>) 中找到好的例子. 一个方便的宏( to_ldd_device ) 也为 struct ldd_device 定义, 使得容易转换指向被嵌入的结构的指针为 ldd_device 指针. 

    lddbus 输出的注册接口看来如此: 

    int register_ldd_device(struct ldd_device *ldddev)  

     ldddev->dev.bus = &ldd_bus_type; 

     ldddev->dev.parent = &ldd_bus; 

     ldddev->dev.release = ldd_dev_release; 

     strncpy(ldddev->dev.bus_id, ldddev->name, BUS_ID_SIZE); 

     return device_register(&ldddev->dev);  

    EXPORT_SYMBOL(register_ldd_device); 

    这里, 我们简单地填充一些嵌入的设备结构成员( 单个驱动不应当需要知道这个 ), 并且注册这个设备到驱动核心. 如果我们想添加总线特定的属性到设备, 我们可在这里做。如同大部分驱动核心结构的情形, device_driver 结构常常被发现嵌到一个更高级的, 总线特定的结构. lddbus 子系统不会和这样的趋势相反, 因此它已定义了它自己的 ldd_driver 结构: 

    struct ldd_driver { 

     char *version; 

     struct module *module; 

     struct device_driver driver; 

     struct driver_attribute version_attr;  

    };  

    #define to_ldd_driver(drv) container_of(drv, struct ldd_driver, driver);  

    这里, 我们要求每个驱动提供特定当前软件版本, 并且 lddbus 输出这个版本字串为它知道的每个驱动. 总线特定的驱动注册函数是: 

    int register_ldd_driver(struct ldd_driver *driver) 

    {  

     int ret; 

     driver->driver.bus = &ldd_bus_type; 

     ret = driver_register(&driver->driver); 

     if (ret) 

     return ret; 

     driver->version_attr.attr.name = "version"; 

     driver->version_attr.attr.owner = driver->module; 

     driver->version_attr.attr.mode = S_IRUGO; 

     driver->version_attr.show = show_version; 

     driver->version_attr.store = NULL; 

     return driver_create_file(&driver->driver, &driver->version_attr); 

    这个函数的第一部分只注册低级的 device_driver 结构到核心; 剩下的建立版本属性. 因为这个属性在运行时被创建, 我们不能使用 DRIVER_ATTR 宏; 反之,  driver_attribute 结构必须手工填充. 注意我们设定属性的拥有者为驱动模块, 不是 lddbus 模块; 这样做的理由是可以在为这个属性的 show 函数的实现中见到: 

    static ssize_t show_version(struct device_driver *driver, char *buf) 

     struct ldd_driver *ldriver = to_ldd_driver(driver); 

     sprintf(buf, "%s\n", ldriver->version); 

     return strlen(buf); 

    有些来源于各位大侠博客:

    http://hi.baidu.com/%EC%C5%B6%AF%B0%AE%C9%F1/blog/item/173b12648e84adcd8db10d2a.html

    http://www.2cto.com/os/201108/100392.html

    展开全文
  • 网卡 串口驱动 pci总线设备驱动 驱动研究 及vxworks的启动过程
  • 总线设备驱动模型其实现主要是基于Kobject和sysfs等机制,对于驱动模型程序开发主要是理解三个元素:总线、设备、驱动的关系。三者之间因为一定的联系性实现对设备的控制。
  • 总线设备驱动模型

    2017-07-26 13:28:52
    总线设备驱动模型

    总线模型

    随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求也越来越高,2.4内核已经难以满足这些需求。为适应这种形势的需要,从Linux 2.6内核开始提供了全新的设备模型。

    总线设备驱动模型包括 总线设备驱动 三个组成部分。

    总线

    描述结构体:
    在 Linux 内核中, 总线由 bus_type 结构表示,定义在 同文件

    struct bus_type {
        const char *name; /*总线名称*/
        int (*match) (struct device *dev, struct device_driver *drv); /*驱动与设备的匹配函数*/
        //………
    };

    匹配函数:

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

    当一个新设备或者新驱动被添加到这个总线时,该函数被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零

    总线注册与注销:
    总线的 注册 使用如下函数:

    bus_register(struct bus_type *bus)

    若成功,新的总线将被添加进系统,并可在 * /sys/bus/ * 下看到相应的目录。

    总线的 注销 使用:

    void bus_unregister(struct bus_type *bus)

    驱动

    在 Linux内核中, 驱动由 device_driver 结构 表示:

    struct device_driver {
    {
        const char *name; /*驱动名称*/
        struct bus_type *bus; /*驱动程序所在的总线*/
        int (*probe) (struct device *dev);
        //………
    }

    驱动的注册使用如下函数:

    int driver_register(struct device_driver *drv)

    驱动的注销使用:

    void driver_unregister(struct device_driver *drv)

    设备

    在 Linux内核中, 设备由struct device 结构 表示。

    struct device {
    {
        const char *init_name; /*设备的名字*/
        struct bus_type *bus; /*设备所在的总线*/
        //………
    }

    设备的 注册 使用如下函数:

    int device_register(struct device *dev)

    设备的 注销 使用:

    void device_unregister(struct device *dev)

    代码举例:

    总线:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/device.h>//需要包含该头文件
    
    MODULE_LICENSE("GPL");//需要声明遵循GPL协议
    
    int my_match(struct device *dev, struct device_driver *drv)
    //设备与驱动的匹配函数,设备插入时,总线将挂载的设备与每一个驱动分别匹配
    {
        return !strncmp(dev->kobj.name,drv->name,strlen(drv->name));
        //注意:dev的名字在 kobj.name 成员中
        //判断设备的名字与驱动的名字是否相同
        //该函数用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零。    
    }  
    
    struct bus_type my_bus_type = { //定义总线结构体
        .name = "my_bus",
        .match = my_match,
    };
    
    EXPORT_SYMBOL(my_bus_type);//要输出该变量,其他文件需要使用
    
    int my_bus_init()//入口函数
    {
        int ret;    
        ret = bus_register(&my_bus_type); //注册总线设备
        return ret;
    }
    
    void my_bus_exit()//出口函数
    {
        bus_unregister(&my_bus_type);//注销总线设备
    }
    
    module_init(my_bus_init);
    module_exit(my_bus_exit);
    
    //在 /sys/bus/ 文件夹下可以看到添加的总线结构
    //在该文件夹下对应的总线结构文件夹下,是该总线上加载的设备和相关驱动

    驱动:

    #include <linux/device.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    
    extern struct bus_type my_bus_type;//总线结构,注意加 extern
    
    int my_probe(struct device *dev)
    {
        printk("driver found the device it can handle!\n");
        return 0;
    }
    
    struct device_driver my_driver = {   //驱动结构体
        .name = "my_dev",    //驱动的名字和设备的名字需要相同
        .bus = &my_bus_type,    
        .probe = my_probe,
    };
    
    int my_driver_init()//入口
    {
        int ret;
        ret = driver_register(&my_driver);//注册
        return ret;
    }
    
    void my_driver_exit()//出口
    {
        driver_unregister(&my_driver);//注销
    }
    
    module_init(my_driver_init);
    module_exit(my_driver_exit);
    

    设备:

    #include <linux/device.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    
    extern struct bus_type my_bus_type;//总线结构,注意加 extern
    
    struct device my_dev = {  //设备结构体
         .init_name = "my_dev",
         .bus = &my_bus_type,   
    };
    
    int my_device_init()//入口
    {
        int ret;
         ret = device_register(&my_dev);//注册设备
         return ret;
    }
    
    void my_device_exit()
    {
        device_unregister(&my_dev);//主销设备
    }
    
    module_init(my_device_init);
    module_exit(my_device_exit);
    

    注意:在使用insmod命令加载了总线程序之后,驱动和设备的程序加载无论先后都可以正常工作。

    展开全文
  • 关于总线设备驱动模型的理论知识我们在上一篇笔记【Linux笔记】总线设备驱动模型中也有简单地学习过了。这篇笔记我们来分析、学习程序。下面分析主要基于上面的框图4。 应用程序ledtest.c: int main(int argc, char...
  • vxworks下PCI总线设备驱动程序设计.PDF
  • 一、总线设备驱动模型二、总线1、总线描述在 Linux 内核中, 总线由 bus_type 结构表示,定义在 &lt;linux/device.h&gt;struct bus_type {const char *name; /*总线名称*/int (*match) (struct device *dev, ...

    一、总线设备驱动模型

    二、总线

    1、总线描述

    在 Linux 内核中, 总线由 bus_type 结构表示,
    定义在 <linux/device.h>
    struct bus_type {
    const char *name; /*总线名称*/
    int (*match) (struct device *dev, structdevice_driver *drv); /*驱动与设备的匹配函数*/
    ………
    }

    int (*match)(struct device * dev, struct device_driver * drv)
    当一个新设备或者新驱动被添加到这个总线时,该函数被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零。
    2、总线注册与注销
    总线的注册:
    bus_register(struct bus_type *bus)
    若成功,新的总线将被添加进系统,并可在/sys/bus 下看到相应的目录。
    总线的注销:
    bus_unregister(struct bus_type *bus)
    三、驱动

    1、驱动描述

    在 Linux内核中, 驱动由 device_driver结构表示。
    struct device_driver {
    {
    const char *name; /*驱动名称*/
    struct bus_type *bus; /*驱动程序所在的总线*/
    int (*probe) (struct device *dev); /*匹配成功之后需要执行的操作*/
    ………
    }

    2、驱动注册与注销

    驱动注册:
    int driver_register(struct device_driver *drv)
    驱动注销:
    void driver_unregister(struct device_driver *drv)
    三、设备

    1、设备描述

    在 Linux内核中, 设备由device结构表示。
    struct device {
    {
    const char *init_name; /*设备的名字*/
    struct bus_type *bus; /*设备所在的总线*/
    ………
    }
    2、设备注册与注销
    设备注册:
    int device_register(struct device *dev)
    设备注销:
    void device_unregister(struct device *dev)

    四、代码 下载点击打开链接

    bus.c

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/device.h>
    
    int my_match(struct device *dev, struct device_driver *drv)
    {
        return !strncmp(dev->kobj.name,drv->name,strlen(drv->name));
    }  
    
    struct bus_type my_bus_type = {
        .name = "my_bus",
        .match = my_match,
    };
    	
    EXPORT_SYMBOL(my_bus_type);
    
    int my_bus_init()
    {
        int ret;
        ret = bus_register(&my_bus_type);
        return ret;
    }
    
    void my_bus_exit()
    {
        bus_unregister(&my_bus_type);
    }
    
    module_init(my_bus_init);
    module_exit(my_bus_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Jerry.Gou");
    MODULE_DESCRIPTION("TQ210 bus driver");

    device.c

    #include <linux/device.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    
    extern struct bus_type my_bus_type;
    
    struct device my_dev = {
         .init_name = "my_dev",
         .bus = &my_bus_type,	
    };
    
    int my_device_init()
    {
         int ret;
         ret = device_register(&my_dev);
         return ret;
    }
    
    void my_device_exit()
    {
        device_unregister(&my_dev);
    }
    
    module_init(my_device_init);
    module_exit(my_device_exit);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Jerry.Gou");
    MODULE_DESCRIPTION("TQ210 device driver");
    driver.c
    #include <linux/device.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    
    extern struct bus_type my_bus_type;
    
    int my_probe(struct device *dev)
    {
        printk("driver found the device it can handle!\n");
        return 0;
    }
    
    struct device_driver my_driver = {
        .name = "my_dev",
        .bus = &my_bus_type,	
        .probe = my_probe,
    };
    
    int my_driver_init()
    {
        int ret;
        ret = driver_register(&my_driver);
        return ret;
    }
    
    void my_driver_exit()
    {
        driver_unregister(&my_driver);	
    }
    
    module_init(my_driver_init);
    module_exit(my_driver_exit);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Jerry.Gou");
    MODULE_DESCRIPTION("TQ210 driver driver");

    五、查看已注册的设备、驱动



    展开全文
  • 本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程。 目录: 一、总线设备驱动模型总体介绍及其实现方式 ...
  • Linux下总线设备驱动的实例,实现了通过总线接口的简单通信协议
  • 嵌入式uClinux下CAN总线设备驱动程序设计,王月庆,郭卫栋,本文介绍了嵌入式uClinux下设备驱动程序的结构,描述了CAN总线设备驱动程序的软件构架以及将CAN设备驱动程序加入到uClinux系统内核的过�
  • 文章目录1 驱动编写的3种方法1.1 传统写法1.2 总线设备驱动模型1.3 设备树2 在 Linux 中实现“分离”:Bus/Dev/Drv 模型2.1 模型2.2 driver和device的匹配规则2.3 函数调用关系2.4 常用函数2.5 如何写程序 ...
  • 总线设备驱动模型国嵌示例代码及pdf,学习总线设备驱动的比较好的例子。简单容易理解,偏入门
  • 讨论了在内核态下PCI总线设备驱动程序的编程方法,并利用通用设备驱动程序Win- Driver实现了对PCI总线控制器PCIgo52的访问和控制;给出了PCI设备安装程序的编程方法;提出了开发PCI总线驱动程序的三级编程结构。
  • Linux平台总线设备驱动模型 1. 传统Linux驱动模型 与 平台总线设备驱动模型    传统的Linux驱动模型将对于设备的一切操作都放在了一个文件当中, 这个文件既包含了硬件相关的设备信息(例如引脚信息), 也包含了对...
  • 一、总线设备驱动模型 随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求也越来越高,2.4内核已经难以满足这些需求。为适应这种形势的需要,从Linux 2.6内核开始提供了全新的设备模型...
  • 参考国嵌教程以及网络资料学习。 ... 一、总线设备驱动模型 总线是处理器和设备之间的通道,在设备模型中,所有的设备都通过总线相连,甚至是内部的虚拟“p...
  • 总线设备驱动框架

    2012-11-15 03:36:00
    总线设备驱动框架是一种类似于输入子系统的框架。 总线设备驱动,顾名思义,共有三个模块,负责硬件资源的设备(device),负责处理硬件事务并且连接其他功能模块的驱动(driver),还有就是连接这两者的总线(bus...
  • Linux总线设备驱动模型 总线设计 总线描述 总线是处理器和设备之间的通道,在设备模型中,所有的设备读通过总线相连,甚至是内部的虚拟“platform”总线。在Linux设备模型中,总线由bus_type结构表示,定义在 ...
  • 一份很好的介绍PCIE总线设备驱动的资料
  • 总线设备驱动模型就是这样一个思想。我们基于总线设备驱动模型,实现树莓派的点灯程序。 总线设备驱动模型: 在Linux2.6以后的设备驱动模型中,需关心总线、设备和驱动三个实体,总线将设备和驱动绑定。在系统每...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,329
精华内容 3,331
关键字:

总线设备驱动