【学习笔记】设备,驱动,总线

时间:2021-04-23 15:08:17

设备/驱动

结构体 struct device ; 头文件位于linux/include/linux/device.h
用于描述设备相关的信息设备之间的层次关系,以及设备与总线、驱动的关系。

这篇讲如何创建设备
http://blog.csdn.net/paul_liao/article/details/6848536
结构体
http://blog.csdn.net/abo8888882006/article/details/5424363

device_register(&tdev);
device_unregister(&tdev);

总线

学过了设备驱动后,就开始看总线。之所以电脑可以识别插入的设备,就是靠总线分离和配对设备及驱动。

这篇文章已经讲解了相关的代码。
http://blog.csdn.net/wh_19910525/article/details/7398051

当设备插入时,总线会调用probe函数,读其结构体,了解 到底是什么设备什么匹配规则,然后初始化调用相对应的驱动。
设备和驱动的拔出则使用remove函数释放。
如果设备注册时没有归类(class)和加入总线(bus),不出错但也没意义。而驱动在没有总线的情况下不能注册入内核。
bus_register(&bus_type)
bus_unregister(&bus_type)

子系统class

 一个类是一个设备的高层视图,它抽象掉了底层的实现细节。它帮助设备归类,mdev自动生成设备文件于/dev。

 struct class {
const char *name; //类名称
struct module *owner; //对应模块
struct subsystem subsys; //对应的subsystem;
struct list_head children; //class_device链表
struct list_head interfaces; //class_interface链表
struct semaphore sem; //用于同步的信号锁
struct class_attribute *class_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); //释放类
}

一样有注册注销:
class_register(&cls);
class_unregister(&cls);

struct class_device
{
struct list_head node;

struct kobject kobj; //内嵌的kobject,用于计数

struct class *class; //所属的类;

dev_t devt; //dev_t设备号

struct class_device_attribute *devt_attr;

struct class_device_attribute uevent_attr;

struct device *dev; //如果存在则创建到/sys/devices相应入口的符号链接

void *class_data; //私有数据

struct class_device *parent; //父设备

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_IO_SIZE]; //类标志
}

调用函数:注册注销

int class_device_register(struct class_device *class_dev);
void class_device_unregister(struct class_device *class_dev);

不易分类的可以分到杂设备:miscdevice


一个独立的挂接在总线上的设备单元,一般都需要一段线性的地址空间来描述设备自身。
通过struct resource资源结构体来了解:

/include/linux/ioport.h

struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};

struct resource_list {
struct resource_list *next;
struct resource *res;
struct pci_dev *dev;
};
resource->start描述设备实体在cpu总线上的线性起始物理地址;
resource->end -描述设备实体在cpu总线上的线性结尾物理地址;
resource->name 描述这个设备实体的名称,这个名字开发人员可以随意起,但最好贴切;
resource->flag 描述这个设备实体的一些共性和特性的标志位;

没有对应的结构体需要自己封装。

struct my_device
struct device
....