news 2026/10/6 16:11:49

字符设备驱动(一)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
字符设备驱动(一)

字符设备驱动(一)

目录

前言

我们前两天提到了模块的编写,知道了模块是我们驱动代码的承载物,那么设备又是什么东西呢,顾名思义,它是我们在内核注册的对于硬件的一种抽象,如果把模块比作流水线,那么设备就是生产的产品,所以呢,一个模块可以注册多个设备,但是一个设备只能来自一个模块。本节我们还会用到之前我们Linux应用那几个函数open,read,write函数,以理解Linux内这些函数与c库函数的不同之处。

一、open 函数的流程

我们在应用的那节知道,open函数可以根据flag,和设定权限打开文件,返回fd,当时可能大家都以为这个open跟普通库函数没两样,其实不然,在驱动中,由于不同硬件的差异性,所以这些应用函数肯定不尽相同,就比如一个简简单单的read,不同传感器,不同设备它读取数据肯定不一样吧,所以这个read函数也不一样,那怎么才能做到用户态用一个函数做出不同的效果呢,我们就以open为例来讲一讲。

首先,用户调用open("/dev/xxx"), 这时,就要靠一个sys_open函数让我们从用户态陷入内核态,这时,VFS会根据我们要打开的设备名,查找目录项,找到对应的inode号,里面有我们的设备号等信息,这时会分配一个struct file结构体,就是我们熟知空的文件表,里面存着inode指针,fops函数表这些信息,不过这时候还是默认的,这时候调用的就是默认函数表中的open(chrdev_open),此时内核会给你一个fd进程号,接着内核会调用这个默认open函数,它会路径追踪从inode表里面找到设备号,去/dev里面找到cdev表,读这个哈希表,读到该设备驱动的函数表,并讲file结构体的函数表替换成该函数表(这些函数我们称为回调函数),然后尝试执行这个函数表中的open函数,如果没有open则会返回fd,就跟我们平时的open一样,这样我们就可以在设备驱动这个函数表里添加一些我们想要的功能了。

值得一提的是,open我们就算不写回调函数它也能执行打开文件分配fd的操作,这是内核帮你完成的,是比较特殊的存在。但是呢read,write就不一样了,在设备驱动中,read,write在不同设备中的特异性,必须确保每个read,write函数都有回调函数,否则内核如果找不到这俩回调函数,则会返回错误码。

那么知道了流程,我们就可以反推一下进而设计驱动代码了,这个我们下节再讲,接下来讲讲我们刚刚提到的这一些结构体,它们的成员包含的信息都有哪些。

二、一些结构体

  • file_operations结构体
  • cdev结构体
  • inode结构体
  • device结构体
  • class结构体

一些结构体

file_operations结构体

struct file_operations { struct module *owner; int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); };

该结构体定义了字符设备驱动中文件操作的函数指针,用于实现对设备的读写、打开、关闭等操作。


cdev结构体

struct cdev { struct kobject kobj; dev_t dev; /* 设备号 */ unsigned int count; /* 设备数量 */ struct file_operations *ops; /* 文件操作结构体 */ };

cdev是字符设备的核心结构体,用于管理字符设备的注册和注销过程。


inode结构体

struct inode { umode_t i_mode; /* 文件权限 */ uid_t i_uid; /* 文件所有者 */ gid_t i_gid; /* 文件所属组 */ dev_t i_rdev; /* 字符设备的设备号 */ struct file_operations *i_fop; /* 文件操作结构体 */ };

inode是 Linux 文件系统中表示文件或目录的元数据结构,包含文件的权限、大小、时间戳等信息。


device结构体

struct device { struct class *class; /* 设备所属的类 */ dev_t devt; /* 设备号 */ struct device_driver *driver; /* 关联的驱动程序 */ };

device结构体用于描述设备的属性和行为,是设备模型中的核心结构之一。


class结构体

struct class { struct kobject *kobj; /* 内核对象 */ char name[20]; /* 类名 */ };

class结构体用于表示设备类,是设备模型中用于组织设备的一种方式。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 16:04:46

证书链不完整修复方法(进阶篇):原理、方案与优化

本文深入探讨证书链不完整修复方法(进阶篇),涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。随着业务规模增长,证书链不完整修复方法(进阶篇)的重要性日益凸显。无论你是刚入门还是资深…

作者头像 李华
网站建设 2026/10/6 15:44:12

USB转SATA桥接芯片怎么选?ASMedia五款主流型号对比与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 15:44:07

Linux服务器故障排查:从ping通到SSH不通的分层定位与实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 15:42:16

GM/T 0018-2023实战指南:从SDF接口到国密应用落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华