Linux字符设备驱动应用

1Linux字符设备驱动的设备对象组成-linux字符设备结构体

struct cdev {
	struct kobject kobj; /*内核内嵌Kobj对象
	struct moudle *owner; /*所属模块*/
	struct file_operations *ops;//文件操作结构体
	struct list_head list;//链表头
	cdev_t cdev;//设备号
	unsigned int count;
};

(1)字符设备成员-设备号的生成以及获取
设备号的生成方式:cdev_t 为设备值,32位,其中前十二位为主设备,后20位为次设备

MAJOR(cdev_t dev)//通过设备号dev的值获取到主设备
MINOR(cdev_t dev)//通过设备号dev的值获取到次设备
MKDEV(int major,int minor)//通过主次设备值得到设备值

申请以及释放字符设备号(在注册cdev之前需要申请设备号)

//申请设备号接口
int register_chrdev_region(cdev_t from,unsigned count,const char *name);//已经知道from情况下向系统申请
//设备号,from为已经知道的设备号,name为设备名字
int alloc_chrdev_region(cdev_t *dev,unsigned baseminor,unsigned count,const char *name)//在没用知道设
//备的情况下向linux内核动态申请设备号,*dev储存申请设备成功的返回值,baseminor是要申请的次设备
//号,name为设备名字

//释放设备号接口
void unregister_chrdev_region(cdev_t from,unsinged count)

(2)字符设备成员--file_operations操作集合
这些接口是在系统文件系统打开设备节点的时候通过系统调用陷入内核调用的接口,例如系统调用open,write,read,close就分别对应着file_operations集合的open,write,read,close。

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 ssize_t (*aio_write) (struct kiocb *
, const struct iovec *
, unsigned int (*iterate) (struct file *
, struct dir_context *);unsigned int (*poll) (struct file *
, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *
, unsigned int, unsigned long);long (*compat_ioctl) (struct file *
, unsigned int, unsigned long);int (*mmap) (struct file *
, struct vm_area_struct *);int (*open) (struct inode *
, struct file *);int (*flush) (struct file *
, fl_owner_t id);int (*release) (struct inode *
, struct file *);int (*fsync) (struct file *
, loff_t, loff_t, int datasync);int (*aio_fsync) (struct kiocb *
, int datasync);int (*fasync) (int, struct file *
, int);int (*lock) (struct file *
, int, struct file_lock *);ssize_t (*sendpage) (struct file *
, struct page *
, int, size_t, loffunsigned long (*get_unmapped_area)(struct file *
, unsigned long, unsunsigned long, unsigned long);int (*check_flags)(int);int (*flock) (struct file *
, int, struct file_lock *);ssize_t (*splice_write)(struct pipe_inode_info *
, struct file *
, lofssize_t (*splice_read)(struct file *
, loff_t *
, struct pipe_inode_inint (*setlease)(struct file *
, long, struct file_lock **);long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);int (*show_fdinfo)(struct seq_file *m, struct file *f);

(3)常用字符设备初始化以及注册接口

void cdev_init(struct cdev *,struct file_operations *);//初始化file_operations 成员
struct cdev *cdev_alloc(void);//申请一个cdev内存
int cdev_add(struct cdev *,dev_t ,unsigned);//注册cdev,dev_t为设备号
void cdev_del(struct cdev *);//删除cdev设备

2.Linux字符设备的驱动demo

(1)字符设备驱动的加载以及卸载函数

struct xxx_dev{
...
struct cdev cdev;/**/封装cdev
...
};
//类似继承效果,在原来的字符设备的结构体上封装了一层。

static init __int xxx_cdev_init(void)
{

	//初始化文件操作集合以及模块拥有者
	...cdev_init(&xxx_dev.dev,xxx_fops);
	xxx_dev.cdev.owner = THIS_MODULE;
	
	//申请设备号
	if(xxx_major){
			register_chrdev_region(xxx_dev_no,1,DEV_NAME);
	}else{
			alloc_chrdev_region(&xxx_dev_no,0,1,DEV_NAME);
	}
	//注册字符设备
	cdev_add(&xxx_dev.dev,xxx_dev_no,1);
}

static init __exit xxx_cdev_exit(void)
{
		unregister_chrdev_region(xxx_dev_no,1);
		cdev_del(&xxx_dev.dev);
}

3,设备节点的创建

需要操作字符设备驱动的file_operations中open,read,write等接口还需要创建一个设备节点。
//这里面又两个函数
dev_class = class_create(THIS_MODULE, DEVICE_NAME);
和class_device_create(dev_class, NULL, MKDEV(dev_major, 0), NULL, “%s”, DEVICE_NAME);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值