字符驱动流程

一、字符设备驱动流程

 

  • 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据。字符设备是面向流的设备,常见的字符设备有鼠标、键盘、串口、控制台和LED设备等。
  • 存放位置:在 /dev 目录下对应一个设备文件

 


分配cdev(二选一)
register_chrdev_regiondev_t from, unsigned count, const char * name分配名为name,count设备号为from+count的字符设备,有端口占用的风险
alloc_chrdev_regiondev_t *dev, unsigned baseminor, unsigned count, const char *name让内核分配名为name,count设备号存在dev+count中的字符设备
初始化file_opera  struct file_operations file_opera ={ .... }将自定义的操作方法加入到file_opera 
初始化cdevcdev_initstruct cdev *cdev, const struct file_operations *fops将cdev加入cdev链表,cdev中的kobject加入其链表,绑定fops操作方法块
注册cdevcdev_addstruct cdev *p, dev_t dev, unsigned count申请设备号dev+count个字符设备,并加入到总线中
  cdev.owner = THIS_MODULE

给字符设备中的owner赋值,常用THIS_MODULE

 

创建设备节点(可选)class_createowner, name创建一个设备名为name的基类
device_create

struct class *class, struct device *parent,

dev_t devt, void *drvdata, const char *fmt, ...

以class为数据基类,在其之上创建一个设备号为devt的名为fmt的设备节点,parent、drvdata常为NULL,devt要与相对应注册的字符设备号一致

 

初始化流程如上图所示,其相关函数作用可自行百度搜索,其主要注意事项如下:

//Linux内核抽象出来的设备结构体
struct cdev {
	struct kobject kobj;
	struct module *owner;
	const struct file_operations *ops;
	struct list_head list;
	dev_t dev;
	unsigned int count;
};

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;
}

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;
}

其中在注册完字符设备 cdev_add 后,cdev结构体除了owner均已初始化,所以我们还要加上owner的初始化。

cdev.owner = THIS_MODULE;
//其中 THIS_MODULE 意为当前模块,是常用的赋值,其源码如下

#ifdef MODULE
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
#else
#define THIS_MODULE ((struct module *)0)
#endif

在cdev_add后,可选择执行 class_create(owner, name) →  device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)  自动生成设备文件。

#define class_create(owner, name)		\
({						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})



struct device *device_create(struct class *class, struct device *parent,
			     dev_t devt, void *drvdata, const char *fmt, ...)
{
	va_list vargs;
	struct device *dev;

	va_start(vargs, fmt);
	dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
	va_end(vargs);
	return dev;
}

执行class_create → device_create 后即在dev中生成设备文件(设备节点)。

 

其对应Linux操作为和流程思考如下:

Linux系统中 总线挂载着各个驱动和设备,驱动实质上就是跟设备通信的特定方法

make编译出来的.ko文件为驱动文件
insmod 后 挂载设备到 linux 系统,同时给它分配主设备号(用来区分驱动类型),
从此在 lsmod 及  proc/devices(设备驱动记录)可以查询驱动名称和它的主设备号

mknod /dev/XXX c 主设备号 次设备号
mknod 后在 dev 中生成设备驱动文件XXX----实质为系统操作主设备号对应的驱动文件接口,可以对这个文件open/write等操作

rmmod 是卸载掉了设备,在 lsmod 和proc/devices中查询不到
没有删除XXX文件前,设备文件依然存在,但是它对应的主设备号驱动已经被卸载了
rm /dev/XXX  删除了设备文件

 

 

驱动操作命令:

      insmod / modprobe 加载驱动

      rmmod                     卸载驱动

      lsmod                       查看系统中所有已经被加载了的所有的模块以及模块间的依赖关系

      modinfo                    获得模块的信息

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值