26.文件使用磁盘的代码实现

Posted PacosonSWJTU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了26.文件使用磁盘的代码实现相关的知识,希望对你有一定的参考价值。

【README】

1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐;

2.文件内容复习:

  • 1)如何从生磁盘抽象为文件?
    • 核心是从字符流位置算出盘块号;
  • 2)如何算出盘块号?
    • 用到顺序结构,或链式结构,或索引结构提供的字符流到盘块号的映射表。

【1】再一次使用磁盘,通过文件使用

 1) fs/read_write.c 文件读写代码

// 在 fs/read_write.c 中 
// fd : 文件描述符 
// buf: 内存缓冲区
// count: 读写字符个数  
int sys_write(int fd, const char* buf, int count) 

	struct file *file = current->file[fd]; 
	struct m_inode *inode = file->inode; 
	if (S_ISREG(inode->i_mode)) 
		return file_write(inode, file, buf, count); // file_write 写文件

【代码说明】

  • Write 到了内核级代码就是系统调用  sys_write ;
  • Sys_write 代码没有使用盘块号,但会通过参数计算出盘块号;
  • 实际对文件的使用,对磁盘读写,就是去处理字符流中的一段;

【图解】读写磁盘细节(代码层面)

  • 步骤1:获取文件的inode,i 指的是索引,node指的是 FCB(文件控制块);其中FCB 存储了索引盘块号(即 字符流到盘块号的映射关系);
  • 步骤2:根据要操作的字符位置和索引(映射关系)计算出字符流对应的盘块号进行读写;代码表现为 file_write(inode, file, buf, count) ,其中inode是index+fcb(索引+索引块),file存储了文件字符流位置范围(如200~212),buf内存缓冲区地址,count字符个数;  

【1.1】file_write 整个工作过程

1)file_write(inode, file, buf, count) 文件写函数

  • inode: inode存储了索引盘块号(字符范围与盘块号的映射关系);
  • file: 字符起始位置 200;
  • buf: 内存缓冲区;
  • count: 字符个数12;

通过 file 和 count 就可以计算出字符范围 200~212 ;

2)磁盘读写整个过程如下(用户程序到磁盘驱动,到磁盘控制器):

  • 步骤1: 用户应用程序调用 file_write 函数写磁盘,传入 inode,file,buf,count 参数;
  • 步骤2: file中的字符起始位置200,count为12,则可以表示字符范围 200~212;
  • 步骤3: 通过索引盘块号读入索引(字符范围与盘块号的映射关系),根据字符起始位置查找索引可以找到盘块号789;
  • 步骤4: 把盘块号789添加到请求队列,由驱动程序中的中断处理程序调用电梯算法选择盘块号,并把盘块号解析出 CHS(柱面号,磁头号,扇区偏移)送入磁盘控制器;
  • 步骤5:磁盘控制器根据CHS对具体扇区进行磁盘读写;

3)file_write 的 代码实现

 【图解】file_write写文件详细步骤

  • 1)步骤1:找到要操作的文件字符位置 pos;
  • 2)步骤2:调用 create_block() 根据位置pos查找索引(inode存储了索引)得到盘块号block;
  • 3)步骤3: bread(...) 把盘块号添加到请求队列,当前线程睡眠(当磁盘读写完成,由中断处理程序唤醒当前线程);
  • 4)步骤4: 添加到请求队列后,在循环体中从磁盘读字符(每次读一个字符);

4)Create_block() 算出盘块号的代码实现

5)设备文件的inode

 【图解】

  • i_mode 指向字符文件;
  • i_zone 指向文件内容数据块;
  • MAJOR : 主设备号;
  • MINOR  : 次设备号;

【2】伟大的文件视图

【2.1】操作文件

 【图解】操作磁盘步骤

  • 步骤1:打开文件; fd = open(“test.c”) ; // 获取文件描述符 ;
  • 步骤2:读取文件; write(fd) ; fd 存在于 文件列表;
  • 步骤3:通过文件列表找到 fd 对应的inode; (以上3个步骤讲的是 通过文件名或文件路径获得inode)
  • 步骤4:通过inode找到盘块号;
  • 步骤5:把盘块号送入请求队列;
  • 步骤6:驱动程序从队列取出盘块号,计算出CHS参数并发出 out 指令把参数送入磁盘控制器;
  • 步骤7:磁盘控制器驱动马达读写磁盘扇区,电生磁磁生电

【2.2】操作显示器等其他外设

  • 其调用路径也与操作磁盘路径类似;
  • 只不过inode指向的是显示器,而不是文件盘块号;操作函数是 tty_write 而不是file_write ;

以上是关于26.文件使用磁盘的代码实现的主要内容,如果未能解决你的问题,请参考以下文章

磁盘管理-软硬链接及创建设备文件

liunx磁盘存储

操作系统文件使用磁盘的实现---20

磁盘管理详解

如何使用 ansible 在一个循环中挂载多个磁盘

8.25_Linux磁盘管理