Linux 0.11内核hd_out后磁盘准备数据时的运行机制问询
Linux 0.11磁盘IO流程疑问:等待磁盘就绪时内核行为分析
我正在研究Linux 0.11内核源码,重点分析磁盘数据读取至内存的流程,目前正对hd.c中的hd_out函数及关联的do_hd_request函数进行解析。相关代码片段如下:
#define CURRENT (blk_dev[MAJOR_NR].current_request) // hd.c void do_hd_request(void) { ... unsigned int dev = MINOR(CURRENT->dev); unsigned int block = CURRENT->sector; ... nsect = CURRENT->nr_sectors; ... if (CURRENT->cmd == WRITE) { hd_out(dev, nsect, sec, head, cyl, WIN_WRITE, &write_intr); // Poll status register to check if ready to write for (i = 0; i < 3000 && !(r = inb_p(HD_STATUS) & DRQ_STAT); i++); if (!r) { bad_rw_intr(); goto repeat; } port_write(HD_DATA, CURRENT->buffer, 256); } else if (CURRENT->cmd == READ) { hd_out(dev, nsect, sec, head, cyl, WIN_READ, &read_intr); } else panic("unknown hd-command"); } 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 = HD_DATA; 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); }
据我理解,hd_out会向磁盘下发命令并绑定对应的中断处理函数(如read_intr或write_intr),随后磁盘开始准备数据。我的核心问题是:磁盘准备数据期间,Linux 0.11内核会执行什么操作?
我原本认为内核会切换至其他进程(如通过定时器中断),但调试时发现hd_out执行后直接进入磁盘中断处理函数(如hd_interrupt),仿佛磁盘立即就绪,这与预期的进程切换行为不符。我有以下疑问:
- 等待磁盘准备数据时,内核是否会进行进程切换?
- 若不进行进程切换,内核如何避免浪费CPU周期?
问题解答
1. 等待磁盘准备数据时的进程切换行为
Linux 0.11在磁盘准备数据阶段不会主动触发进程切换,但存在两种不同场景的差异:
- 写操作场景:代码中写操作后会执行一段有限次数的轮询逻辑,这段轮询完全阻塞在当前上下文,期间不会切换进程。
- 读操作场景:调用
hd_out下发读命令后,do_hd_request函数会直接返回。如果当前是用户进程发起的IO,内核会回到系统调用处理流程,最终通过schedule()触发进程切换;如果是内核线程发起的IO,则会继续执行其他内核逻辑,直到下一次定时器中断触发调度。
你调试时看到hd_out后直接进入hd_interrupt,大概率是因为虚拟机环境下磁盘IO被模拟为即时完成,物理磁盘的机械寻道、数据准备延迟被大幅缩短,导致磁盘中断几乎立刻触发,看起来像是没有切换进程就进入了中断处理。
2. 避免CPU周期浪费的机制
Linux 0.11针对磁盘IO等待的CPU浪费问题,主要通过以下方式处理:
- 中断驱动IO:读操作完全依赖中断触发,下发命令后内核不会原地等待,而是回到调度流程让其他进程执行,直到磁盘准备好数据后发送中断,再唤醒等待的进程处理数据。
- 有限轮询+失败回退:写操作的轮询设置了3000次的上限,若超时则调用
bad_rw_intr()标记请求失败并重新处理,不会无限占用CPU;这个次数是基于早期磁盘的响应速度设置的,属于平衡延迟和CPU占用的折中方案。 - 定时器调度:即使内核在某些场景下处于空闲等待,默认10ms一次的定时器中断会定期触发
schedule(),切换到就绪队列中的其他进程,避免CPU空转。
内容的提问来源于stack exchange,提问作者0x1B05
相关产品推荐
相关产品推荐

