设备与磁盘

185 阅读2分钟

设备的工作原理

CPU发出指令,写数据到设备控制器上的存储。设备控制器上的电路读指令,进行相应操作。指令完成后设备控制器发起中断。

int fd = open("/dev/xxx");
for (int i = 0; i < 10; ++i) {
    write(fd, i, sizeof(int));
}
close(fd);

操作系统提供了操作设备的同一接口。无论任何设备都是open, read, write, close。不同的设备对应不同的设备文件,可以通过设备文件找到设备控制器的地址、内容格式等。

举个栗子

printf其实就是write(1),当前进程的filep[1]对应一个文件结构,我们可以从filep[1]中拿到f_inode。

int sys_write(int fd, char* buf, int count) {
    fp = current_pcb->filep[fd];
    inode = fp->f_inode;
}

当前进程的filep数组是在父进程fork时拷贝来的,而第一份filep数组是在系统初始化的init函数中创建的。init后,0、1、2号fd都指向"/dev/tty0"这个设备文件。

void main() {
    if (!fork()) init();
}

磁盘

image.png

磁盘的访问单位是扇区,扇区大小512字节,扇区的大小是传输时间和碎片浪费的折中。

如何从磁盘读取一个字节?

  1. 移动磁臂到指定的柱面(多个盘面的相同磁道组成柱面)上。
  2. 移动磁头到指定的磁道。
  3. 磁盘开始旋转,旋转到指定扇区。
  4. 加载扇区到内存。
  5. 从内存中读取一个字节。

访问磁盘需要柱面、盘面、扇区等信息,操作系统抽象了一个block的概念用于屏蔽这些细节,磁盘驱动负责将block转换为柱面、盘面、扇区等信息。

磁盘访问时间 = 写入控制器时间 + 寻道时间 + 旋转时间 + 传输时间。block相邻的盘块可以快速读出。

磁盘的读写单位是扇区,操作系统的读写单位是盘块(连续的几个扇区),提升了读写粒度,读写速度提升了(减少了寻道和旋转时间),空间碎片也变大了,相当于空间换时间。

多个进程读写磁盘,需要加一个请求队列,进程把block放在队列中,磁盘驱动从队列中获取block。