应用程序读取磁盘的数据流程

  • 应用程序请求文件读取: 用户态的应用程序发起文件读取请求,通常是通过标准的文件操作函数(例如,在Linux中是 read(),在Windows中是 ReadFile())

  • 系统调用: 操作系统内核接收到应用程序的读取请求,这将触发一个系统调用(system call)。系统调用是用户态和内核态之间的通信机制,用于执行操作系统内核中的特定功能

  • 内核态处理: 操作系统内核根据请求打开相应的文件,确定要读取的数据位置等,并准备好数据进行读取。这一过程通常发生在内核态

  • 磁盘读取: 操作系统内核通过设备驱动程序或文件系统模块与硬盘或存储设备进行通信,以从磁盘中读取请求的数据块

  • 数据加载到内核缓冲区: 读取的数据通常会被加载到内核缓冲区(kernel buffer)中,这是内核维护的一块内存区域

  • 数据复制到用户态缓冲区: 一旦数据被加载到内核缓冲区中,内核将执行一个额外的操作,将数据从内核缓冲区复制到用户态缓冲区(user buffer),这是应用程序所拥有的内存区域

  • 系统调用返回: 当数据成功复制到用户态缓冲区后,系统调用返回到用户态,通知应用程序已经完成读取操作

  • 应用程序使用数据: 应用程序处理从磁盘读取的数据


调用read()函数读取硬盘数据到用户空间:

  • 调用read()函数,用户态进程发起系统调用,请求读取硬盘数据到用户空间,通过软中断或陷阱机制,CPU由用户态切换到内核态
  • 内核分配一块内核缓冲区PageCache,CPU向DMA控制器发起请求
  • DMA控制器被触发,将硬盘数据拷贝到内核缓冲区PageCache
  • DMA控制器向CPU发起请求,CPU将内核缓冲区PageCache的数据拷贝到用户空间的缓冲区
  • read函数结束后,内核将CPU由内核态切换到用户态,继续执行被中断的用户态进程

调用write()函数将用户空间数据写入到网卡中

  • 调用write()函数,用户态进程发起系统调用,请求将用户空间数据写入网卡,CPU由用户态切换到内核态
  • 内核分配一块内核缓冲区PageCache,CPU将用户空间的数据拷贝到Socket缓冲区,CPU向DMA控制器发起请求
  • DMA控制器被触发,DMA控制器将Socket缓冲区的数据拷贝的网卡中
  • 最好,DMA控制器发出数据写完信号,write结束,CPU由内核态切换到用户态

进程中有页表数据结构指向用户空间和内核空间,使用户态和内核态访问内存空间不同
(待改)


数据传输流程的伪代码
CPU主导的数据传输流程伪代码
# 假设场景:从外设读取512字节数据到内存地址0x1000
# 外设 ——> CPU ——> 内存

# ------------------------
# 1. 初始化参数
# ------------------------
source_address = 0x1F0        # 外设I/O端口地址(假设为IDE磁盘控制器)
destination_address = 0x1000  # 目标内存地址
data_length = 512             # 传输字节数
current_position = 0          # 当前传输位置

# ------------------------
# 2. cpu轮询外设状态,CPU持续读取外设状态寄存器,直到数据就绪; 另一种数据备注完成的方式是外设通过中断主动通知CPU,CPU暂停当前任务,执行中断服务程序处理数据,完成后恢复原任务
# ------------------------
def wait_for_device_ready():
    while True:
        # 读取外设状态寄存器(假设状态端口为0x1F7)
        status = read_io_port(0x1F7)
        # 检查"数据就绪"标志位(假设第3位为就绪位)
        if (status & 0x08) != 0:
            break

# ------------------------
# 3. 逐字节传输数据,CPU通过IN指令从外设读数据到寄存器,再通过MOV指令写入内存
# ------------------------
def cpu_transfer():
    global current_position
    while current_position < data_length:
        # 从外设读取1字节数据到CPU寄存器
        data_byte = read_io_port(source_address)
        
        # 将数据从寄存器写入内存
        write_memory(destination_address + current_position, data_byte)
        
        current_position += 1

# ------------------------
# 4. 主流程
# ------------------------
# 步骤1:等待外设准备就绪
wait_for_device_ready()

# 步骤2:执行CPU驱动的数据传输
cpu_transfer()

# 步骤3: 触发磁盘中断,标记传输完成
set_interrupt_flag(IRQ_DISK)  
DMA主导的数据传输流程伪代码
# DMA传输伪代码
def dma_transfer():
    # 配置DMA控制器
    set_dma_source(source_address)
    set_dma_destination(destination_address)
    set_dma_length(data_length)
    
    # 启动DMA,数据以块(Block)为单位在外设和内存之间传输,并等待完成
    start_dma()
    while not dma_complete():
        cpu_do_other_tasks()  # CPU可执行其他任务

    # 处理完成中断
    handle_dma_interrupt()
posted @ 2023-09-24 19:33  jishaleng  阅读(384)  评论(0)    收藏  举报