// 段操作头文件。定义了有关段寄存器操作的嵌入式汇编函数。

#include // 内存拷贝头文件。含有 memcpy()嵌入式汇编宏函数。

#define MAJOR_NR 1 // RAM 盘主设备号是 1。主设备号必须在 blk.h 之前被定义。

#include "blk.h"

char *rd_start; // 虚拟盘在内存中的起始位置。在 52 行初始化函数 rd_init()中

// 确定。参见(init/main.c,124)(缩写 rd_代表 ramdisk_)。

int rd_length = 0; // 虚拟盘所占内存大小(字节)。

// 虚拟盘当前请求项操作函数。程序结构与 do_hd_request()类似(hd.c,294)。

// 在低级块设备接口函数 ll_rw_block()建立了虚拟盘(rd)的请求项并添加到 rd 的链表中之后,

// 就会调用该函数对 rd 当前请求项进行处理。该函数首先计算当前请求项中指定的起始扇区对应

// 虚拟盘所处内存的起始位置 addr 和要求的扇区数对应的字节长度值 len,然后根据请求项中的

// 命令进行操作。若是写命令 WRITE,就把请求项所指缓冲区中的数据直接复制到内存位置 addr

// 处。若是读操作则反之。数据复制完成后即可直接调用 end_request()对本次请求项作结束处理。

// 然后跳转到函数开始处再去处理下一个请求项。

void do_rd_request(void)

{

int len;

char *addr;

// 检测请求项的合法性,若已没有请求项则退出(参见 blk.h,127)。

INIT_REQUEST;

// 下面语句取得 ramdisk 的起始扇区对应的内存起始位置和内存长度。

// 其中 sector << 9 表示 sector * 512,CURRENT 定义为(blk_dev[MAJOR_NR].current_request)。

addr = rd_start + (CURRENT->sector << 9);

len = CURRENT->nr_sectors << 9;

// 如果子设备号不为 1 或者对应内存起始位置>虚拟盘末尾,则结束该请求,并跳转到 repeat 处。

// 标号 repeat 定义在宏 INIT_REQUEST 内,位于宏的开始处,参见 blk.h,127 行。

if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) {

end_request(0);

goto repeat;

}

// 如果是写命令(WRITE),则将请求项中缓冲区的内容复制到 addr 处,长度为 len 字节。

if (CURRENT-> cmd == WRITE) {

(void ) memcpy(addr,

CURRENT->buffer,

len);

// 如果是读命令(READ),则将 addr 开始的内容复制到请求项中缓冲区中,长度为 len 字节。

} else if (CURRENT->cmd == READ) {

(void) memcpy(CURRENT->buffer,

addr,

len);

// 否则显示命令不存在,死机。

} else

panic( "unknown ramdisk-command" );

// 请求项成功后处理,置更新标志。并继续处理本设备的下一请求项。

end_request(1);

goto repeat;

}

/*

* Returns amount of memory which needs to be reserved.

*/

/* 返回内存虚拟盘 ramdisk 所需的内存量 */

// 虚拟盘初始化函数。确定虚拟盘在内存中的起始地址,长度。并对整个虚拟盘区清零。

long rd_init(long mem_start, int length)

{

int i;

char *cp;

blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; // do_rd_request()。

rd_start = (char *) mem_start; // 对于 16MB 系统,该值为 4MB。

rd_length = length;

cp = rd_start;

for (i=0; i < length; i++)

*cp++ = '\0' ;

return(length);

}

/*

* If the root device is the ram disk, try to load it.

* In order to do this, the root device is originally set to the

* floppy, and we later change it to be ram disk.

*/

/*

* 如果根文件系统设备(root device)是 ramdisk 的话,则尝试加载它。root device 原先是指向

* 软盘的,我们将它改成指向 ramdisk。

*/

尝试把根文件系统加载到虚拟盘中。

// 该函数将在内核设置函数 setup()(hd.c,156 行)中被调用。另外,1 磁盘块 = 1024 字节。

void rd_load(void)

{

struct buffer_head *bh; // 高速缓冲块头指针。

struct super_block s; // 文件超级块结构。

int block = 256; /* Start at block 256 */

int i = 1; /* 表示根文件系统映象文件在 boot 盘第 256 磁盘块开始处*/

int nblocks;

char *cp; /* Move pointer */

if (!rd_length) // 如果 ramdisk 的长度为零,则退出。

return;

printk( "Ram disk: %d bytes, starting at 0x%x\n" , rd_length,(int) rd_start);

// 显示 ramdisk 的大小以及内存起始位置。

if (MAJOR(ROOT_DEV) != 2) // 如果此时根文件设备不是软盘,则退出。

return;

// 读软盘块 256+1,256,256+2。breada()用于读取指定的数据块,并标出还需要读的块,然后返回

// 含有数据块的缓冲区指针。如果返回 NULL,则表示数据块不可读(fs/buffer.c,322)。

// 这里 block+1 是指磁盘上的超级块。

bh = breada(ROOT_DEV,block+1,block,block+2,-1);

if (!bh) {

printk( "Disk error while looking for ramdisk!\n" );

return;

}

// 将 s 指向缓冲区中的磁盘超级块。(d_super_block 磁盘中超级块结构)。

*((struct d_super_block *) &s) = *((struct d_super_block *) bh->b_data);

brelse(bh);

if (s.s_magic != SUPER_MAGIC) // 如果超级块中魔数不对,则说明不是 minix 文件系统。

/* No ram disk image present, assume normal floppy boot */

/* 磁盘中没有 ramdisk 映像文件,退出去执行通常的软盘引导 */

return;

// 块数 = 逻辑块数(区段数) * 2^(每区段块数的次方)。

// 如果数据块数大于内存中虚拟盘所能容纳的块数,则也不能加载,显示出错信息并返回。否则显示

// 加载数据块信息。

nblocks = s.s_nzones << s.s_log_zone_size;

if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {

printk( "Ram disk image too big! (%d blocks, %d avail)\n" ,

nblocks, rd_length >> BLOCK_SIZE_BITS);

return;

}

printk( "Loading %d bytes into ram disk... 0000k" ,

nblocks << BLOCK_SIZE_BITS);

// cp 指向虚拟盘起始处,然后将磁盘上的根文件系统映象文件复制到虚拟盘上。

cp = rd_start;

while (nblocks) {

if (nblocks > 2) // 如果需读取的块数多于 3 快则采用超前预读方式读数据块。

bh = breada(ROOT_DEV, block, block+1, block+2, -1);

else // 否则就单块读取。

bh = bread(ROOT_DEV, block);

if (!bh) {

printk( "I/O error on block %d, aborting load\n" ,

block);

return;

}

(void) memcpy(cp, bh->b_data, BLOCK_SIZE); // 将缓冲区中的数据复制到 cp 处。

brelse(bh); // 释放缓冲区。

printk( "\010\010\010\010\010%4dk" ,i); // 打印加载块计数值。

cp += BLOCK_SIZE; // 虚拟盘指针前移。

block++;

nblocks--;

i++;

}

printk( "\010\010\010\010\010done \n" );

ROOT_DEV=0x0101; // 修改 ROOT_DEV 使其指向虚拟盘 ramdisk。

}

linux内核完全剖析0.11,linux0.11内核完全剖析 - ramdisk.c相关推荐

  1. bootsect.s 预备——Linux-0.11 剖析笔记(一)

    文章目录 boot 目录下文件介绍 16 位代码是什么意思 计算机启动过程 Linux 0.11 启动过程 boot 目录下文件介绍 boot 目录中一共有三个文件,都是用汇编语言写的,如下图(图来自 ...

  2. LINUX0.11内核阅读笔记

    我是通过阅读赵炯老师编的厚厚的linux内核完全剖析看完LINUX0.11的代码,不得不发自内心的说Linus真的是个天才.虽然我觉得很多OS设计的思想他是从UNIX学来的,但是他自己很周全很漂亮很巧 ...

  3. Linux0.11内核源码解析-setup.s

    学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->setup程序将system模块从0x10000~0x8ffff整块向下移 ...

  4. Linux0.11内核源码解析-bootsect.s

    学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->上电 ->80x86架构CPU会自动进入实模式 ->从地址0x ...

  5. linux0.11磁盘映像制作及其剩余程序阅读注释笔记

    [ 1] linux0.11引导程序阅读注释. [ 2] linux0.11由实模式进入保护模式程序阅读注释 . [ 3] linux0.11护模式初始化程序阅读注释. [ 4] linux0.11主 ...

  6. Linux0.11 execve函数(六)

    系列文章目录 Linux 0.11启动过程分析(一) Linux 0.11 fork 函数(二) Linux0.11 缺页处理(三) Linux0.11 根文件系统挂载(四) Linux0.11 文件 ...

  7. Linux0.11 文件打开open函数(五)

    系列文章目录 Linux 0.11启动过程分析(一) Linux 0.11 fork 函数(二) Linux0.11 缺页处理(三) Linux0.11 根文件系统挂载(四) Linux0.11 文件 ...

  8. linux0.11—内存管理实验

    实验基本内容 用 Bochs 调试工具跟踪 Linux 0.11 的地址翻译(地址映射)过程,了解 IA-32 和 Linux 0.11 的内存管理机制: 在 Ubuntu 上编写多进程的生产者-消费 ...

  9. linux0.11内核完全剖析 - ll_rw_blk.c

    声明: 参考<linux内核完全剖析基于linux0.11>--赵炯    节选 1.功能描述 该程序主要用于执行低层块设备读 / 写操作,是本章所有块设备与系统其它部分的接口程序.其它程 ...

最新文章

  1. 跨学科整合,打造大数据最强集团军:清华大学大数据能力提升项目宣讲会来了!...
  2. 位运算02 - 零基础入门学习C语言65(完)
  3. eplan增加其他到工具栏_EPLAN增效之工具栏定制(十三:端子排编辑不进导航器)
  4. Ecplise软件Devices看到两个相同设备问题
  5. pmcaff2013产品经理时尚文化屌丝style--马克杯投票。
  6. Web程序员的Mysql进阶序一之sql使用分类及基础
  7. 华为微型计算机b515,华为MateStation B515台式机曝光:五种配置
  8. linux删除磁盘后刷新,linux – 短暂的文件是否刷新到磁盘?
  9. MySQL_管理与维护
  10. docker搭建zookeeper集群
  11. python之禅星号_那些用起来很爽,但用不好可能会被人打的Python骚操作
  12. 比特币矿业公司 Marathon 一季度产出 196 枚 BTC,共持有超 5100 枚 BTC
  13. android 图标 textview,Android TextView添加图标ImageView
  14. 当数据处理做不到实时,应该怎么办?
  15. 马云马斯克激辩:AI 是威胁还是被低估了?
  16. Python实现 N*N 乘法表
  17. r9270公版bios_显卡成功刷入UEFI GOP BIOS 彻底解决开机扁苹果
  18. android开发利器--站在巨人肩膀上前行
  19. drupal插入css,drupal8 自定义主题开发——导入自定义css和js
  20. IM即时通信多房间聊天室仿微信聊天(一)

热门文章

  1. batchplot放到哪个文件夹_如何整理文件夹?来看腾讯设计师的方法
  2. sourcetree克隆一直不成功_Git神器| SourceTree安装使用教程
  3. 关于MySQL buffer pool的预读机制
  4. python面试题_01
  5. 关于有类路由协议和无类路由协议
  6. 深入探索PowerPivot客户端和服务器端架构
  7. 对目前自己的博客做一个小结
  8. leetcode 61 python
  9. Dual-arm cooperation and implementing for robotic harvesting tomato using binocular vision(摘西红柿机器人)
  10. 计算机辅助语文识字教学的优势,小学语文计算机辅助教学研究