字符设备驱动

0. 字符设备驱动简介

字符设备驱动是Linux驱动中最基本的一类设备驱动,也是我们学习重点。

我们从下面这一张图来详解字符设备驱动

在这里插入图片描述

在linux内核中,使用cdev结构体来描述一个字符设备驱动,关于cdev的结构体的定义和操作在include\linux\cdev.h头文件中

#ifndef _LINUX_CDEV_H
#define _LINUX_CDEV_H

#include <linux/kobject.h>
#include <linux/kdev_t.h>
#include <linux/list.h>

struct file_operations;
struct inode;
struct module;

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 *, const struct file_operations *);

struct cdev *cdev_alloc(void);

void cdev_put(struct cdev *p);

int cdev_add(struct cdev *, dev_t, unsigned);

void cdev_del(struct cdev *);

void cd_forget(struct inode *);

#endif

1. cdve 结构体

struct cdev {
	struct kobject kobj;  /*内嵌的kobject对象方便以后引用,也会在sys下生成相关的设备文件*/
	struct module *owner; /*所属于的模块,正常的就是本模块THIS_MODULE*/
	const struct file_operations *ops;/*linux下一切皆文件,字符设备也是文件。*/
	struct list_head list;/*字符设备的链表头*/
	dev_t dev;   /*设备号*/
	unsigned int count;
};

在字符设备中最重要的就是 const struct file_operations *ops dev_t dev 2个成员。

2.dev_t Linux设备号

dev_t 类型定义在include/linux/types.h 头文件中。

typedef __u32 __kernel_dev_t;

typedef __kernel_dev_t		dev_t;

Linux设备号位32位,其高12位为主设备号,第20为次设备号。include\linux\kdev_t.h头文件中定义了设备号相关宏和函数。

#define MINORBITS	20
#define MINORMASK	((1U << MINORBITS) - 1)

#define MAJOR(dev)	((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev)	((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi)	(((ma) << MINORBITS) | (mi))

2.1设备号的分配

  1. 静态分配设备号(自己确定设备的设备号)

    内核如何管理设备驱动:内核中有一个255个元素的数组来存储字符设备驱动。

    有一些常用的设备号已经给Linux内核开发使用了,具体如miscdev input。分配的内容可以查看文档 Documentation/devices.txt。

    查看当前系统中所使用的设备号:

    cat /proc/devices
    
  2. 动态分配设备号(由系统分配)

    静态分配设备号需要我们检查当前系统中所有被使用了的设备号,然后挑选一个没有使用的。而且静态分配设备号很容易带来冲突问题, Linux 社区推荐使用动态分配设备号,在注册字符设备之前先申请一个设备号,系统会自动给你一个没有被使用的设备号,这样就避免了冲突。卸载驱动的时候释放掉这个设备号即可。

    设备号的申请函数:

    int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
    			const char *name)
    

    设备号的注册函数:

    int register_chrdev_region(dev_t from, unsigned count, const char *name)
    

    设备号的释放函数:

    void unregister_chrdev_region(dev_t from, unsigned count)
    

3. cdev操作函数

void cdev_init(struct cdev *, const struct file_operations *);

struct cdev *cdev_alloc(void);

void cdev_put(struct cdev *p);

int cdev_add(struct cdev *, dev_t, unsigned);

void cdev_del(struct cdev *);

void cd_forget(struct inode *);

cdev_add()函数和cdev_del()函数分别向系统添加和删除一个cdev,完成字符设备的注册和注销。对cdev_add()的调用通常发生在字符设备驱动的模块加载函数中,而对cdev_del()函数通常发生在字符设备驱动模块卸载函数中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值