1.字符设备驱动
\qquad字符设备驱动是最基本,最常用的设备。它将千差万别的硬件设备采用统一的接口封装起来,屏蔽了硬件的差异,简化了应用层的操作。
2.描述所有字符设备的结构体
\qquad描述所有字符设备的结构体在linux内核目录下的\include\linux\cdev.h
中,结构体为:
struct cdev {struct kobject kobj;struct module *owner;const struct file_operations *ops;struct list_head list;dev_t dev; //设备号unsigned int count; //设备个数
};
\qquadcdev结构体中的struct file_operations
位于linux内核目录下的\include\linux\fs.h
中,除了第一个结构体变量是结构体指针,其它的都是函数指针。我们称struct file_operations
为提供给应用层的操作方法集。
\qquaddev_t
用于唯一的标识设备的号码,也是内核设备管理驱动设备的唯一标识符。其一系列定义如下,所以dev_t
是32位无符号整型。设备号:主设备号+次设备号
typedef __kernel_dev_t dev_t;
typedef __u32 __kernel_dev_t;
typedef unsigned int __u32;
MAJOR(dev_t dev) //从设备号中提取主设备号
MINOR(dev_t dev) //从设备号中提取次设备号
MKDEV(int ma,int mi) //主次设备号合成设备号
3.编写字符设备驱动
3.1为cdev结构体分配空间
\qquadcdev结构体分配内存空间,内核内存空间分配函数cdev_alloc()
\qquad功能:为cdev结构体分配空间
\qquad参数:void
\qquad返回值:成功就返回分配到的结构体地址;失败就返回NULL
struct cdev *cdev_alloc(void)
{struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);if (p) {INIT_LIST_HEAD(&p->list);kobject_init(&p->kobj, &ktype_cdev_dynamic);}return p;
}
3.2初始化cdev结构体
\qquadcdev结构体初始化,初始化函数cdev_init()
\qquad功能:初始化cdev设备
\qquad参数:第一个参数:cdev结构体指针;第二个参数:操作方法集的指针
\qquad返回值:void
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{memset(cdev, 0, sizeof *cdev);INIT_LIST_HEAD(&cdev->list);kobject_init(&cdev->kobj, &ktype_cdev_default);cdev->ops = fops;
}
3.3添加(注册)字符设备到内核中,由内核统一管理
\qquad函数:int cdev_add(struct cdev *p, dev_t dev, unsigned count)
\qquad功能:添加字符设备到内核
\qquad参数:第一个参数:结构体指针;第二个参数:设备号;第三个参数:设备个数
\qquad返回值:成功返回0;失败返回错误码
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{int error;p->dev = dev;p->count = count;error = kobj_map(cdev_map, dev, count, NULL,exact_match, exact_lock, p);if (error)return error;kobject_get(p->kobj.parent);return 0;
}
3.4删除(注销)字符设备
\qquad函数:void cdev_del(struct cdev *p)
\qquad功能:删除(注销)字符设备