当前位置: 首页 > news >正文

操作系统 4.3-生磁盘的使用

磁盘的物理组成

  1. 盘面

    • 磁盘由多个盘面组成,每个盘面上都有数据存储的区域。

  2. 磁道

    • 每个盘面上都有若干个同心圆,这些同心圆称为磁道。磁道是数据存储的路径。

  3. 扇区

    • 磁道被进一步划分为若干个扇区,扇区是磁盘的最小访问单位。

    • 扇区大小通常为512字节。

磁盘的io流程

该幻灯片描述了磁盘的输入/输出(I/O)过程,具体步骤如下:

  1. 开始使用磁盘

    • 首先,系统需要通过IDE控制器与磁盘建立连接,开始磁盘的I/O操作。

  2. 磁盘I/O过程

    • 磁盘的I/O过程包括以下几个步骤:控制器、寻道、旋转、传输。

  3. 寻道

    • 控制器发送指令,使磁头移动到正确的磁道上。这是为了定位到数据所在的物理位置。

  4. 旋转

    • 磁盘旋转,使得目标扇区移动到磁头下方。这个过程需要等待磁盘旋转到正确的位置,可能会有一定的延迟。

  5. 传输

    • 一旦目标扇区位于磁头下方,数据就可以从磁盘读取到内存中,或者从内存写入到磁盘中。

  6. 内存缓存

    • 读取或写入的数据首先会进入内存缓存。对于读取操作,数据从磁盘读出后存储在内存缓存中;对于写操作,数据首先写入内存缓存,然后再从缓存写入磁盘。

使用磁盘

柱面(Cylinder)

柱面是磁盘上所有盘面中具有相同径向位置的磁道的集合。

当计算机需要读取或写入数据时,它会根据柱面号、磁头号和扇区号来确定目标数据的位置。

通过控制磁头的移动和盘片的旋转,计算机可以准确地定位到特定柱面上的特定扇区,进行数据的读写操作。

磁头(Head)

每个盘面对应一个磁头

所有的磁头都是连在同一个磁臂上的,因此所有磁头只能“共进退”。

每个磁头上都有读和写的操作装置,用于读取和写入数据。

磁头臂是支持磁头的可移动臂,通过电动机或电磁力控制,可以使磁头在盘片上移动到不同的磁道位置。

扇区(Sector)

每个盘片被划分为一个个磁道,每个磁道又划分为一个个扇区。

扇区是磁盘的最小访问单位,通常为512字节。

在读取或写入数据时,磁头需要准确地定位到相应的扇区。磁盘驱动器在向磁盘读取和写入数据时,要以扇区为单位。

代码分析

从提供的幻灯片内容中,我们可以提取出两个函数的代码,它们是 do_hd_request hd_out。以下是提取的代码和总结:

提取的代码

void do_hd_request(void) {
    ...hd_out(dev, nsect, sec, head, cyl, WIN_WRITE, ...); // 调用hd_out函数
    port_write(HD_DATA, CURRENT->buffer, 256); // 将数据写入硬盘
}
​
void hd_out(drive, nsect, sec, head, cyl, cmd...) {
    port = HD_DATA; // 数据寄存器端口(0x1f0)
    outb_p(nsect, ++port); // 输出扇区数
    outb_p(sec, ++port);   // 输出起始扇区号
    outb_p(cyl, ++port);   // 输出柱面号
    outb_p(cyl >> 8, ++port); // 输出柱面号的高字节
    outb_p(0xA0 | (drive << 4) | head, ++port); // 输出驱动器和磁头信息
    outb_p(cmd, ++port); // 输出命令
}

代码总结

  1. do_hd_request 函数

    • 这个函数处理硬盘的I/O请求。

    • 它调用 hd_out 函数来设置硬盘控制器的参数,包括设备号(dev)、扇区数(nsect)、扇区号(sec)、磁头号(head)、柱面号(cyl)等。

    • 然后,它使用 port_write 函数将数据从内存缓冲区(CURRENT->buffer)写入硬盘,这里写入的数据量为256字节。

  2. hd_out 函数

    • 这个函数负责将控制命令和参数输出到硬盘控制器。

    • 它首先设置数据寄存器端口(HD_DATA)。

    • 然后,它使用 outb_p 函数依次输出扇区数、扇区号、柱面号、柱面号的高字节、驱动器和磁头信息以及命令。

    • 这些参数用于控制硬盘的读写操作,例如移动磁头到指定的柱面和磁头位置,然后读取或写入指定的扇区。

这些代码是磁盘驱动程序的核心部分,它们实现了操作系统与硬盘硬件之间的直接交互,是文件系统和数据存储管理的基础。

如何通过盘块号读写磁盘

盘块

盘块(Block)是文件系统中用于数据存储和管理的一个逻辑概念,它是文件系统中数据存储的基本单位。盘块是逻辑上的划分,不同于磁盘物理结构中的扇区(Sector)、柱面(Cylinder)和磁头(Head)等概念。以下是盘块的详细解释:

  1. 盘块号

    • 每个盘块都有一个唯一的标识符,称为盘块号(Block Number)。盘块号用于在文件系统中定位和访问特定的盘块。

  2. 盘块与扇区的关系

    • 盘块通常由一个或多个扇区组成。一个扇区是磁盘上最小的物理存储单位,通常大小为512字节。

    • 文件系统将一个或多个连续的扇区组合成一个盘块,以提高数据管理的效率。

  3. 盘块的分配

    • 文件系统使用盘块分配表(Block Allocation Table, BAT)或inode(索引节点)等数据结构来记录每个文件占用的盘块信息。

    • 当文件被创建或修改时,文件系统会分配新的盘块或更新现有文件的盘块信息。

  4. 盘块的优缺点

    • 优点:简化了文件数据的管理,提高了数据存储和检索的效率。

    • 缺点:如果文件大小不是盘块大小的整数倍,最后一个盘块可能会有未使用的空间,导致一定的空间浪费。就是用空间换时间

为什么使用盘块

  1. 磁盘访问时间的组成

    • 磁盘访问时间包括写入控制器时间、寻道时间、旋转时间和传输时间。

    • 寻道时间:磁头移动到目标磁道的时间,通常在12毫秒到8毫秒之间。

    • 旋转时间:磁盘旋转到目标扇区的时间,对于7200转/分钟的硬盘,半周大约需要4毫秒。

    • 传输时间:数据从磁盘传输到内存的时间,大约0.3毫秒(50MB/秒)。

  2. 盘块相邻的优势

    • 相邻的盘块在物理位置上接近,因此可以快速连续读出,减少了寻道时间和旋转时间,提高了磁盘访问效率

优点分析

  • 提高效率:通过减少寻道时间和旋转时间,提高了磁盘访问的速度,从而提高了整体的系统性能。

  • 抽象层次:操作系统通过提供这一层抽象,隐藏了磁盘的物理访问细节,使得上层应用程序可以更加方便地使用磁盘资源。

如何编址?为什么这样编址?

  • 如何编址:磁盘驱动通过算法将盘块号映射到CHS地址。这通常涉及到磁盘的几何结构和盘块的布局。

  • 为什么这样编址:这种编址方式是为了优化磁盘访问效率。通过将相邻的盘块放在磁盘上的相邻位置,可以减少寻道时间和旋转时间,从而提高数据访问速度。

扇区号的获得

从CHS到扇区号

  • CHS地址转换:磁盘的物理地址通常由柱面号(Cylinder)、磁头号(Head)和扇区号(Sector)组成。幻灯片中提到的公式 Cx(HeadsxSectors) + HxSectors + S 用于计算从CHS地址到扇区号的转换。

    • C:柱面号

    • Heads:磁盘上的磁头数

    • Sectors:每个磁道上的扇区数

    • H:磁头号

    • S:扇区号

磁盘请求的创建和处理过程

从提供的幻灯片内容中,我们可以提取出两个函数的代码,它们是 make_request do_hd_request。以下是提取的代码和分析:

提取的代码

// 创建一个磁盘请求
static void make_request()
{
    struct request *req;
    req = request + NR_REQUEST;
    req->sector = bh->b_blocknr << 1;
    add_request(major + blk_dev, req);
}
​
// 处理硬盘请求
void do_hd_request(void)
{
    unsigned int block = CURRENT->sector;
    asm volatile (
        "divl %4, %%eax;"    // block / sect (每个磁头的扇区数)
        "=a" (block),        // 输入:eax = 被除数
        "=d" (sec),          // 输出:edx = 余数(扇区号)
        "0" (block),         // 输入:eax = 被除数
        "1" (0),             // 输入:edx = 0(初始化为0)
        "r" (hd_info[dev].sect) // 输入:ecx = 除数(每个磁头的扇区数)
    );
    asm volatile (
        "divl %4, %%eax;"    // (block / sect) / head (磁头数)
        "=a" (cyl),          // 输出:eax = 商(柱面号)
        "=d" (head),         // 输出:edx = 余数(磁头号)
        "0" (block),         // 输入:eax = 被除数
        "1" (0),             // 输入:edx = 0(初始化为0)
        "r" (hd_info[dev].head) // 输入:ecx = 除数(磁头数)
    );
    hd_out(dev, nsect, sec, head, cyl, WIN_WRITE, ...);
    ...
}

代码分析

  1. make_request 函数

    • 这个函数用于创建一个新的磁盘请求

    • 它分配一个新的请求结构体 req,并设置请求的扇区号 req->sector

    • bh->b_blocknr << 1:将块号左移一位,为了将块号转换为扇区号(假设每个块由两个扇区组成)。

    • add_request:将新创建的请求添加到请求队列中。

  2. do_hd_request 函数

    • 这个函数处理硬盘请求,将盘块号转换为CHS地址,并调用 hd_out 函数执行实际的磁盘操作。

    • CURRENT->sector:获取当前请求的扇区号。

    • 使用内联汇编(asm volatile)进行除法运算,将扇区号转换为柱面号(cyl)、磁头号(head)和扇区号(sec)。

      • 第一个除法运算计算扇区号(sec)。

      • 第二个除法运算计算柱面号(cyl)和磁头号(head)。

    • hd_out:执行实际的磁盘操作,包括寻道、旋转和数据传输。

总结

这段代码展示了Linux 0.11内核中磁盘请求的创建和处理过程。make_request 函数负责创建新的磁盘请求,而 do_hd_request 函数负责将盘块号转换为CHS地址,并执行实际的磁盘操作。

通过内联汇编进行除法运算,实现了从盘块号到CHS地址的转换,这是磁盘驱动程序中的关键步骤。

多个进程使用磁盘

多进程通过队列使用磁盘

  1. 请求队列

    • 当多个进程需要访问磁盘时,它们的请求被放入一个请求队列中。这个队列管理所有磁盘访问请求,确保它们有序地被处理。

  2. 磁盘驱动

    • 磁盘驱动负责从请求队列中取出请求,并将其转换为磁盘控制器可以理解的CHS(柱面、磁头、扇区)地址。

  3. 磁盘控制器

    • 磁盘控制器根据磁盘驱动提供的CHS地址执行实际的磁盘操作,如寻道、旋转和数据传输。

磁盘调度

  1. 调度目标

    • 磁盘调度的主要目标是最小化平均访问延迟。这意味着调度算法需要尽可能减少磁盘访问请求的等待时间。

  2. 调度时主要考察的因素

    • 寻道时间:磁头移动到目标磁道的时间,这是磁盘访问时间中的主要部分。

    • 旋转时间:磁盘旋转到目标扇区的时间。

    • 传输时间:数据从磁盘传输到内存的时间。

  3. 调度算法

    • FCFS(First-Come, First-Served):最简单的调度算法,按照请求到达的顺序处理。虽然公平,但可能不是最高效的,因为它不考虑磁头的当前位置或请求的物理位置。

    • 更复杂的算法:如SSTF(Shortest Seek Time First)、SCAN(Elevator Algorithm)等,这些算法试图通过优化磁头移动路径来减少寻道时间,从而提高整体性能。

FCFS

  1. 最直观、最公平的调度

    • FCFS算法按照请求到达的顺序处理,确保每个请求都能被公平地处理。

  2. 实例分析

    • 磁头开始位置为53。

    • 请求队列为:98, 183, 37, 122, 14, 124, 65, 67。

  3. 磁头移动

    • FCFS算法导致磁头共移动了640个磁道。

    • 磁头在移动过程中处理了经过的请求。

  4. 磁头在长途奔袭

    • 图中显示了磁头在处理请求时的移动路径,磁头需要在磁盘上进行大量的移动,这可能导致效率低下。

  5. 效率问题

    • FCFS算法虽然公平,但可能导致磁头在磁盘上进行大量的寻道操作,增加了寻道时间和旋转时间,从而降低了磁盘的整体性能。

SSTF

SSTF(Shortest Seek Time First,最短寻道时间优先)磁盘调度算法。SSTF算法是一种优化磁盘访问时间的算法,它选择距离当前磁头位置最近的请求进行处理,以减少磁头移动的距离。以下是对幻灯片内容的分析:

  1. 算法原理

    • SSTF算法选择距离当前磁头位置最近的请求进行处理,以减少寻道时间。

    • 这种方法可以显著减少磁头移动的总距离,从而提高磁盘访问效率。

  2. 实例分析

    • 磁头开始位置为53。

    • 请求队列为:98, 183, 37, 122, 14, 124, 65, 67。

  3. 磁头移动

    • 在这个实例中,SSTF算法导致磁头共移动了236个磁道(4+53+169)。

    • 相比FCFS算法的640个磁道,SSTF算法显著减少了磁头移动的距离。

  4. 效率提升

    • 通过优先处理距离当前磁头位置最近的请求,SSTF算法可以更快地响应请求,减少等待时间。

  5. 饥饿问题

    • SSTF算法存在饥饿问题,即远离当前磁头位置的请求可能会长时间得不到处理。

    • 如果在处理183号请求之前,又来了一些中间磁道的请求,那么183号请求可能会被推迟处理,导致延迟。

SCAN

SCAN磁盘调度算法,也称为电梯算法,它是一种常见的磁盘调度策略,旨在优化磁盘的寻道操作,减少寻道时间。

  1. 算法原理

    • SCAN算法模拟电梯的运行方式,磁头从一个方向开始移动,直到达到最后一个请求,然后改变方向,继续处理另一方向的请求。

    • 这种算法确保每个请求最终都会被处理,避免了SSTF算法中可能出现的饥饿问题。

  2. 实例分析

    • 磁头开始位置为53。

    • 请求队列为:98, 183, 37, 122, 14, 124, 65, 67。

  3. 磁头移动

    • 在这个实例中,SCAN算法导致磁头共移动了236个磁道(53+183)。

    • 与SSTF算法相比,SCAN算法在处理请求时更加公平,因为它确保了磁头会遍历所有请求。

  4. 公平性

    • SCAN算法通过确保每个方向上的请求都被处理,提高了算法的公平性。

  5. 效率

    • SCAN算法通过减少磁头的来回移动,提高了磁盘访问的效率。

    • 与SSTF相比,SCAN算法在处理大量随机分布的请求时,通常能提供更好的性能。

C-SCAN

这张幻灯片介绍了C-SCAN(Circular SCAN)磁盘调度算法,这是一种类似于电梯算法的磁盘调度策略,但在到达一端后直接移动到另一端,而不是改变方向。以下是对幻灯片内容的分析和总结:

  1. 算法原理

    • C-SCAN算法从磁头的当前位置开始,向一个方向移动,处理所有请求,到达磁盘的一端后,直接移动到另一端,然后继续处理请求。

    • 这种算法确保了两端的请求都能被快速处理。

  2. 实例分析

    • 磁头开始位置为53。

    • 请求队列为:98, 183, 37, 122, 14, 124, 65, 67。

  3. 磁头移动

    • 在这个实例中,C-SCAN算法导致磁头共移动了157+200个磁道。

    • 其中200个磁道是磁头从一端移动到另一端的距离,这个过程很快,因为它是连续的,没有寻道时间。

  4. 效率

    • C-SCAN算法通过直接从一端移动到另一端,减少了磁头的寻道时间,提高了磁盘访问的效率。

    • 这种算法特别适合于请求分布均匀的情况,因为它可以确保所有请求都能被快速处理。

  5. 公平性

    • C-SCAN算法在处理请求时,可能会对靠近磁头起始位置的请求提供更快的服务,而对远离起始位置的请求提供较慢的服务。

代码实现

从提供的幻灯片内容中,我们可以提取出两个函数的代码:make_request add_request,以及一个宏定义 IN_ORDER。以下是提取的代码和总结:

提取的代码

// 创建一个磁盘请求
static void make_request()
{
    struct request *req;
    req->sector = bh->b_blocknr << 1;
    add_request(major + blk_dev, req);
}
​
// 将请求添加到请求队列
static void add_request(struct blk_dev_struct *dev, struct request *req)
{
    struct request *tmp = dev->current_request;
    req->next = NULL;
    cli(); // 关中断(互斥)
    for (; tmp->next; tmp = tmp->next)
        if (IN_ORDER(tmp, req) || !IN_ORDER(tmp, tmp->next))
            && IN_ORDER(req, tmp->next)) break;
    req->next = tmp->next; 
    tmp->next = req; 
    sti();
}
​
// 判断请求是否有序
#define IN_ORDER(s1, s2) \
    ((s1)->dev < (s2)->dev || \
    ((s1)->dev == (s2)->dev && (s1)->sector < (s2)->sector))

代码总结

  1. make_request 函数

    • 这个函数初始化一个新的磁盘请求,设置请求的扇区号 req->sector,并将请求添加到磁盘请求队列中。

    • bh->b_blocknr << 1:假设每个块由两个扇区组成,因此将块号左移一位来计算扇区号。

  2. add_request 函数

    • 这个函数将一个新的请求插入到磁盘请求队列中,保持队列的有序性。

    • 使用 cli() 关闭中断来确保在操作请求队列时的互斥访问。

    • 通过 IN_ORDER 宏判断请求是否有序,如果新请求应该插入到 tmptmp->next 之间,则进行插入。

    • 使用 sti() 重新开启中断。

  3. IN_ORDER

    • 这个宏用于判断两个请求是否有序,即是否按照设备号和扇区号的顺序排列。

    • 如果第一个请求的设备号小于第二个请求的设备号,或者设备号相同但扇区号小于第二个请求的扇区号,则认为有序。

总结如何使用生磁盘

这张幻灯片介绍了操作系统中生磁盘(raw disk)的使用流程,以及如何通过磁盘驱动程序来管理多个进程对磁盘的访问。

  1. 进程获取盘块号

    • 进程首先需要获取到要访问的盘块号(block number)。

  2. 计算扇区号

    • 根据盘块号计算出对应的扇区号(sector number)。这通常涉及到将盘块号映射到磁盘的物理地址。

  3. 创建请求并加入请求队列

    • 使用计算出的扇区号创建一个磁盘请求(make req)。

    • 将该请求加入到请求队列中(add_request),可能使用电梯算法(SCAN算法)来优化请求的处理顺序。

  4. 进程等待

    • 进程在发起磁盘请求后进入等待状态(sleep_on)。

  5. 磁盘中断处理

    • 当磁盘操作完成时,磁盘控制器会产生一个中断信号。

    • 中断处理程序(read_intr)被触发,唤醒等待的进程。

  6. 执行磁盘请求

    • 磁盘驱动程序处理请求(do_hd_request),计算出具体的柱面(cylinder)、磁头(head)和扇区号(sector)。

  7. 端口写入

    • 使用端口写入操作(hd_out),通过outp函数将数据写入磁盘控制器的端口,完成数据的实际读写操作。

相关文章:

  • 种田游戏的综合尝试
  • IBM Rational Software Architect安装感受及使用初体验
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(2):んです
  • 【ESP32S3】GATT Server service table传送数据到调试助手
  • 2025.04.05 广东汕尾两日游记
  • DNS正反向解析复习,DNS主从服务,转发服务及DNS和nginx联合案例(不断更新)
  • BERT-DDP
  • Google ADK(Agent Development Kit)简要示例说明
  • 凌科加密芯片LKT4304在充电桩上的应用
  • 【LeetCode 题解】算法:36.有效的数独
  • C++20新特性:协程
  • 一文解析2025年移动游戏用户获取策略 | 增长方法论
  • 【CF】Day30——Codeforces Round 824 (Div. 2) C + Codeforces Round 825 (Div. 2) BC1
  • 数字内容体验的核心价值是什么?
  • 【前后端】npm包mysql2的使用__nodejs mysql包升级版
  • 四、TorchRec的推理优化
  • RAG(检索增强生成)系统,提示词(Prompt)表现测试(数据说话)
  • 如何在AMD MI300X 服务器上部署 DeepSeek R1模型?
  • c++关键字new
  • CExercise_07_1指针和数组_2数组元素的逆序数组逆序(指针版 reverse_by_ptr 和下标版 reverse_arr)
  • 吉林电商网站建设公司哪家好/青岛网站建设公司哪家好
  • 长沙网络营销首选智投未来/河北seo网络优化师
  • 做360网站中保存的图片存在哪里的/搜索引擎在线
  • 淮北做网站的公司有哪些/班级优化大师官网
  • 小型便利店装修设计/安卓优化大师旧版
  • 学做网站先学什么/百度总部投诉电话