字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、IIC、SPI,LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。
/************字符设备注册*******/
static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
//major:主设备号(Linux每个设备下有一个主设备号和次设备号)
//设备号可通过cat /proc/devices查看已经使用的设备号,即可使用没用的设备号。
//name:设备名,一般用字符串来表示
//fops:指向设备的操作函数集合变量的结构体指针,fop内的我们要使用的函数需要自己去实现
/************字符设备注销**************/
static inline void unregister_chrdev(unsigned int major, const char *name)
//major:要注销的设备对应的主设备号。
//name:要注销的设备对应的设备名。
开发步骤:
1.自定义实现结构体内的函数,并在实例化file_operations的结构体的时候,依次按在File_operations结构体对函数定义的格式写好具体实现的函数。。
2.框架:模块加载(注册设备)---->即可用之前自定义好的函数---->当完成设备操作---->模块卸载(注销设备)。
现在我需要对这个设备执行以下操作,open,read,write,release。需要先定义好一个结构体。以及随后要写的具体函数。
static struct file_operations test_fops = {
.owner = THIS_MODULE,
.open = chrtest_open,
.read = chrtest_read,
.write = chrtest_write,
.release = chrtest_release,
};
搭建好字符设备的框架:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#define MAJOR_NUMBER 200 //cat /proc/devices即可查看已使用的设备号
const char* CHR_NAME = "chr_test";
static int chrtest_open(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t chrtest_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
return 0;
}
static ssize_t chrtest_write(struct file *filp,const char __user *buf, size_t cnt, loff_t *offt)
{
return 0;
}
static int chrtest_release(struct inode *inode, struct file *filp)
{
return 0;
}
static struct file_operations test_fops = { //实例化一个函数结构体
.owner = THIS_MODULE,
.open = chrtest_open,
.read = chrtest_read,
.write = chrtest_write,
.release = chrtest_release,
};
int xxx_init(void) //模块入口函数
{
int retvalue = 0;
retvalue = register_chrdev(MAJOR_NUMBER, CHR_NAME, &test_fops); //设备注册
if(retvalue < 0){
printk("register failed!!!!\n"); //printf 运行在用户态,printk 运行在内核态。
}
printk("register success!!!!\n");
return 0;
}
void xxx_exit(void) //模块退出函数
{
unregister_chrdev(200, CHR_NAME); //设备注销
}
module_init(xxx_init);
module_exit(xxx_exit);
MODULE_LICENSE("Dual BSD/GPL");