4.字符设备驱动基础(上)

字符设备驱动框架

在这里插入图片描述
什么是字符设备?
就是它所产生的数据是字符流。读取速度快,读取数据少。比如LCD,keyboard,IIC
什么是块设备?
就是以块为单位存储的,就是存储设备。读取速度慢,读取数据大。比如,磁盘、u盘、flash、SD卡
什么是网络设备?
就是socket设备。比如,以太网、wifi

作为字符设备驱动要素:
1,必须有一个设备号,用在众多到设备驱动中进行区分
2,用户必须知道设备驱动对应到设备节点(设备文件)
linux把所有到设备都看成文件

		crw-r----- 1 root root 13, 64 Mar 28 20:14 event0
		crw-r----- 1 root root 13, 65 Mar 28 20:14 event1
		crw-r----- 1 root root 13, 66 Mar 28 20:14 event2
	3,对设备操作其实就是对文件操作,应用空间操作open,read,write的时候
		实际在驱动代码有对应到open, read,write

设备节点用于open的时候打开该设备
设备号用于区分某一类设备中的某一个设备

申请设备号-register_chrdev接口

作为驱动必须有一个主设备号–向系统申请
申请
int register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
参数1:主设备号
设备号(32bit–dev_t)==主设备号(12bit) + 次设备号(20bit)
主设备号:表示一类设备–camera
次设备号: 表示一类设备中某一个:前置,后置

		给定到方式有两种:
			1,动态分配--参数1直接填0
			2,静态指定--指定一个较大的整数,250


参数2: 描述一个设备信息,可以自定义
		/proc/devices列举出所有到已经注册的设备
参数3: 文件操作对象--提供open, read,write
返回值: 正确返回0,错误返回负数

释放
void unregister_chrdev(unsigned int major, const char * name)
参数1:主设备号
参数2: 描述一个设备信息,可以自定义

ps:怎么查看函数的头文件?
在sourceinsight中把鼠标移到函数上会显示头文件信息

ps:怎么查看申请的设备信息?
cat /proc/devices可以看到字符设备、块设备的设备号,在装载字符设备驱动后能查看是否装载成功

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>

//静态的指定
static unsigned int dev_major = 250;

const struct file_operations my_fops{
   
	
};

static int __init char_dev_init(void)
{
   
	//申请设备号,在proc/devices中可以查看注册的设备号
	int ret;
	ret = register_chrdev(dev_major, "char_dev_test", &my_fops);
	if (ret == 0){
   
		printk("register successfully!\n");
	}else{
   
		printk("register failed!\n");
		return -EINVAL;
	}
	return 0;
}

static void __exit char_dev_exit()
{
   
	//一般都是释放资源
	unregister_chrdev(dev_major, "char_dev_test");
}

module_init(char_dev_init);
module_exit(char_dev_exit);
MODULE_LICENSE("GPL");

手动或自动创建设备节点

1,手动创建–缺点/dev/目录中文件都是在内存中,断电后/dev/文件就会消失

	mknod /dev/设备名  类型  主设备号 次设备号
	比如:
		mknod  /dev/chr0  c  250 0


	[root@farsight drv_module]# ls /dev/chr0 -l
	crw-r--r--    1 0        0         250,   0 Jan  1 00:33 /dev/chr0

2,自动创建(通过udev/mdev机制)
	struct class *class_create(owner, name)//创建一个类
		参数1: THIS_MODULE
		参数2: 字符串名字,自定义
		返回一个class指针

	//创建一个设备文件
	struct device *device_create(struct class * class, struct device * parent, dev_t devt, 
						void * drvdata, const char * fmt,...)
	参数1: class结构体,class_create调用之后到返回值
	参数2:表示父亲,一般直接填NULL
	参数3: 设备号类型 dev_t
			dev_t devt
				#define MAJOR(dev)	((unsigned int) ((dev) >> MINORBITS))
				#define MINOR(dev)	((unsigned int) ((dev) & MINORMASK))
				#define MKDEV(ma,mi)	(((ma) << MINORBITS) | (mi))
	参数4:私有数据,一般直接填NULL
	参数5和6:表示可变参数,字符串,表示设备节点名字,用于open的时候打开


	销毁动作:
		void device_destroy(devcls,  MKDEV(dev_major, 0));
		参数1: class结构体,class_create调用之后到返回值
		参数2: 设备号类型 dev_t

		void class_destroy(devcls);
		参数1: class结构体,class_create调用之后到返回值

ps:怎么查看创建的设备节点?
ls /dev/
a,驱动中实现文件io操作接口:struct file_operations
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值