一、设备的分类
1、设备可以分为:字符设备、块设备、网络设备。
字符设备:以字节流的形式进行数据读写。
块设备:存储设备。
网络设备:网卡。
2、描述字符设备的结构体cdev
<linux/cdev.h>
struct cdev {
struct module *owner; //THIS_MODULE
struct file_operations *ops; //操作方法集
dev_t dev; //设备号
unsigned int count; //设备计数
};
3、操作方法集
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
/* read 接口 */
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
/* write 接口 */
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
/* poll接口 */
unsigned int (*poll) (struct file *, struct poll_table_struct *);
/* ioctl接口 */
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
/* open 接口 */
int (*open) (struct inode *, struct file *);
/* release 接口*/
int (*release) (struct inode *, struct file *);
/* 异步通知接口 */
int (*fasync) (int, struct file *, int);
};
4、设备号
dev_t dev; __u32
主设备和次设备号组成
主设备号:高12bit
MAJOR(dev_t dev)
#define MINORBITS 20
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
MINOR(dev_t dev) //次设备号
#define MINORMASK ((1U << MINORBITS) - 1)
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
MKDEV(int major,int minor)
二、字符设备驱动编写
1、申请设备号
自动分配设备号
/****************************************************************************
*参数:
* @dev dev_t类型的指针
* @baseminor 次设备号的起始
* @count 设备个数
* @name 设备名
*返回值:成功返回0,失败返回负数错误码
***************************************************************************/
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
手动指定设备号
/****************************************************************************
*参数:
* @from 设备号 MKDEV(int major , int minor)
* @count 设备个数
* @name 设备名
*返回值:成功返回0,失败返回负数错误码
***************************************************************************/
int register_chrdev_region(dev_t from, unsigned count, const char *name)
void unregister_chrdev_region(dev_t from, unsigned count)
2、分配cdev结构体
/***************************************
*参数:
* @void
*返回值:成功返回cdev结构体指针,失败
* 返回NULL
**************************************/
struct cdev *cdev_alloc(void)
3、初始化cdev结构体
/**********************************************************************
*参数:
* @cdev cdev结构体指针
* @fops 操作方法集指针
*返回值:void
*********************************************************************/
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
4、将cdev添加到内核中
/***************************************************************
*参数:
* @p cdev结构指针
* @dev 设备号
* @count 设备个数
*返回值:成功返回0,失败返回负数错误码
**************************************************************/
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
void cdev_del(struct cdev *p)
三、字符设备驱动文件创建
1、 通过命令创建设备文件
mknod - make block or character special files
mknod NAME TYPE [MAJOR MINOR]
TYPE : c 字符设备 b :块设备
NAME : 设备文件名
2、通过udev守护进程创建
class_create
device_crete