操作系统(Linux Kernel 0.11Linux Kernel 0.12)解读整理——内核初始化(main init)之硬盘初始化

前言

硬盘软盘块设备上数据的读写操作是通过中断处理程序进行的。内核每次读写的数据量以一个逻辑块(1024 字节)为单位,而块设备控制器则是以扇区(512字节)为单位访问块设备。在处理过程中,内核使用了读写请求项等待队列来顺序地缓冲一次读写多个逻辑块的操作。

        具体的,当一个程序需要读取硬盘上的一个逻辑块时,就会向缓冲区管理程序提出申请。而请求读写的程序进程则进入睡眠等待状态。缓冲区管理程序首先在缓冲区中寻找以前是否已经读取过这块数据。如果缓冲区中已经有了,就直接将对应的缓冲区块头指针返回给程序并唤醒等待的进程。若缓冲区中还不存在所要求的数据块,则缓冲管理程序就会调用低级块读写函数 ll_rw_block(),向相应的块设备驱动程序发出一个读数据块的操作请求。该函数会为此创建一个请求结构项,并插入请求队列中。为了提高读写磁盘的效率,减小磁头移动的距离,内核代码在把请求项插入请求队列时,会使用电梯算法将请求项插入到磁头移动距离最小的请求队列位置处。(关于缓冲区概念及交互过程块设备操作请求过程将在后续另起文章介绍)
        若此时对应块设备的请求项队列为空,则表明此刻该块设备不忙。于是内核就会立刻向该块设备的控制器发出读数据命令。当块设备的控制器将数据读入到指定的缓冲块后,就会发出中断请求信号,并调用相应的读命令后处理函数,处理继续读扇区操作或者结束本次请求项的过程。例如对相应块设备进行关闭操作和设置该缓冲块数据已经更新标志,最后唤醒等待该块数据的进程。

        各种关于硬盘或者其他块设备的操作都离不开对关键数据结构的定义与初始化,本篇将简要地解读整理内核v0.11关于硬盘的初始化。

硬盘初始化 hd_init()

不外乎就是往某些 IO 端口上读写一些数据,表示开启它;然后再向中断向量表中添加一个中断,使得 CPU 能够响应这个硬件设备的动作;最后再初始化一些数据结构来管理。

void main(void) {
    ...
    hd_init(); 
    ...
}

//struct blk_dev_struct {
//    void (*request_fn)(void);
//    struct request * current_request;
//};
//extern struct blk_dev_struct blk_dev[NR_BLK_DEV];

void hd_init(void) {
    blk_dev[3].request_fn = do_hd_request;
    set_intr_gate(0x2E,&hd_interrupt);
    outb_p(inb_p(0x21)&0xfb,0x21);
    outb(inb_p(0xA1)&0xbf,0xA1); 
}

因为有很多块设备,所以 Linux 0.11 内核用了一个 blk_dev[] 来进行管理,每一个索引表示一个块设备

struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
    { NULL, NULL },     /* no_dev */
    { NULL, NULL },     /* dev mem */
    { NULL, NULL },     /* dev fd */
    { NULL, NULL },     /* dev hd */
    { NULL, NULL },     /* dev ttyx */
    { NULL, NULL },     /* dev tty */
    { NULL, NULL }      /* dev lp */
};

索引为 3 这个位置,就表示给硬盘 hd 这个块设备留的位置。并且每个块设备执行读写请求都有自己的函数实现,在上层看来都是一个统一函数 request_fn 接口,具体实现各有不同,对于硬盘来说,这个实现就是 do_hd_request 函数。

(这其实就是多态思想在 C 语言的体现。用C++熟悉的话就是,抽象基类接口指针 request_fn 指向派生类对象具体方法 do_hd_request 的感觉。)

接着又设置了一个新的中断,中断号是 0x2E,中断处理函数是 hd_interrupt,也即硬盘发生读写时,硬盘会发出中断信号给 CPU,之后 CPU 便会陷入中断处理程序,即执行 hd_interrupt 函数。

(tips:赵炯的内核注释书中是这样描述的:当硬盘操作完成或出错会发出此中断信号。)

_hd_interrupt:
    ...
    xchgl _do_hd,%edx
    ...
    
// 如果是读盘操作,这个 do_hd 是 read_intr
static void read_intr(void) {
    ...
    do_hd_request();
    ...
}

(操作系统就是一个靠中断驱动的死循环而已,如果不发生任何中断,操作系统会一直在一个死循环里等待。换句话说,让操作系统工作的唯一方式,就是触发中断。)

最后就是往几个 IO 端口上读写,其作用是允许硬盘控制器发送中断请求信号

硬盘的端口表如下:

所谓读硬盘,就是往除了第一个以外的后面几个端口写数据,告诉要读硬盘的哪个扇区,读多少。然后再从 0x1F0 端口一个字节一个字节的读数据,这就完成了一次硬盘读操作。

例如:

1. 在 0x1F2 写入要读取的扇区数

2. 在 0x1F3 ~ 0x1F6 这四个端口写入计算好的起始 LBA 地址

3. 在 0x1F7 处写入读命令的指令号

4. 不断检测 0x1F7 (此时已成为状态寄存器的含义)的忙位

5. 如果第四步骤为不忙,则开始不断从 0x1F0 处读取数据到内存指定位置,直到读完

操作系统中读写端口的核心如下:

static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
        unsigned int head,unsigned int cyl,unsigned int cmd,
        void (*intr_addr)(void)) {
    ...
    do_hd = intr_addr;
    outb_p(hd_info[drive].ctl,HD_CMD);
    port = 0x1f0;
    outb_p(hd_info[drive].wpcom>>2,++port);
    outb_p(nsect,++port);
    outb_p(sect,++port);
    outb_p(cyl,++port);
    outb_p(cyl>>8,++port);
    outb_p(0xA0|(drive<<4)|head,++port);
    outb(cmd,++port);
}

outb_p 方法,转换成汇编语言,就是 out 指令,往指定的硬盘 IO 端口上写数据,达到读或者写的目的。

由用户层写的各种 read / write 函数,即便是经过系统调用、文件系统、缓冲区管理等等过程,但只要是读写硬盘,最终都要调用到这个最底层的函数,殊途同归!

hd.c 中有很多读写硬盘的方法,这个在之后文件系统会使用到,将另外整理一篇进行展开!!!

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

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

相关文章

利用机器学习创建基于位置的推荐程序

推荐系统被广泛应用于不同的应用程序中&#xff0c;用于预测用户对产品或服务的偏好或评价。在过去的几分钟或几小时里&#xff0c;你很可能在网上遇到过或与某种类型的推荐系统进行过互动。这些推荐系统有不同的类型&#xff0c;其中最突出的包括基于内容的过滤和协作过滤。在…

【AI论文】Video-MMMU:评估从多学科专业视频中获取知识的能力

摘要&#xff1a;人类通过三个认知阶段获取知识&#xff1a;感知信息、理解知识以及运用知识解决新问题。视频作为这一学习过程的有效媒介&#xff0c;促进了这些认知阶段的逐步推进。然而&#xff0c;现有的视频基准测试未能系统地评估大型多模态模型&#xff08;LMMs&#xf…

【C++高并发服务器WebServer】-9:多线程开发

本文目录 一、线程概述1.1 线程和进程的区别1.2 线程之间共享和非共享资源1.3 NPTL 二、线程操作2.1 pthread_create2.2 pthread_exit2.3 pthread_join2.4 pthread_detach2.5 patch_cancel2.6 pthread_attr 三、实战demo四、线程同步五、死锁六、读写锁七、生产消费者模型 一、…

C语言学习强化

前言 数据的逻辑结构包括&#xff1a; 常见数据结构&#xff1a; 线性结构&#xff1a;数组、链表、队列、栈 树形结构&#xff1a;树、堆 图形结构&#xff1a;图 一、链表 链表是物理位置不连续&#xff0c;逻辑位置连续 链表的特点&#xff1a; 1.链表没有固定的长度…

【C++探索之路】STL---string

走进C的世界&#xff0c;也意味着我们对编程世界的认知达到另一个维度&#xff0c;如果你学习过C语言&#xff0c;那你绝对会有不一般的收获&#xff0c;感受到C所带来的码云风暴~ ---------------------------------------begin--------------------------------------- 什么是…

【WebRTC - STUN/TURN服务 - COTURN配置】

在WebRTC中&#xff0c;对于通信的两端不在同一个局域网的情况下&#xff0c;通信两端往往无法P2P直接连接&#xff0c;需要一个TURN中继服务&#xff0c;而中继服务可以选用 COTURN 构建。 注&#xff1a;COTURN 是一个开源的 TURN&#xff08;Traversal Using Relays around…

React 前端框架实战教程

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 React 是由 Facebook 开发的前端 JavaScript 库&#xff0c;旨在构建高效、灵活的用户界面&#xff0c;尤其适用于单页应用…

MiniMax-01中Lightning Attention的由来(线性注意力进化史)

目录 引言原始注意力线性注意力因果模型存在的问题累加求和操作的限制Lightning AttentionLightning Attention-1Lightning Attention-2 备注 引言 MiniMax-01: Scaling Foundation Models with Lightning Attention表明自己是第一个将线性注意力应用到如此大规模的模型&#…

互联网医院成品|互联网医院软件源码

互联网医院系统带来的好处是显而易见的&#xff0c;其通过先进的互联网技术为医疗行业带来了巨大的变革。以下将从多个方面详细阐述其带来的益处。 一、便捷的医疗服务 互联网医院系统为患者提供了更为便捷的医疗服务。患者无需再亲自前往医院&#xff0c;只需通过电脑、手机等…

unity学习20:time相关基础 Time.time 和 Time.deltaTime

目录 1 unity里的几种基本时间 1.1 time 相关测试脚本 1.2 游戏开始到现在所用的时间 Time.time 1.3 时间缩放值 Time.timeScale 1.4 固定时间间隔 Time.fixedDeltaTime 1.5 两次响应时间之间的间隔&#xff1a;Time.deltaTime 1.6 对应测试代码 1.7 需要关注的2个基本…

Centos7系统php8编译安装ImageMagick/Imagick扩展教程整理

Centos7系统php8编译安装ImageMagick/Imagick扩展教程整理 安装php8安装ImageMagick1、下载ImageMagick2、解压并安装3、查看是否安装成功 安装imagick扩展包 安装php8 点我安装php8 安装ImageMagick 1、下载ImageMagick wget https://www.imagemagick.org/download/ImageMa…

RabbitMQ模块新增消息转换器

文章目录 1.目录结构2.代码1.pom.xml 排除logging2.RabbitMQConfig.java3.RabbitMQAutoConfiguration.java 1.目录结构 2.代码 1.pom.xml 排除logging <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/PO…

Linux——网络基础(1)

文章目录 目录 文章目录 前言 一、文件传输协议 应用层 传输层 网络层 数据链路层 数据接收与解封装 主机与网卡 数据传输过程示意 二、IP和MAC地址 定义与性质 地址格式 分配方式 作用范围 可见性与可获取性 生活例子 定义 用途 特点 联系 四、TCP和UDP协…

SpringBoot+Electron教务管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.查询课程表代码2.保存学生信息代码3.用户登录代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootElectron框架开发的教务管理系统。首先&#xff…

有限元分析学习——Anasys Workbanch第一阶段笔记(15)接触间隙处理与赫兹接触

目录 0 序言 1 接触的间隙处理 1.1 结果对比 1.2 处理方法 2 赫兹接触 0 序言 本章主要介绍间隙出现时的三种解决方法&#xff0c;齿轮点蚀/表面剥落涉及的赫兹接触的一些理论知识。 1 接触的间隙处理 在实际产品过程中&#xff0c;很多时候由于设计问题&#xff0c;原本…

go单元测试和基准测试

1、单元测试和基准测试 单元测试和基准测试代码开发中的重要环节&#xff0c;良好的单元测试和基准测试&#xff0c;能提升开发质量&#xff0c;对整体开发有非常重要的重要&#xff0c;下面介绍单元测试和基准测试的写法。 2、单元测试和基准测试写法 以排序基本排序算法&a…

自由窗口边框阴影描绘方案汇总-社群讨论学习

背景&#xff1a; 针对很多厂商的自由窗口都有内外阴影效果&#xff0c;针对这样一个需求其实不仔细看可能都看不出来&#xff0c;不过确实也是存在的这种阴影&#xff0c;这里我搞个明显一些的给大家看看&#xff1a; 针对这样一个需求&#xff0c;在我们vip学员群里进行了相…

应用层协议 HTTP 讲解实战:从0实现HTTP 服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; HTTP 协议 &#x1f98b; 认识 URL&#x1f98b; urlencode 和 urldecode 二&#xff1a;&#x1f525; HTTP 协议请求与响应格式 &#x1f98b; HTTP 请求…

深入剖析 Adam 优化器:原理、优势与应用

在深度学习领域&#xff0c;优化器的选择对模型的训练效率和性能起着决定性作用。Adam优化器作为一种自适应优化算法&#xff0c;凭借其根据历史梯度信息动态调整学习率的特性&#xff0c;备受研究者和工程师的青睐。它巧妙融合了RMSProp和Momentum两种优化算法的理念&#xff…

ppp综合实验

IP地址 r1 r2 r3 r4 hdlc封装 pap认证 r2 r3 chap认证 r2 r4 MGRE 主认证 [r1]int Tunnel 0/0/0 [r1-Tunnel0/0/0]ip add 192.168.4.1 24 [r1-Tunnel0/0/0]tunnel-protocol gre p2mp [r1-Tunnel0/0/0]source 12.1.1.1 [r1-Tunnel0/0/0]nhrp entry multicast dynamic [r1-Tu…