Linux系统调用过程详解:应用程序调用驱动过程

Linux下应用程序调用驱动程序过程:

(1)加载一个驱动模块(.ko),产生一个设备文件,有唯一对应的inode结构体

                a、每个设备文件都有一个对应的’inode‘结构体,包含了设备的主次设备号,是设备的唯一标识。

                b、驱动加载至内核,初始化时通常会调用’register_chrdev()‘或’register_blkdev()‘(字符设备和块设备),注册设备号和关联文件操作file_operation。

                c、有了设备号后,用class_create()和 device_create()创建设备文件 ,device_create()该函数需要一个有效设备号

                d、当设备文件创建后,文件系统会为其创建和初始化一个’inode‘结构体,包含文件类型、权限、所有者信息以及重要的设备号

(2)应用层调用open函数打开设备文件(该函数是在应用层中写好的),对于上层open调用到内核时,发生一次软中断,从用户空间进入到内核空间

(3)open会调用到sys_open(内核系统调用函数),sys_open根据文件的地址(文件的路径),找到设备文件对应的struct inode结构体描述的信息,得知要操作的设备类型(字符设备还是块设备),还会分配一个struct file结构体。

  • sys_open:

                内核级的系统调用函数,用于打开文件和设备。系统调用是用户空间和内核空间之间的接口,通过系统调用可从用户态切换至内核态。

  • sys_open函数的基本操作:

                a、解析用户提供的文件名,确定文件位置和权限(通常为文件的路径名,如/dev/设备名)

                b、检查文件访问权限

                c、分配并初始化一个文件描述符(对该文件操作的引用,非负的整数,是该文件表条目在文件表中的索引)

                d、将文件描述符返回给用户空间

  • struct file:
    • 内核中的重要结构体,表示一个已打开的文件(信息)。
    • 包含相关的文件状态信息,如当前偏移量、文件操作指针file_operation(包含对文件读写的操作函数指针)、'inode'结构体指针
    • 由sys_open创建,内核为打开的文件创建一个新的'struct file'实例

(4)根据struct inode结构体内记录的主次设备号,在驱动链表(管理所有设备驱动)里面,找到字符设备驱动。

        这一步也是后续为了给创建的file结构体内的f_ops成员,文件操作指针赋值

  • 驱动链表:
    • Linux内核中用于管理设备驱动的关键数据结构,是一个链表或哈希表结构,其中包含了所有注册的设备驱动。
    • 字符设备的驱动链表中,每个成员(设备)确实是通过 struct cdev 结构体来表示的。
    • 字符设备驱动通过调用 cdev_add() 函数将自己的 cdev 结构体添加到内核的设备表中(这通常是在调用 register_chrdev_region() 或 alloc_chrdev_region() 注册设备号之后进行的。

(5)每个字符设备都有一个struct cdev结构体。描述了字符设备的所有信息,其中最重要的一项是字符设备的操作函数接口

(6)找到struct cdev结构体后,linux内核就会将struct cdev结构体所在内存空间首地址记录在struct inode结构体i_cdev成员中,将struct cdev结构体中记录的函数操作接口地址记录在strct file结构体的f_ops成员中

(7)执行xxx_open驱动函数。

流程架构参考自:最全Linux驱动开发全流程详细解析(持续更新)-CSDN博客

inode结构体组成

变量赋值的来源

这些变量的值大多是由文件系统、内核的设备管理子系统,或驱动自身在注册设备时设置的。

例如:

  • i_mode(文件模式):通常由驱动设置以标识设备文件的类型(字符设备或块设备)
  • i_rdev(实际设备ID):包含主设备号和次设备号(高12位和低20位),由register_chrdev()或register_blkdev()设置

文件系统中对于'inode'

在创建和管理'inode'结构体中起到核心作用,当一个文件系统被挂载时,它会初始化其管理的所有 inode,并负责管理它们的生命周期。文件系统会定义自己的'inode'操作方法('inode_operation'结构体,也是inode结构体的成员变量),包括:

        a、创建 (create):当新文件被创建时,文件系统会分配和初始化一个 inode 结构体。这包括设置文件类型、权限、所有者等。

        b、查找 (lookup):在访问文件时,文件系统需要通过路径查找相应的 inode。

        c、删除 (delete):当文件被删除时,文件系统负责清理 inode 结构体,并可能将其空间释放回 inode 缓存。

文件描述符:
用于访问文件和设备的一个抽象表示。文件描述符本质上是一个非负整数,当一个程序打开一个文件(包括设备文件)时,操作系统返回的文件描述符作为未来所有对该文件的操作的引用。

文件描述符的形式和功能

  • 形式:文件描述符是一个简单的整数值。在一个进程的上下文中,每打开一个文件或设备,内核就会分配最低未被使用的文件描述符。
  • 功能:文件描述符提供了一个通用的方法来引用所有类型的文件,无论它们是普通的磁盘文件、目录、链接还是设备(如键盘、硬盘、网络设备等)。

文件描述符的操作

当一个文件或设备被打开时,内核会创建一个文件表条目。文件描述符就是这个文件表条目在文件表中的索引。

文件表条目包括:文件位置、当前偏移量、访问权限、指向具体文件操作的指针等。

  • 基于文件描述符的标准操作:

                a、打开操作open(pathname, flags, ... ):打开一个已存在的文件或创建一个新文件,并返回一个文件描述符

                b、读操作 (read(fd, buffer, size)):从由 fd 指定的文件或设备中读取数据。

                c、写操作 (write(fd, buffer, size)):向由 fd 指定的文件或设备写入数据。

                d、输入输出控制操作 (ioctl(fd, command, ...)):对特定的设备执行控制和配置操作。

                e、文件控制操作(fcntl(fd, command, ...)):改变已打开的文件性质。

                f、关闭操作 (close(int fd)):关闭文件描述符。

file结构体组成

struct file主要成员解释

  • f_path:包含文件的路径和文件系统信息,struct path 结构体包括一个指向 dentry(目录项)和 vfsmount(文件系统挂载点)的指针。
  • f_inode:指向与文件关联的 inode 结构体的指针,它存储了文件的大部分元数据。
  • f_op:指向文件操作表的指针,这个表包含了各种文件操作相关的函数指针,如 readwriteopenrelease 等。
  • f_lock:自旋锁,用于保护文件相关的敏感操作。
  • f_count:原子类型,表示文件描述符的引用计数,用于文件描述符的复制和释放管理。
  • f_flags:打开文件时使用的标志,如 O_RDONLYO_NONBLOCK 等。
  • f_mode:文件模式,指定文件的访问模式,如只读、只写等。
  • f_pos:当前文件的偏移量,表示下一次读/写的起始位置。
  • f_owner:文件所有者的信息,常用于信号发送。
  • f_mapping:指向文件的地址空间结构,用于文件映射和内存管理。

驱动链表的设备匹配

当一个应用程序尝试通过系统调用(open())访问一个字符设备时,内核在驱动链表中找到相应的设备驱动的步骤:

1、设备号解析

应用程序请求打开一个设备文件(/dev/example)时,内核首先获取该设备文件的'inode'结构体,从中读取主次设备号

  • 主设备号:用于识别该设备的驱动程序
  • 次设备号:用于识别该驱动程序控制的特定设备实例(控制的是哪个设备)

2、驱动链表搜索

内核中维护了一个包含所有已注册字符设备的列表(register_chrdev()),每个注册设备通过一个'struct cdev'实例表示,并链接到全局链表中。内核遍历这个链表,比较每个'struct cdev'的设备号

  • 链表遍历:从链表头部开始,内核遍历每个'cdev'条目
  • 匹配主设备号:内核检测每个'cdev'的主设备号是否与请求的主设备号匹配

3、文件操作结构体关联

一旦找到匹配的'cdev'结构体,内核将使用该结构体中的'file_operations'指针。

  • 设备操作:应用程序通过系统调用请求的操作(如读取或写入数据)将由file_operations结构体中相应的函数处理。

4、f_op指针设置

内核在打开文件时会创建file struct结构体,但此时部分成员未设置,包括f_op指针(file_operation的指针)。一旦找到正确的驱动,f_op指针会被设置为指向该驱动的file_operations结构体。

后续的操作(如再次读写文件)都会通过这些函数处理(file_operation中的函数)。

Linux设备号:

Linux中每个设备都有一个设备号,由主设备号和次设备号组成。主设备号对应一个具体的驱动,次设备号表示使用这个驱动的各个设备。Linux中提供了一个名为dev_t的数据类型表示设备号,定义在include/linux/types.h中。

1、dev_t类型

  • _u32类型别名为_kernel_dev_t;
  • _kernel_dev_t别名为dev_t
  • 所以dev_t 是__u32 类型的(即unsigned int)

  • _u32:32位的无符号整形unsigned int。

该32位数据构成了主设备号和次设备号,高12位为主设备号,低20位为次设备号,所以系统中主设备号范围为0~4095。

2、设备操作函数:

  • MINORBITS:次设备号位数,20位。
  • MINORMASK:次设备号掩码
  • MAJOR(dev):从dev_t中获取主设备号,将dev_t右移20位
  • MINOR(dev):从dev_t中获取次设备号,取dev_t低20位的值
  • MKDEV(ma,mi):将给定的主设备号和次设备号的值组合成dev_t类型的设备号。(主设备号左移20位)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/611677.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGLM3-6B部署与微调及微调后使用

记录ChatGLM3-6B部署及官方Lora微调示例详细步骤及如何使用微调后的模型进行推理 一、下载代码 使用git clone 命令下载源码 git clone https://github.com/THUDM/ChatGLM3.git 如图所示 二、下载模型 模型权重文件从魔塔进行下载,不需要翻墙。权重文件比较大&…

搭建知识库必备:12个开源 Wiki 软件工具盘点

在任何成功的公司中,部门间的知识共享是至关重要的。如果没有一个简单的信息交流方法,团队怎样才能有效合作呢?Wiki软件提供了一种创建、组织及在全公司范围内分享知识的直接方法。但是,哪一种Wiki软件是最佳的选择呢?…

【计算机毕业设计】springboot工资管理系统

人类现已迈入二十一世纪,科学技术日新月异,经济、资讯等各方面都有了非常大的进步,尤其是资讯与 网络技术的飞速发展,对政治、经济、军事、文化等各方面都有了极大的影响。 利用电脑网络的这些便利,发展一套工资管理系…

Unity 修复Sentinel key not found (h0007)错误

这个问题是第二次遇到了,上次稀里糊涂的解决了,也没当回事,这次又跑出来了,网上找的教程大部分都是出自一个人。 1.删除这个路径下的文件 C:\ProgramData\SafeNet Sentinel,注意ProgramData好像是隐藏文件 2.在Windows…

Mac安装激活--Typora,一个比记事本更加强大的纯文本软件

一、安装 1.首先到官网下载Mac版的Typora,下载地址:https://typoraio.cn/ (1)打开默认中文站 (2)往下滑,下载Mac版 2.下载完成后,会看到Typora.dmg文件,点击打开文件 3.打开Typ…

mac苹果电脑卡顿反应慢如何解决?2024最新免费方法教程

苹果电脑以其稳定的性能、出色的设计和高效的操作系统,赢得了广大用户的喜爱。然而,随着时间的推移,一些用户会发现自己的苹果电脑开始出现卡顿、反应慢等问题。这不仅影响使用体验,还会影响工作效率。那么,面对这些问…

luceda ipkiss教程 68:通过代码模板提高线路设计效率

在用ipkiss设计器件或者线路时,经常需要输入: from ipkiss3 import all as i3那么有什么办法可以快速输入这段代码呢?这里就可以利用Pycharm的 live template功能,只需要将文件:ipkiss.xml (luceda ipkiss教程 68&…

JetBrains的Java集成开发环境IntelliJ 2024.1版本在Windows/Linux系统的下载与安装配置

目录 前言一、IntelliJ在Windows安装二、IntelliJ在Linux安装三、Windows下使用配置四、Linux下使用配置总结 前言 ​ “ IntelliJ IDEA Ultimate是一款功能强大的Java集成开发环境(IDE)。它提供了丰富的功能和工具,可以帮助开发人员更高效地…

深入理解Java HashSet类及其实现原理

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一…

LabVIEW MEMS电容式压力传感器测试系统

LabVIEW MEMS电容式压力传感器测试系统 随着微电子技术的发展,MEMS(微电机系统)技术在各个领域得到了广泛应用。MEMS电容式压力传感器以其高灵敏度、小尺寸、低功耗等优点,在微传感器领域占据了重要的地位。然而,这些…

基于FPGA的音视频监视器,音视频接口采集器的应用

① 支持1路HDMI1路SDI 输入 ② 支持1路HDMI输出 ③ 支持1080P高清屏显示实时画面以 及叠加的分析结果 ④ 支持同时查看波形图(亮度/RGB)、 直方图、矢量图 ⑤ 支持峰值对焦、斑马纹、伪彩色、 单色、安全框遮幅标记 ⑥ 支持任意缩放画面,支…

TypeScript安装及编译

一、TypeScript是什么 ​ Type script 是微软基于 Javascript 开发的开源编程语言,是拥有类型的 Javascript 的超集,继承了js 所有语法,此外增加了一些自己语法。可以编译成普通、千净、完整的 JavaScript 代码。 目的: 不是创造…

【Linux】从零开始认识动静态库 - 静态库

送给大家一句话: 永不言弃,就是我的魔法! ——阿斯塔《黑色四叶草》 ଘ(੭ˊ꒳​ˋ)੭✧ଘ(੭ˊ꒳​ˋ)੭✧ଘ(੭ˊ꒳​ˋ)੭✧ ଘ(੭ˊ꒳​ˋ)੭✧ଘ(੭ˊ꒳​ˋ)੭✧ଘ(੭ˊ꒳​ˋ)੭✧ ଘ(੭ˊ꒳​ˋ)੭✧ଘ(੭ˊ꒳​ˋ)੭✧ଘ(੭ˊ꒳​ˋ)੭✧ 从零…

mysql数据库调优篇章1--日志篇

目录 1.认识数据库中日志的作用2.增加mysql数据库中my.ini 基本配置3.增加my.ini中参数配置4.查看已经执行过的sql语句过去执行时间5.找出慢查询的sql6.常用参数查询命令7.认识慢查询日志记录8.认识通用日志记录(记录增删改查操作)9.认识二进制文件binlo…

多维点分布的均匀性评估方法(NDD和Voronoi 图法)

评估多维点分布的均匀性是统计学和数据科学中的一个重要问题,特别是在模拟、空间分析和样本设计等领域。下面,我将详细介绍2种评估多维点分布均匀性的方法,包括它们的数学原理、实现公式以及各自的优缺点。 1. 最近邻距离法(Neare…

CTF例题和知识点

[ACTF2020 新生赛]Include 打开靶机发现一个超链接,点击之后出现一段话 “Can you find out the flag?” 查看源码注入,无果 仔细看url,发现有flag.php 根据题目提示,该题应该是文件包含漏洞,因此可以判断出此题是PH…

通俗的理解网关的概念的用途(三):你的数据包是如何到达下一层的

其实,这一章我写不好,因为这其中会涉及到一些计算和一些广播等概念,本人不善于此项。在此略述,可以参考。 每台设备的不同连接在获得有效的IP地址后,会根据IP地址的规则和掩码的规则,在操作系统和交换机&a…

自动控制原理学习--平衡小车的控制算法(三)

上一节PID的simulin仿真,这一节用LQR 一、模型 二、LQR LQR属于现代控制理论的一个很重要的点,这里推荐B站的【Advanced控制理论】课程(up主DR_CAN),讲得很好,这里引用了他视频里讲LQR的ppt。 LQR属于lo…

车载电子电器架构 —— 应用软件开发(中)

车载电子电器架构 —— 应用软件开发(中) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明…

医疗行业如何提升Windows操作系统登录的安全性

医疗行业使用账号和密码登录Windows系统时,可能会遇到一些痛点,这些痛点可能会影响工作效率、数据安全和用户体验。以下是一些主要的痛点: 1. 密码管理复杂性:医疗行业通常涉及大量的敏感数据和隐私信息,因此密码策略…