linux内核完全剖析0.11,linux0.11内核完全剖析 - ramdisk.c
// 段操作头文件。定义了有关段寄存器操作的嵌入式汇编函数。
#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相关推荐
- bootsect.s 预备——Linux-0.11 剖析笔记(一)
文章目录 boot 目录下文件介绍 16 位代码是什么意思 计算机启动过程 Linux 0.11 启动过程 boot 目录下文件介绍 boot 目录中一共有三个文件,都是用汇编语言写的,如下图(图来自 ...
- LINUX0.11内核阅读笔记
我是通过阅读赵炯老师编的厚厚的linux内核完全剖析看完LINUX0.11的代码,不得不发自内心的说Linus真的是个天才.虽然我觉得很多OS设计的思想他是从UNIX学来的,但是他自己很周全很漂亮很巧 ...
- Linux0.11内核源码解析-setup.s
学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->setup程序将system模块从0x10000~0x8ffff整块向下移 ...
- Linux0.11内核源码解析-bootsect.s
学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->上电 ->80x86架构CPU会自动进入实模式 ->从地址0x ...
- linux0.11磁盘映像制作及其剩余程序阅读注释笔记
[ 1] linux0.11引导程序阅读注释. [ 2] linux0.11由实模式进入保护模式程序阅读注释 . [ 3] linux0.11护模式初始化程序阅读注释. [ 4] linux0.11主 ...
- Linux0.11 execve函数(六)
系列文章目录 Linux 0.11启动过程分析(一) Linux 0.11 fork 函数(二) Linux0.11 缺页处理(三) Linux0.11 根文件系统挂载(四) Linux0.11 文件 ...
- Linux0.11 文件打开open函数(五)
系列文章目录 Linux 0.11启动过程分析(一) Linux 0.11 fork 函数(二) Linux0.11 缺页处理(三) Linux0.11 根文件系统挂载(四) Linux0.11 文件 ...
- linux0.11—内存管理实验
实验基本内容 用 Bochs 调试工具跟踪 Linux 0.11 的地址翻译(地址映射)过程,了解 IA-32 和 Linux 0.11 的内存管理机制: 在 Ubuntu 上编写多进程的生产者-消费 ...
- linux0.11内核完全剖析 - ll_rw_blk.c
声明: 参考<linux内核完全剖析基于linux0.11>--赵炯 节选 1.功能描述 该程序主要用于执行低层块设备读 / 写操作,是本章所有块设备与系统其它部分的接口程序.其它程 ...
最新文章
- 跨学科整合,打造大数据最强集团军:清华大学大数据能力提升项目宣讲会来了!...
- 位运算02 - 零基础入门学习C语言65(完)
- eplan增加其他到工具栏_EPLAN增效之工具栏定制(十三:端子排编辑不进导航器)
- Ecplise软件Devices看到两个相同设备问题
- pmcaff2013产品经理时尚文化屌丝style--马克杯投票。
- Web程序员的Mysql进阶序一之sql使用分类及基础
- 华为微型计算机b515,华为MateStation B515台式机曝光:五种配置
- linux删除磁盘后刷新,linux – 短暂的文件是否刷新到磁盘?
- MySQL_管理与维护
- docker搭建zookeeper集群
- python之禅星号_那些用起来很爽,但用不好可能会被人打的Python骚操作
- 比特币矿业公司 Marathon 一季度产出 196 枚 BTC,共持有超 5100 枚 BTC
- android 图标 textview,Android TextView添加图标ImageView
- 当数据处理做不到实时,应该怎么办?
- 马云马斯克激辩:AI 是威胁还是被低估了?
- Python实现 N*N 乘法表
- r9270公版bios_显卡成功刷入UEFI GOP BIOS 彻底解决开机扁苹果
- android开发利器--站在巨人肩膀上前行
- drupal插入css,drupal8 自定义主题开发——导入自定义css和js
- IM即时通信多房间聊天室仿微信聊天(一)
热门文章
- batchplot放到哪个文件夹_如何整理文件夹?来看腾讯设计师的方法
- sourcetree克隆一直不成功_Git神器| SourceTree安装使用教程
- 关于MySQL buffer pool的预读机制
- python面试题_01
- 关于有类路由协议和无类路由协议
- 深入探索PowerPivot客户端和服务器端架构
- 对目前自己的博客做一个小结
- leetcode 61 python
- Dual-arm cooperation and implementing for robotic harvesting tomato using binocular vision(摘西红柿机器人)
- 计算机辅助语文识字教学的优势,小学语文计算机辅助教学研究