注册

Linux设备驱动模型

目录

linux环境变量,设备驱动模型1.Linux设备驱动模型的来历

首先回顾设备驱动编撰的通常流程

【1】实现入口函数module_init()和模块卸载函数module_exit();

【2】申请设备号,register_chrdev();----->(与内核相关)

【3】利用udev/mdev机制创建设备文件结点class_create(),device_create();------>(与内核相关)

【4】硬件初始化:1.io资源映射ioremap(),内核提供gpio库函数;2.注册中断。------->(与硬件相关)

【5】构建file_operation结构体-------->(与内核相关)

【6】实现操作硬件的方式xxx_open(),xxx_write()…

linux驱动编程_编程驱动聚水潭_编程驱动光谱仪

推论:整个流程不仅第四部份与硬件有关,其他都是相像的操作方式,为了便捷的(不重复造轮子)编撰设备驱动,节约人力,所以提出了设备驱动模型,简化了设备驱动编撰的流程。

2.设备驱动模型框架

可以通过sysfs虚拟文件系统查看总线对象(以usb为例)

linux驱动编程,BUS总线模型编程

概念图

1.总线对象

【1】structbus_type:总线对象linux培训机构,描述一个总线,管理device和driverlinux驱动编程,完匹配。

 struct bus_type {//只列举重要成员
 const char  *name; //总线名字
 int (*match)(struct device *dev, struct device_driver *drv);//匹配方法
};

【2】注册和注销总线

int bus_register(struct bus_type *bus);
void bus_unregister(struct bus_type *bus);

【3】构建一个总线

 #include 
#include 
#include 
//实例化一个bus对象
struct bus_type mybus = {
 .name = "mybus",
 .match = mybus_match,
};
EXPORT_SYMBOL(mybus); //导出总线对象,让device对象和driver对象使用
 
static int __init mybus_init(void)
{
 printk("------%s---------n",__FUNCTION__);
 int ret;
 
 //构建一个总线结果:/sys/bus/mybus
 ret = bus_register(&mybus);
 if(ret != 0)
 {
  printk("bus_register errorn");
  return ret;
 }
 return 0;
}
static void __exit mybus_exit(void)
{
 printk("------%s---------n",__FUNCTION__);
 bus_unregister(&mybus);
}
module_init(mybus_init);
module_exit(mybus_exit);
MODULE_LICENSE("GPL");

2.device对象

【1】device对象:设备对象,描述设备信息,包括地址,中断等其他数据

struct device {//只列举重要成员
 struct kobject kobj; //所有对象的父类
 const char *init_name;//在/sys/bus/mybus/device的名字,用于在总线中匹配
 struct bus_type *bus;   //指向该device对象依附的总线对象
 void *platform_data;  //自定义的数据,指向任何类型的数据
};

【2】注册和注销总线

int device_register(struct device *dev);
void device_unregister(struct device *dev);

【3】编写设备对象

定义一个描述设备的信息的结构体,匹配成功以后让driver对象在总线中领到device对象的信息,实现分离。

#include 
#include 
#include 
extern struct bus_type mybus;
struct mydev_desc{
 char* name;
 int irqno;
 unsigned long addr;
};
struct mydev_desc deviofo = {
 .name = "hqs",
 .irqno = 8877,
 .addr = 0x12345678,
};
void mydev_release(struct device* dev)
{
 printk("------%s---------n",__FUNCTION__);
}
//构建一个device对象
struct device mydev = {
 .init_name = "fsdev_drv",
 .bus = &mybus,
 .release = mydev_release,
 .platform_data = &deviofo,
};
static int __init mydev_init(void)
{
 printk("------%s---------n",__FUNCTION__);
 int ret;
 //将device注册到总线中
 ret = device_register(&mydev);
 if(ret < 0)
 {
  printk("device_register errorn");
  return ret;
 }
 return 0;
}
static void __exit mydev_exit(void)
{
 printk("------%s---------n",__FUNCTION__);
 device_unregister(&mydev);
}
module_init(mydev_init);
module_exit(mydev_exit);
MODULE_LICENSE("GPL");

3.driver对象

【1】driver对象:描述设备驱动发的方式

struct device_driver {//只列举重要成员
 const char  *name;//在/sys/bus/mybus/driver的名字,用于在总线中匹配
 struct bus_type  *bus;//指向该device对象依附的总线对象
 int (*probe) (struct device *dev); //device和driver匹配之后要做的事情
 int (*remove) (struct device *dev); //device和driver分离之后要做的事情
};

【2】注册和注销总线

int driver_register(struct device_driver *drv);
void driver_unregister(struct device_driver *drv);

【3】编写driver对象

匹配成功以后可以在总线中领到device对象的数据,具体实现在probe函数里。

#include 
#include 
#include 
#include 
extern struct bus_type mybus;
struct mydev_desc{
 char* name;
 int irqno;
 unsigned long addr;
};
struct mydev_desc* pdesc;
int mydrv_probe(struct device *dev)
{
 printk("------%s---------n",__FUNCTION__);
 pdesc = (struct mydev_desc*)dev->platform_data;
 printk("name =%sn",pdesc->name);
 printk("irqno = %dn",pdesc->irqno);
 unsigned long * paddr = ioremap(pdesc->addr, 8);
 return 0;
}
int mydrv_remove (struct device *dev)
{
 printk("------%s---------n",__FUNCTION__);
 return 0;
}
//构建一个driver对象
struct device_driver mydrv = {
 .name = "fsdev_drv",
 .bus = &mybus,
 .probe = mydrv_probe,
 .remove = mydrv_remove,
};
static int __init mydrv_init(void)
{
 printk("------%s---------n",__FUNCTION__);
 int ret;
 //将device注册到总线中
 ret = driver_register(&mydrv);
 if(ret < 0)
 {
  printk("driver_register errorn");
  return ret;
 }
 return 0;
}
static void __exit mydrv_exit(void)
{
 printk("------%s---------n",__FUNCTION__);
 driver_unregister(&mydrv); 
}
module_init(mydrv_init);
module_exit(mydrv_exit);
MODULE_LICENSE("GPL");

4.device对象和driver对象匹配

【1】实现BUS对象中的match方式(按device对象的名子和driver对象中的名子相匹配)

要注意的是不能直接用device对象中的init_name,而要用device对象中继承的structkobjectkobj;上面的成员name不然会报错

int mybus_match(struct device *dev, struct device_driver *drv)
{
 //如果匹配成功,match方法一定要返回一个1,失败返回0
 if(! strncmp(drv->name,dev->kobj.name,strlen(drv->name)))
 {
  printk("match okn");
  return 1;
 }
 else
 { 
  printk("match failedn");
  return 0;  
 }
 return 0;
}
//实例化一个bus对象
struct bus_type mybus = {
 .name = "mybus",
 .match = mybus_match,
};

【2】保证device对象和driver对象的名子一样:例如这儿都使用"fsdev_drv"才能保证能匹配成功

//构建一个device对象
struct device mydev = {
 .init_name = "fsdev_drv",
 .bus = &mybus,
 .release = mydev_release,
 .platform_data = &deviofo,
};

//构建一个driver对象
struct device_driver mydrv = {
 .name = "fsdev_drv",
 .bus = &mybus,
 .probe = mydrv_probe,
 .remove = mydrv_remove,
};

以上就是Linux设备驱动模型的详细内容,更多请关注CTO智库其它相关文章!