最近在学习于渊先生《Orange's:一个操作系统的实现》这本书,源码中有关硬盘驱动程序中的一段代码,似乎有些问题,贴出来与大家分享下。
PRIVATE void hd_rdwt(MESSAGE * p)
{
int drive = DRV_OF_DEV(p->DEVICE);
u64 pos = p->POSITION;
assert((pos >> SECTOR_SIZE_SHIFT) < (1 << 31));
/**
* We only allow to R/W from a SECTOR boundary:
*/
assert((pos & 0x1FF) == 0);
u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT); /* pos / SECTOR_SIZE */
int logidx = (p->DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE;
sect_nr += p->DEVICE < MAX_PRIM ?
hd_info[drive].primary[p->DEVICE].base :
hd_info[drive].logical[logidx].base;
struct hd_cmd cmd;
cmd.features = 0;
cmd.count = (p->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
cmd.lba_low = sect_nr & 0xFF;
cmd.lba_mid = (sect_nr >> 8) & 0xFF;
cmd.lba_high = (sect_nr >> 16) & 0xFF;
cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
cmd.command = (p->type == DEV_READ) ? ATA_READ : ATA_WRITE;
hd_cmd_out(&cmd);
int bytes_left = p->CNT;
void * la = (void*)va2la(p->PROC_NR, p->BUF);
while (bytes_left) {
int bytes = min(SECTOR_SIZE, bytes_left);
if (p->type == DEV_READ) {
interrupt_wait();
port_read(REG_DATA, hdbuf, SECTOR_SIZE);
phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
}
else {
if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
panic("hd writing error.");
port_write(REG_DATA, la, bytes);
interrupt_wait();
}
bytes_left -= SECTOR_SIZE;
la += SECTOR_SIZE;
}
}
以上是硬盘驱动程序中读写硬盘的一段代码,在while循环中向硬盘读取或写入数据。bytes_left变量记录着需要读写的剩余字节数。
while循环中的变量bytes 记录着每次循环处理的字节数,但是在while循环的末尾却是这样两行代码:
bytes_left -= SECTOR_SIZE;
la += SECTOR_SIZE;
la += SECTOR_SIZE;
显然不妥,正确的写法应该是:
bytes_left -= bytes ;
la += bytes ;
算法本身很简单,应该也容易理解,不知道有没有其他朋友也和我一样,发现了这个小问题。