当前位置:首页 > 嵌入式 > 嵌入式硬件

Linux中I/O设备分为两类:块设备和字符设备。两种设备本身没有严格限制,但是,基于不同的功能进行了分类。

(1) 字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。相反,此类设备支持按字节/字符来读写数据。举例来说,调制解调器是典型的字符设备。

(2) 块设备:应用程序可以随机访问设备数据,程序可自行确定读取数据的位置。硬盘是典型的块设备,应用程序可以寻址磁盘上的任何位置,并由此读取数据。此外,数据的读写只能以块(通常是512B)的倍数进行。与字符设备不同,块设备并不支持基于字符的寻址。

两种设备本身并没用严格的区分,主要是字符设备和块设备驱动程序提供的访问接口(file I/O API)是不一样的。本文主要就数据接口、访问接口和设备注册方法对两种设备进行比较。

1、数据结构

1.1字符设备数据结构

struct file;
struct inode;

file定义于 , 是设备驱动中第二个最重要的数据结构. 文件结构代表一个打开的文件. 它由内核在 open 时创建, 并传递给在文件上操作的任何函数, 直到最后的关闭. 在文件的所有实例都关闭后, 内核释放这个数据结构。

inode 结构由内核在内部用来表示文件.inode 结构包含大量关于文件的信息其中dev_t i_rdev成员包含实际的设备编号.struct cdev *i_cdev中struct cdev 是内核的内部结构, 代表字符设备。

1.2块设备数据结构

struct gendisk (定义于 ) 是单独一个磁盘驱动器的内核表示. 事实上, 内核还使用 gendisk 来表示分区。

2、设备访问接口

2.1字符设备访问接口

struct file_operations 其中file_operation 结构中的每个成员必须指向驱动中的函数, 这些函数实现一个特别的操作, 或者对于不支持的操作留置为 NULL. 当指定为 NULL 指针时内核的确切的行为是每个函数不同的,该结构中主要函数如下:

ssize_t read(struct file *filp, char __user *buff, size_t count, loff_t *offp);
ssize_t write(struct file *filp, const char __user *buff, size_t count, loff_t *offp);

filp 是文件指针, count 是请求的传输数据大小. buff 参数指向持有被写入数据的缓存, 或者放入新数据的空缓存. 最后, offp 是一个指针指向一个"long offset type"对象, 它指出用户正在存取的文件位置. 返回值是一个"signed size type"。

2.2块设备访问接口

字符设备通过 file_ 操作结构使它们的操作对系统可用. 一个类似的结构用在块设备上; 它是 struct block_device_operations, 定义在 ,其主要操作方法如下:

int (*open)(struct inode *inode, struct file *filp);
int (*release)(struct inode *inode, struct file *filp);

就像它们的字符驱动对等体一样工作的函数; 无论何时设备被打开和关闭都调用它们. 一个字符驱动可能通过启动设备或者锁住门(为可移出的介质)来响应一个 open 调用. 如果你将介质锁入设备, 你当然应当在 release 方法中解锁。

int (*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);

实现 ioctl 系统调用的方法. 但是, 块层首先解释大量的标准请求; 因此大部分的块驱动 ioctl 方法相当短。

3、设备注册

3.1字符设备注册

int register_chrdev_region(dev_t first, unsigned int count, char *name)
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name)
void unregister_chrdev_region(dev_t first, unsigned int count);

允许驱动分配和释放设备编号的范围的函数. register_chrdev_region 应当用在事先知道需要的主编号时; 对于动态分配, 使用 alloc_chrdev_region 代替.

3.2块设备注册

int register_blkdev(unsigned int major, const char *name);
int unregister_blkdev(unsigned int major, const char *name);

register_blkdev 注册一个块驱动到内核, 并且, 可选地, 获得一个主编号. 一个驱动可被注销, 使用 unregister_blkdev。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在嵌入式系统和底层驱动开发中,C语言因其高效性和可控性成为主流选择,但缺乏原生单元测试支持成为开发痛点。本文提出一种基于宏定义和测试用例管理的轻量级单元测试框架方案,通过自定义断言宏和测试注册机制,实现无需外部依赖的嵌入...

关键字: C语言 嵌入式系统 驱动开发

在Linux设备驱动开发中,等待队列(Wait Queue)是实现进程睡眠与唤醒的核心机制,它允许进程在资源不可用时主动放弃CPU,进入可中断睡眠状态,待资源就绪后再被唤醒。本文通过C语言模型解析等待队列的实现原理,结合...

关键字: 驱动开发 C语言 Linux

需求分析是单片机定制研发的基石,此阶段需要开发团队与客户展开深度沟通。不仅要明确设备的应用场景,例如是用于工业控制、消费电子,还是医疗设备等领域;还要精准确定功能目标,像工业控制设备可能要求高速数据处理和可靠的通信功能,...

关键字: 单片机 设备 工业控制

在现代电子系统中,电源扮演着核心角色,如同人体的心脏,为整个系统稳定运行提供不可或缺的动力支持。从日常生活中的智能设备,到复杂精密的工业控制系统,再到关乎国计民生的航空航天、医疗等关键领域,电源的可靠性直接决定了系统的稳...

关键字: 电源 设备 系统

在当今快节奏的生活中,智能家居已成为提升居家幸福感与舒适度的得力助手。从清晨自动拉开的窗帘,到夜晚根据环境自动调节亮度的灯光,智能家电让生活变得更加便捷、高效。据相关数据显示,过去几年间,全球智能家居市场规模持续增长,预...

关键字: 智能家居 设备 电气安全

前段时间 Semicon 热闹非凡,半导体设备企业占据了多数席位,呈现一片欣欣向荣之势。但殊不知在这喧嚣的背后,设备产业已经悄然切换到分层时代。接下来海量设备企业将无可避免地迎来残酷的淘汰赛,现在关税大战爆发,国产替代加...

关键字: 半导体 设备 国产替代

在工业物联网(IIoT)蓬勃发展的当下,为设备挑选恰当的通信方案至关重要。而节能,更是其中不可忽视的关键考量因素。从降低运营成本,到提升设备续航、减少环境影响,节能通信方案都发挥着举足轻重的作用。接下来,我们就深入探讨如...

关键字: 工业物联网 设备 通信

在数字化时代,电子墨水屏(E-Ink)因其独特的显示效果和低功耗特性,在电子书、智能手写本等领域得到了广泛应用。然而,电子墨水屏的刷新率一直是其发展的瓶颈,如何在保证低功耗的同时提高刷新率,成为了驱动开发中的一个重要课题...

关键字: 电子墨水屏 E-Ink 驱动开发

在当今科技飞速发展的时代,大功率电源在众多领域发挥着关键作用,从工业制造到新能源汽车,从通信基站到数据中心,其应用范围极为广泛。大功率电源部研发部承担着研发高效、稳定、可靠的大功率电源的重任,而这离不开一系列专业设备与工...

关键字: 大功率 电源 设备

触摸屏作为现代电子设备的重要组成部分,广泛应用于智能手机、平板电脑、智能穿戴设备、车载系统以及各类自助终端等领域。然而,触摸失灵作为触摸屏常见的故障之一,不仅影响用户体验,还可能导致设备无法正常使用。

关键字: 触摸屏 触摸失灵 设备
关闭