30天自制操作系统第九天学习笔记(u盘软盘双启动版本)
暑假学习小日本的那本书:30天自制操作系统
qq交流群:122358078 ,更多学习中的问题、资料,群里分享
environment:开发环境:ubuntu
第九天的课程已学完,确实有点不想写这个笔记了,因为开学了,还要学习课业上的压力,转博了压力山大啊.
这一天的课程最难的我感觉是后面的memory free的部分,这一部分有很多已经没有接触到的东西,所以感觉比较难.
内存的管理在任何os中都是一个重要的问题.
还是按照作者的书本上第九天的顺序的来做笔记吧:
1:整理源文件部分,这一部分就没有什么了,把一个.c文件拆成多个.c文件工程大了,为了方便管理,方便各类函数的查找,必须要多个函数,能快速的定位所以与keyboard有关的函数放到keyboard中,与mouse有关的函数放到mouse中.
2:这一部分是内存的容量检查,作者的思路,在学arm的时候,也用到了,就是向内存中写一个数,然后读出来,如果这个内在地址可用,那么读出来的数,肯定和写进去的数一样.但是作者在检查内存容量之前,讲了好多关于cache的东西,一开始以为没有用,后来才知,如果不关cahce,我们目的是想往内存中写的数,很有可能写到了cache中这样就会导致,不能正确的检测出这个内存地址是否真的存在.
所以要先关了cache再检查内存的容量,因为386没有cache,先以后的cpu486及以上都有cache.所以要先判断cpu是不是i386,作者的思路是通过cpu中的eflags寄存器中的ac位,因为386的cpu还没有ac位这个标志位,所以向386cpu的efags的ac位写1是无效的,还是保持为0,通过这个方法,可以判断cpu是不是386.下面是伪代码.通过写出伪代码,可以更好的了解整个过程,而不会局限于一个细节
unsigned int memtest(start ,end)
{
tmp=read_eflag();
tmp|=acbit;
write_elfag(tmp);
tmp=read_eflag();
if(tmp_ac_bit==1)
{
cpu=486higher;
}; if(cpu==486higher)
{
turn_off_cache(); //control cr0 register
} size=get_memory_size(start,end); if(cpu==486higher)
{
turn_on_cache();
}
return size;//返回得到的memroy的值(byte为单位)
}
而get_memory_size()这个函数就用作者的方法搞定就行了,只是作者最后用汇编写了这部分的代码,因为作者认为编译器把他的代码给优化了,所以不得不用汇编写.但是实际上因为作者不了解c语言中还有一个强大的关键字,volatile.
只要把这个关键字用上,编译器就不会对指向内存地址的变量进行优化了.
当然,这一招是在学arm的时候学到的.
所以get_memory_size()这个函数,就用下面的代码来实现就ok了
unsigned int get_memory_size(start,end)
{
unsigned int i ,old;
unsigned int pat0=0xaa55aa55,pat1=0x55aa55aa;
volatile unsigned int *p;//注意这里的volatile关键字,
for(i=start;i<end;i+=0x1000)
{
p=(unsigned int *)(i+0xffc);
old=*p;
*p=pat0;
*p^=0xffffffff;
if(*p!=pat1)
{
*p=old;
break;
} }
return i;//i就是得到的memory size }
上面的函数我做了一些简化,因为我觉得作者做了一些没用用的事
当然在memtest,中需要用到读eflag,cr0,写eflag,cr0的函数,这个是用gcc内嵌汇编实现的
3:这一部分就是作者一步一步发现c编译器如何优化了他的函数,而不得已只好用汇编写get_memory_size这个函数的过程,没有细看,能看懂汇编对于做顶层的人太重要了.
4:这一天的第四部分,我觉得是最值得一看的,作者分析了两种内存管理的方法,
第一种是用数组的方法,也介绍了如何实现内在的allocate and free,数组中的每一个字节都和一个具体的地址对应了,而且每一个
memory block的大小也是固定的.有点想是分段的机制.因为这个管理内存的这个表太大了,而且在alocate and free时候要用for对数组
读写多次,非常耗时.但是这个方法是最简单的,非常好理解.
第二种方法是用下面的个数据结构:
sturct FREEINFO
{
unsigned int addr;
unsigend int size;
};
struct MEMMAN
{
unsigned int frees;
struct FREEINFO free[1000];
};
上面的数据结构,配合上 下面的四个函数,内存管理就搞定了
void memman_init(struct MEMMAN *man);
unsigned int memman_total(struct MEMMAN *man);
unsigned int memman_alloc(struct MEMMAN *man):
int memman_free(struct MEMMAN *man,unsigned int addr,unsigned int size);
用struct数据结构抽象成对象,上面的四个函数抽象成对 对象的操作.oop的编程.
四个函数有个共同的特点,传递的都是函数的指针,所以要对一个对象进行操作,指针是非常重要的,
可以在这些函数内部改变对象的属性.传递指针的方法也使函数具有更好的封装性,高内聚,低耦合就是这个道理吧.
当然作者对memman_free这个函数是写的非常清楚的,可是我还是只看到了一个半懂.后面再温故知新吧.
下面上一张virtualbox启动运行的图片,u盘启动,我也试了.如果要从u盘启动,命令如下
sudo -s
make usb=1
make copy
make u
make dd //这一步是写os.img到u盘,会看到u盘灯闪
好了,启动u盘做好了,have a try and enjoy !
30天自制操作系统第九天学习笔记(u盘软盘双启动版本)的更多相关文章
- 30天自制操作系统第八天学习笔记(u盘软盘双启动版本)
暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078 ,更多学习中的问题.资料,群里分享 environment:开发环境:ubuntu 第八天的学习思考: 关于鼠标是怎么 ...
- 《30天自制操作系统》19_day_学习笔记
harib16a: 这一部分,我们在系统中实现读取文件内容的命令type.在windows中,输入“type 文件名”,在Linux中,输入“cat 文件名”都可以显示文件的内容.我们先来看看如何读取 ...
- 《30天自制操作系统》12_day_学习笔记
harib09a: 定时器:(Timer)每隔一段时间,会向CPU发送一个中断.这样CPU不用记住每一条指令的执行时间.没有定时器很多指令CPU都很难执行.例如HLT指令,这个指令的执行时间不是个固定 ...
- 《30天自制操作系统》09_day_学习笔记
harib06a: 在昨天的最后一部分,我们已经变成了32位的模式,目的就是希望能够使用电脑的全部内存. 虽然鼠标的显示处理有一些叠加问题,不过笔者为了不让我们感到腻烦,先带我们折腾一下内存 这里笔者 ...
- 《30天自制操作系统》05_day_学习笔记
//bootpack.c 完整代码 #include <stdio.h> void io_hlt(void); void io_cli(void); void io_out8(int po ...
- 《30天自制操作系统》03_day_学习笔记
harib00a: 添加的部分从P46开始,制作IPL准备开始从磁盘装载程序了 笔者讲解了软盘的驱动的构造,以及汇编语言读取软盘的方法 MOV AX,0x0820 MOV ES,AX ; 柱面0 ; ...
- 《30天自制操作系统》17_day_学习笔记
harib14a: 接着上一天的内容,我们来思考一个问题:当所有的LEVEL中都没有任务的时候怎么办?采用前面定时器链表中加入“哨兵”的思路,我们加入一个idle任务,去执行HLT.接下来我们只需要将 ...
- 《30天自制操作系统》18_day_学习笔记
harib15a: 到这里为止,我们已经能实现窗口的切换了.我们发现所有的窗口都有光标闪烁,而我们只希望可以接受输入的窗口有光标闪烁.这里我们先来修改任务A中的光标闪烁,当按下TAB时,如果让A不现实 ...
- 《30天自制操作系统》16_day_学习笔记
harib13a: 今天我们要继续折腾多任务,任务的高效管理是操作系统的一个重要的任务.在今天,我们将为系统创建更加完善的任务管理系统,其中包括优先级,任务等级等. 1.任务管理结构体 #define ...
随机推荐
- opengl学习笔记(二)
这段时间终于接触到一点点shader了,应该说shader是非常有用的东西吧,它就是能够把一些固定渲染管线的东西改变了,按照自己的意愿进行渲染,这样的话图形就可以自由发挥了. 我也只是试验了一下sha ...
- Pip 安装 出现UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: ordinal not in
在Python 环境下,使用PiP 命令安装时,报错提示: UnicodeEncodeError: 'ascii' codec can't encode characters in position ...
- WinForm中嵌入WebBrowser,并且支持C#和JS方法的相互调用
纯粹WinForm界面不够友好,实现数据复杂度高的处理有些力不从心,所以看了看api以后决定用html来做. 我的wlw的代码插件不是很好用,大家凑合看吧 类前说明引用和权限 1: [Permissi ...
- hadoop部署、启动全套过程
Hadoop是Apache基金会的开源项目,为开发者提供了一个分布式系统的基础架构,用户可以在不了解分布式系统的底层细节的情况下开发分布式的应用,充分利用集群的强大功能,实现高速运算和存储.Hadoo ...
- 4Sum -- LeetCode
原题链接: http://oj.leetcode.com/problems/4sum/ 这道题要求跟3Sum差点儿相同,仅仅是需求扩展到四个的数字的和了.我们还是能够依照3Sum中的解法,仅仅是在外 ...
- SxsTrace工具用法
Windows7平台上有一个强大的SxsTrace工具,能够跟踪调试应用程序执行时须要的动态库的版本号和路径. SxsTrace使用的方法: 1.首先必须以Administrator用户身份登录,打开 ...
- DEBUG模式下, 内存中的变量地址分析
测试函数的模板实现 /// @file my_template.h /// @brief 测试数据类型用的模板实现 #ifndef MY_TEMPLATE_H_2016_0123_1226 #defi ...
- wift - 使用UIScreen类获取屏幕大小尺寸
UISreen类代表了屏幕,开发中一般用来获取屏幕相关的属性,例如获取屏幕的大小. 1 2 3 4 5 6 7 //获取屏幕大小 var screenBounds:CGRect = UIScreen. ...
- webdynpro 组件重用 传值问题
组件zwd1,需要调用组件zwd2的时候,zwd2组件控制器中需要定义一个方法,定义所要传输的参数,并且该方法需要定义为interface方法. 组件zwd1可以通过代码向导调用组件zwd2,的该方法 ...
- JDK1.5后的新特性之一:可变参数
Java中的可变参数 Java1.5后出现了一个新特性,即可变参数,格式为:类型 …参数 例如: 总的来说,可变参数可以当成是数组来用: public void testSum() { System. ...