关闭

【Linux设备驱动】字符设备驱动

213人阅读 评论(0) 收藏 举报
分类:

★关于设备号

◇什么是设备号?它有什么作用?

设备号是一个整形数字,它起到连接设备文件与设备驱动的作用。

它具体是怎样进行连接的

在内核中,字符设备被保存在一个kobj_map结构的cdev_map变量中。通过kobj_map函数将设备号(主次设备号)与字符设备结构体cdev保存到cdev_map中。这个过程实现在cdev_add()函数中,代码如下:

int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
	p->dev = dev;
	p->count = count;
	return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}
在cdev_add()函数中最后一行调用的kobj_map()函数实现了上述过程,现在来看一看这个函数代码:

int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
	     struct module *module, kobj_probe_t *probe,
	     int (*lock)(dev_t, void *), void *data)
{
	unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;//设备个数
	unsigned index = MAJOR(dev);//主设备号
	unsigned i;
	struct probe *p;

	if (n > 255)
		n = 255;

	p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);

	if (p == NULL)
		return -ENOMEM;

	for (i = 0; i < n; i++, p++) {
		p->owner = module;
		p->get = probe;
		p->lock = lock;
		p->dev = dev;//设备号存放位置
		p->range = range;
		p->data = data;//cdev结构体存放位置
	}
	mutex_lock(domain->lock);
	for (i = 0, p -= n; i < n; i++, p++, index++) {//s是存放cdev_map结构体中probes[index%255]的地址
		struct probe **s = &domain->probes[index % 255];//主设备号为index的驱动程序
		while (*s && (*s)->range < range)//将主设备号相同的设备放到一个链表中
			s = &(*s)->next;
		p->next = *s;
		*s = p;
	}
	mutex_unlock(domain->lock);
	return 0;
}
其中有一些代码已经加了注释。这里最难理解的地方就是将主设备号相同的字符设备放到同一个链表的这几行代码。

mutex_lock(domain->lock);
	for (i = 0, p -= n; i < n; i++, p++, index++) {//s是存放cdev_map结构体中probes[index%255]的地址
		struct probe **s = &domain->probes[index % 255];//主设备号为index的驱动程序
		while (*s && (*s)->range < range)//将主设备号相同的设备放到一个链表中
			s = &(*s)->next;
		p->next = *s;
		*s = p;
	}
	mutex_unlock(domain->lock);
其中domain在程序中便是cdev_map,这里将cdev_map锁住,防止多进程对cdev_map操作。
struct probe **s = &domain->probes[index % 255]
就是确定主设备号为index的驱动程序。

struct kobj_map {
	struct probe {
		struct probe *next;
		dev_t dev;
		unsigned long range;
		struct module *owner;
		kobj_probe_t *get;
		int (*lock)(dev_t, void *);
		void *data;
	} *probes[255];
	struct mutex *lock;
};
在这个结构体中struct probe *probes[255];这个结构体指针数组就是用来存放主设备号字符驱动的地址的,其中主设备号为0~254
其中这255个数组成员都会指向一个struct probe的结构体,而这个结构体代表的就是主设备号不同的字符设备驱动。
while (*s && (*s)->range < range)//将主设备号相同的设备放到一个链表中
			s = &(*s)->next;
		p->next = *s;
		*s = p;
这段代码就是将之前申请的p指针指向的struct probe结构体加载到主设备号相同的链表中去。

kobj_map()这个函数主要的作用将加载到内核的字符设备cdev与设备号dev存入申请的struct probe结构体p中;然后将p指针指向的struct probe结构体加载到同为主设备号下的一个链表中。这样当打开一个字符设备文件时,就可以通过设备号找到相应的字符设备,并且调用它的file_operations结构体中的函数。

◇申请设备号的方式有两种:静态申请和动态申请。

 所谓静态申请就是直接指定主设备号,然后使用函数

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

申请。动态申请则不指定设备号,

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

让系统自动分配设备号使用。设备号可以分为主设备号与次设备号。可以通过下面的宏实现:

MAJOR(dev_t dev)
MINJOR(dev_t dev)

★申请注册设备

linux系统中使用cdev结构来表示一个字符设备,注册一个字符设备步骤:
◇申请设备号
◇分配并初始化一个cdev结构体
分配并初始化一个cdev结构体有两种方式:cdev_alloc()、cdev_init()
cdev_alloc()用于动态申请一个cdev结构体
cdev_init()用于初始化cdev成员,建立cdev与file_operations之间的联系
◇将此结构体加入内核中
cdev_add(struct cdev*p,int count)将此结构体加入到内核中

★注销设备

首先注销设备号,
unregister_chrdev_region(xxx_dev_no,1)
然后注销设备
cdev_del(&xxx_dev.cdev)

★Linux字符设备驱动的组成

◇字符设备驱动模块加载与卸载函数
◇字符设备驱动的file_operations结构体中成员函数
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

linux设备驱动第三篇:写一个简单的字符设备驱动

在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动。本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存。 下面就开始学习如何写一个简单的字符设备驱动。首先我们来分解一下字符设备驱动都有那些结构或者方法组...
  • HAOMCU
  • HAOMCU
  • 2015-03-28 19:05
  • 23924

字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

学习Linux设备驱动开发的过程中自然会遇到字符设备驱动、平台设备驱动、设备驱动模型和sysfs等相关概念和技术。对于初学者来说会非常困惑,甚至对Linux有一定基础的工程师而言,能够较好理解这些相关技术也相对不错了。要深刻理解其中的原理需要非常熟悉设备驱动相关的框架和模型代码。网络上有关这些技术的...
  • fivedoumi
  • fivedoumi
  • 2016-03-17 14:52
  • 2215

linux字符设备驱动开发模板及Makefile

linux2.6字符设备驱动开发模板 #include #include #include #include #include //=======================字符设备驱动模板开始 ===========================// #define CHAR_...
  • wdzxl198
  • wdzxl198
  • 2013-04-18 09:14
  • 4167

深入理解Linux字符设备驱动

文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次、组成框架和交互、如何编写驱动、设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解。
  • yueqian_scut
  • yueqian_scut
  • 2016-03-20 11:09
  • 3340

块设备和字符设备驱动比较

块设备和字符设备驱动比较 Linux中I/O设备分为两类:块设备和字符设备。两种设备本身没有严格限制,但是,基于不同的功能进行了分类。 (1) 字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。相反,此类设备支持按字节/字符来读写数据。举例来说,调制解调器是典型的字符设备。 ...
  • u013177084
  • u013177084
  • 2014-09-12 22:16
  • 820

linux高级字符设备驱动以及实例(TQ2440)

应用程序即用户空间中,ioctl 原型如下:int ioctl(int fd,unsignedlong cmd,...) 设备驱动方法中:int (*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned...
  • zbffff
  • zbffff
  • 2013-09-22 15:25
  • 1313

Linux字符设备驱动和杂项设备驱动对比

初学Linux驱动程序的时候,可能对什么是字符设备驱动(char device)和杂项设备驱动(misc device)并不是很了解,更谈不上如何区分了。我自己当初在学习Linux字符设备驱动的时候,也并没有特地去了解其两者之间的区别,尤其是在两种驱动设备注册的时候,没有意识到其不同之处,导致后来在...
  • JansonZhe
  • JansonZhe
  • 2016-01-22 16:43
  • 2138

linux字符设备驱动中自动创建设备节点

本文简述在linux字符设备驱动编程中自动创建设备节点。至于手动创建设备节点的编程
  • yxtouch
  • yxtouch
  • 2014-10-23 19:48
  • 958

Linux 字符设备驱动开发基础(三)—— read()、write() 相关函数解析

我们在前面讲到了file_operations,其是一个函数指针的集合,用于存放我们定义的用于操作设备的函数的指针,如果我们不定义,它默认保留为NULL。其中有最重要的几个函数,分别是open()、read()、write()、ioctl() ,下面分别对其进行解析     &#...
  • zqixiao_09
  • zqixiao_09
  • 2016-03-11 22:16
  • 4554

Linux设备驱动之字符设备驱动

一、linux系统将设备分为3类:字符设备、块设备、网络设备。 应用程序调用的流程框图: 三种设备的定义分别如下, 字符设备:只能一个字节一个字节的读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后顺序进行。字符设备是面向流的设备,常见的字符设备如鼠标、键盘、串...
  • andylauren
  • andylauren
  • 2016-07-01 19:36
  • 4704
    个人资料
    • 访问:210950次
    • 积分:3600
    • 等级:
    • 排名:第10588名
    • 原创:131篇
    • 转载:98篇
    • 译文:0篇
    • 评论:23条
    博客专栏