栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

多字符设备驱动

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多字符设备驱动

        如果一类设备有多个个体,比如系统上有两个串口,那么我们就应该写一个驱动来支持多个设备,而不是每一个设备都写一个驱动

        上一节我们有说了单字符设备的驱动,这次我们来说下多字符设备驱动。

        相比于单设备操作,多设备操作首先在init上要注册多个设备,然后添加多个设备,exit的时候要del多个设备。比较麻烦的是读写,因为不同的设备他们的fifo设备就需要各自独立,那么如何读写的时候去判断读写哪个设备呢?我们观察到open的函数有个inode的参数,节点信息里面包含了设备号以及对应的cdev对象的地址。因此我们可以在open接口函数中取出这些信息,并存在file结构对象的某个成员中(读写函数的参数有file),从而在读写过程中判断是哪类设备。


#include 
#include 
#include 

#include 
#include 
#include 

#define CHRDEV_MAJOR 256
#define CHRDEV_MINOR 0
#define CHRDEV_CNT   2
#define CHRDEV_NAME  "chrdev"


DEFINE_KFIFO(vsfifo0, char, 32);  
DEFINE_KFIFO(vsfifo1, char, 32);


struct vser_dev
{
	struct cdev cdev;
	struct kfifo *fifo;
};

static struct vser_dev vsdev[2];//定义两个设备

static int chrdev_open(struct inode *inode, struct file *filp)
{
	
	filp->private_data = container_of(inode->i_cdev, struct vser_dev, cdev);//ptr, type, member
	return 0;
}

static int chrdev_release(struct inode *inode, struct file *filp)
{
	return 0;
}

static ssize_t chrdev_read(struct file *filp, char __user *buf, size_t count, loff_t *pos)
{
	unsigned int copied = 0;
	
	struct vser_dev *dev = filp->private_data;

	kfifo_to_user(dev->fifo, buf, count, &copied);

	return copied;
}

static ssize_t chrdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos)
{
	unsigned int copied = 0;

	
	struct vser_dev *dev = filp->private_data;
	
	kfifo_from_user(dev->fifo, buf, count, &copied);


	return copied;
}

static struct file_operations chrdev_ops = {
	.owner = THIS_MODULE,
	.open = chrdev_open,
	.release = chrdev_release,
	.read = chrdev_read,
	.write = chrdev_write,
};

static int __init chrdev_init(void)
{
	int i;
	int ret;
	dev_t dev; //在内核中dev_t是一个无符号的32位整数,主设备号占12位,次设备号占20位

	dev = MKDEV(CHRDEV_MAJOR, CHRDEV_MINOR); //对一个设备分配设备号

	
	ret = register_chrdev_region(dev, CHRDEV_CNT, CHRDEV_NAME);
	if (ret)
		goto reg_err;

	
	for (i=0; i0; --i)
	{
		cdev_del(&vsdev[i].cdev);
	}
	unregister_chrdev_region(dev, CHRDEV_CNT);//需要把设备注销掉,否则下次在注册会失败
reg_err:
	return ret;
}

static void __exit chrdev_exit(void)
{
	dev_t dev;
	int i;

	dev = MKDEV(CHRDEV_MAJOR, CHRDEV_MINOR);

	for (i=0; i");
MODULE_DEscriptION("A simple module");
MODULE_ALIAS("virtual-serial");

        代码中我已经加了详细的解释,这里就不再多说了,主要是多多习惯内核的编程思想,比如面向对象的思想等

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/603716.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号