<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 设备管理》(29)

本文主要是介绍<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 设备管理》(29),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Linux操作系统原理分析之Linux 设备管理》(29)

  • 10 Linux 设备管理
    • 10.1 Linux 设备分类与识别
      • 10.1.1 Linux 设备的分类
      • 10.1.2 设备文件
    • 10.2 设备驱动程序与设备注册
      • 10.2.1 设备驱动程序
      • 10.2.2 设备注册
    • 10.3Linux 的 I/O 控制方式
      • 10.3.1 查询等待方式((轮询方式 轮询方式)
      • 10.3.2 中断方式
    • 10.4Linux 设备 I/O 操作

10 Linux 设备管理

10.1 Linux 设备分类与识别

10.1.1 Linux 设备的分类

类别详细
字符设备以字符为单位输入输出数据的设备,并且以字符为单位对设备中的信息进行组织和处理。显示器、键盘等
块设备以一定大小的数据块为单位输入输出数据,并且设备中的数据也是以物理块为单位进行组织和管理的。硬盘、软盘、光盘等。
网络设备通过网络与外部近程或远程计算机进行通信的设备。网卡

10.1.2 设备文件

linux 设备管理的特点:物理设备抽象化,把物理设备看成文件,采用文件系统的接口和系统调用来
管理和控制设备。Linux 设备就是一种特殊文件,称为设备文件。

  1. 从设备向内存输入数据,相当于从设备文件读取数据;把数据从内存输出到设备可以看作是把数据写
    入设备文件;启动设备时可以看作是打开设备文件;停止设备可看作是关闭设备文件。
  2. Linux 的设备文件一般置于/dev 目录下。系统中每个设备文件都有设备文件名。设备文件名由两个部分
    组成:
    第一部分 2~3 个字符,表示设备的种类;
    第二部分通常是字母或数字,区分同种设备中的单个设备
    👉IDE 普通硬盘是以 hd 命名;第一个 ide 设备是 hda,第二个是 hdb… ;而 hda1,hda2 表示第一块硬盘的第一、第二个磁盘分区。每个硬盘可以最多有四个主分区,因此 1-4 命名硬盘的主分区。
    逻辑分区是从 5 开始的,每多一个分区,数字加 1 就可以。
    👉SCSI 硬盘是用 sd 命名
    👉软盘是用 fs 命名
  3. Linux 设备中有一个特殊的设备:null 设备。通常称其为“黑洞”设备,并没有实体与之对应。向 null
    设备输出的一切数据都被舍弃。(相当于“回收站”)
  4. 在终端使用 ls –l /dev 查看设备列表
  5. 逻辑设备名( 设备类型, 面向进程),物理设备名(设备文件名,面向内核),设备无关性。
  6. 设备文件与与普通文件的差异
    👉设备文件没有象普通文件那样的文件实体,不在外存占据数据块来存放数据
    👉进程访问普通文件是读写磁盘分区中的数据,访问设备文件是对硬件设备进行读写,完成设备与内存之间的数据传送
  7. 网络设备并不与设备文件对应,故网络设备没有设备文件名,只有逻辑设备名。如系统的第一块以太
    网网卡的逻辑设备名是 eth0。Linux 文件系统不能用来管理和控制网络设备。

10.1.3 Linux 设备的识别
Linux 内核对设备的识别是通过: 设备类型+设备号(主、次设备号)。
👉设备类型:字符设备、块设备
👉主设备号:使用同一个驱动程序的每种设备有一个唯一的主设备号
👉次设备号:区分同种设备中的各个具体设备
主次设备号值都是从 0~255

10.2 设备驱动程序与设备注册

10.2.1 设备驱动程序

在这里插入图片描述
1.功能:
👉对设备进行初始化
👉启动、停止设备的运行
👉把设备上的数据传到内存
👉把数据从内存传送到设备
👉检测设备状态
2. 驱动程序虽然是在设备生产厂家开发的,但装入系统后由内核统一管理,处于内核态,成为内核的一部分。
3. Linux 对设备的管理和控制是使用 VFS 提供的各种数据结构和操作函数实现的
4. 驱动程序的编制:
Linux 中对文件的操作使用的是 VFS 虚拟文件系统的文件操作接口,即 file_operations 结构 。
file_operations 结构是文件操作函数指针的集合,在设备管理中,该结构体各个成员项指向的操作函数就是设备驱动程序的各个操作例程。
编制设备驱动程序的工作就是使用汇编或 c 语言编写控制设备完成各种操作的例程,然后把这些操作例程的入口地址赋予 file_operations 结构体的有关成员项即可。
各个操作函数的主要功能:
在这里插入图片描述

10.2.2 设备注册

当一种设备安装到系统时,必须向系统进行注册,注册之后才能使用,设备注册的任务是把驱动程
序加载到系统中。
👉设备的驱动程序是系统在启动时装载到系统中的;
👉对于“即装即用”设备,驱动程序作为程序模块可以随时加载到系统中,

  1. 设备注册表
    两个设备注册表:字符设备注册表、块设备注册表。
#define MAX_CHRDEV 255
#define MAX_BLKDEV 255
static struct device_struct chrdevs[MAX_CHRDEV]; 
static struct device_struct blkdevs[MAX_BLKDEV];
每个注册表都有 255 个表项,每个表项表示一个设备,都是一个 device_struct 结构,称为设备描述符。
在 fs/device.c 中。
struct device_struct {
const char * name; /*指向设备名字符串*/
struct file_operations * fops; /*指向文件操作函数 file_operations 的指针*/
};

在这里插入图片描述
说明:
👉设备注册表的下标是某种设备的主设备号。使用主设备号作为索引就可以从设备注册表得到这种
设备的驱动程序。
👉两个注册表的第一个表项通常为 null,因为系统中不存在主设备号为 0 的字符设备和块设备。

  1. 设备注册函数
    设备被注册时,系统首先构筑 file_operations 结构体,然后把驱动程序的各个操作函数的入口地址
    赋予结构体的有关成员项,成员项没有对应函数时,则置为 null。设备注册是通过系统调用注册函数实现
    的。在 fs/device.c 中。
    字符设备注册函数:
int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)

块设备注册函数:

int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)

👉若major=0。注册一个新设备,由系统自动分配一个主设备号给驱动程序,成功则返回主设备号。
👉若major!=0,此时注册函数可以变更主设备号为 major 的设备的: 设备名或驱动程序。 成功返回0;

if (major == 0){
for (major = MAX_CHRDEV-1; major > 0; major--) 
if (chrdevs[major].fops == NULL) /*从注册表 chrdevs[]的底部开始,,,,向上搜寻一个空表项 向上搜寻一个空表项。。。。
{
chrdevs[major].name = name;
chrdevs[major].fops = fops;
write_unlock(&chrdevs_lock);
return major;
}
}
write_unlock(&chrdevs_lock);
return -EBUSY;
}
  1. 设备注销
    当设备需要撤销时,可以使用注销函数从设备注册表中删除。
int unregister_blkdev(unsigned int major, const char * name) /* 块设备注销函数*/
int unregister_chrdev(unsigned int major, const char * name) /* 字符设备注销函数*/
{
if (strcmp(chrdevs[major].name, name)) return -EINVAL;
chrdevs[major].name = NULL;
chrdevs[major].fops = NULL;
return 0;
}

10.3Linux 的 I/O 控制方式

Linux 对设备的输入、输出过程实际上是在 cpu 的控制下主机(内存)与外部设备之间传送数据的过程。
所以 Linux 的 I/O 控制方式有 3 种:
👉查询等待方式
👉中断方式
👉DMA 方式

10.3.1 查询等待方式((轮询方式 轮询方式)

驱动程序不断检测设备状态,当设备准备好传送数据时,cpu 执行驱动完成一次 I/O 过程,若设备未转备好,则驱动程序反复检测设备状态,直到设备转备好。适用于:不支持设备中断的系统、系统支持的中断数目有限时;例如并行接口(打印机接口)的驱动程序中默认的控制方式就是轮询方式。

10.3.2 中断方式

当进程向设备提出 I/O 请求时并不等待设备完成 I/O 操作,而是把 cpu 让给其它进程使用,自己则进入睡眠状态。在设备完成 I/O 操作时发出中断信号,系统根据中断信号调用相应的中断服务唤醒等待的进程继续执行后面的操作。

在机器硬件支持中断的情况下,设备驱动程序就可以使用中断方式控制设备的 I/O 操作。因此,设备驱动程序中处理包含各种操作函数外,同时还要提供进行各种中断处理的中断服务例程。CPU 接受到来自硬件的中断请求后,则通过中断请求好就能够执行该设备驱动程序的中断服务例程。

  1. 中断服务例程
    👉 中断服务例程描述表:Linux 中,各种中断服务例程是通过中断服务例程描述表进行管理。中断
    服务例程描述表是一个名为 Irq_action 的指针数组,定义如下:
    Static struct irqaction * irq_action[NR_IRQS+1];
    👉中断服务例程描述符:Irqaction 结构体;
    👉机器支持硬件中断源的数目:NR_IRQS;
    👉中断服务例程描述表数组的下标:与中断请求号 IRQ 对应,使用 IRQ 作为索引就可以找到该设备的中断例程描述符。

  2. Irqaction 结构体

Irqaction 结构体定义在/include/linux/interrupte.h 中,如下所示:
Struct irqaction
{
Void(*handler)(int,void*,struct pt_regs*)/*指向中断服务例程*/
Unsigned long flags; /*中断标志*/
Unsigned long mask; /*中断掩码*/
Const char *name; /*设备名*/
Void *dev_id; /*设备号*/
Struct irqaction *next; /*指向下一个描述符:允许多个设备共享一个中断
请求号 IRQ,一个 IRQ 对应的多个中断例程描述符链接成一个单向链表*/
}

在这里插入图片描述

  1. Request_irq()
    在设备驱动程序加载时,通过调用内核函数 Request_irq()建立驱动程序中断例程描述符 irqaction 结构体,并把它登记到 Irq_action 数组中。Request_irq()与硬件相关。在 80x86 机器上 Request_irq()函数定义在arch/i386/kernel/irq.c 中:
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),unsigned long irqflags, const 
char * devname, void *dev_id)
  1. free_irq()
    撤消中断例程时,可以使用函数:
Void free_irq(unsigned int irq, void *dev_id)

把中断例程描述符表中下标为 irq,设备号为 dev_id 占用的表项释放。

10.4Linux 设备 I/O 操作

10.4.1 设备 I/O 操作

  1. 设备文件的建立 设备文件的建立
    调用:mknod (const char *pathname, mode_t mode, dev_t dev)
    终端:mknod /dev/name type major minor
    提供文件名、类型、主设备号 、次设备号

  2. 设备文件的打开 设备文件的打开、关闭

int open(const char *pathname,int flags) /*flag 给出的对文件的处理方式:只读、只写、读写*/
int close(int fd) /*fd 设备的文件标识号*/
  1. 的读写 的读写
int read(int fd,void *buf,int count)
int write(int fd,void *buf,int count)

这篇关于<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 设备管理》(29)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/472876

相关文章

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service