一个基于X86的小型中文操作系统的设计、编码与调试

2006-11-22      嵌入式在线      收藏 | 打印

简介:本文通过一个基于X86的小型中文操作系统的建立过程,说明了一个小型操作系统的设计原理,编码过程和实现方法。作为一个开放源代码的系统,本文通过对源代码的剖析,较为详细地说明了内存管理,进程结构等的具体实现,并最后介绍了在开发过程中对产生的系统内核的调试,对操作系统的实践具有一定的指导意义。

一 引言

操作系统是计算机的软件基础。在进行一些系统编程实验的时候,我们需要对一些系统程序进行试验,并对这些程序进行量化评测。现有的大型操作系统,如Windows和Linux过于复杂,不适合进行试验。并且由于系统本身的开销比较大,对程序的量化评测要扣除系统(如进程调度)的开销,不易把握。因此我们自行设计开发了一个基于X86的小型中文操作系统。本文介绍了在开发中采用的一些方法和技巧,探讨小型操作系统的实作过程。

二 设计

1.       微内核

微内核是内核的一种形式。在微内核中,各个独立的模块被分离出来,作为独立的实体存在(进程)。在系统运行过程中,各个模块的进程独立运行,各进程通过消息通讯机制进行通讯。由于微内核系统具有良好的结构和可移植性,且易于调试,所以在设计中我们采用了微内核作为我们的内核结构。

2.       内存布局/管理

在X86提供的保护模式(Protected Mode)中,可以采用分段和分页两种方法来对内存进行管理[1]。我们可以通过对GDT或是LDT的相应的描述符表项来对内存的相应段进行设置,如段边界、段大小、特权级等属性[2]。在一个小型的系统中,可以通过将系统的整个内存空间全部设为一个段,即一个平的内存段,来达到简化系统的目的。这样做的缺点是不能有效利用到保护模式的一些优点,如段数据的保护。在NASM中,我们通过以下的代码对GDT进行段的设置:

_gdt:

dw 0, 0, 0, 0          ; (0)

; kernel cs 0x08 (1)

dw 0x3FFF    ; base: 0, limit: 64M

dw 0x0000

dw 0x9A00

dw 0x00C0

; kernel ds 0x10 (2)

dw 0x3FFF    ; base: 0, limit: 64M

dw 0x0000

dw 0x9200

dw 0x00C0

; user cs 0x1b (3)

dw 0x3FFF    ; base: 0, limit: 64M

dw 0x0000

dw 0xFA00

dw 0x00C0

; user ds 0x23 (4)

dw 0x3FFF    ; base: 0, limit: 64M

dw 0x0000

dw 0xF200

dw 0x00C0

3.       进程结构

多任务是一个现代操作系统所必须的一部分。在一个任务切换到另一个任务的过程中,我们必须保存现在正在运行的这个进程的上下文,以便在下次调入运行时能够在现在断下的地方继续运行,然后再调入下一个应该运行的进程的上下文,开始下一个进程的运行。在我们的系统中,简单地保存了下面的这些信息:

struct proc_struct

{

int           pid; // 进程id

int           parent;

struct proc_struct* next_proc; // 下一个进程

struct proc_struct* prev_proc; // 上一个进程

// 进程状态

long eip;

long eax;

long ebx;

long ecx;

long edx;

long esp;

long ebp;

long edi;

long esi;

long eflags;

// 段寄存器

short       cs;

short       ds;

short       es;

short       ss;

short       fs;

short       gs;

// 进程已经运行时间

int           total_tick;

unsigned char stack[STACK_NUM]; // 堆栈段

};

其中pid字段记录了这个进程的ID,parent记录了父进程的ID,next_proc是指向下一个要运行的进程的上下文的结构指针,以便系统调入下一个进程运行时进行快速定位,prev_proc记录了在这个进程之前运行的进程结构地址。由此可见,在我们的实现在,我们采用了双向链表对进程进行管理,既简单,又对进程的增加、删除、调序带来了方便。对于当前正在运行的进程,系统用struct proc_struct* p_proc这个指针来指向其进程结构。

在进行了以上的设置以后,我们就可以实现简单的进程管理系统了。process_schedule函数在进程双向链表中循环切换,在一个进程运行完一定的时间后,直接载入下一个进程的上下文,然后跳到下一个进程的执行点,进行执行。

int process_schedule(void)

{

// 进行一些进进程管理

if(p_proc->next_proc == NULL)

{

// 只有这一个进程运行,跳回去继续运行

jump_to_proc(p_proc);

}

p_proc = p_proc->next_proc; // 转到下一个进程

jump_to_proc(p_proc); // 切换过去

return 1;

}

其中,jump_to_proc这个函数在取得下一个进程的上下文后,将上下文装入CPU各寄存器中,然后运行jmp指令跳到进程的执行点中进行执行。

void jump_to_proc(struct proc_struct* p)

{

// 跳到指定的进程中去运行

temp_ebp = p->ebp;

temp_eip = p->eip;

temp_eax = p->eax;

temp_ebx = p->ebx;

temp_ecx = p->ecx;

temp_edx = p->edx;

temp_esp = p->esp;

temp_edi = p->edi;

temp_esi = p->esi;

temp_eflags = p->eflags;

__asm__("movl %0,%%ebp/n/t"

"movl %2,%%ebx/n/t"

"movl %3,%%ecx/n/t"

"movl %4,%%edx/n/t"

"movl %5,%%esp/n/t"

"movl %6,%%edi/n/t"

"movl %7,%%esi/n/t"

"pushl %8/n/t"

"popfl/n/t"

"movl %1,%%eax/n/t"

"sti/n/t"

::"m"(temp_ebp),

"m"(temp_eax),

"m"(temp_ebx),

"m"(temp_ecx),

"m"(temp_edx),

"m"(temp_esp),

"m"(temp_edi),

"m"(temp_esi),

"m"(temp_eflags));

switching = 0;

__asm__("jmp *%0/n/t"

::"m"(temp_eip));

// 此函数不应被返回

}

4.       文件系统

在FAT16,FAT32,EXT2等文件系统中,FAT32由于其实用性和简单性,我们选用它作为实现在文件系统。在硬盘驱动的基础上,我们简单地实现了FAT32文件系统的读功能,这样在后续的开发中,我们可以将各个功能模块作成单独的文件调入执行,增大系统的灵活性。

5.       启动设计

X86系统加电后BIOS执行完自检,将启动设备的第一个扇区读入到物理地址为0x7C00的内存单元中,然后跳到0x7C00去运行。由此可见,操作系统与BIOS的接口就在于启动设备(软驱,硬盘驱动器或是光盘驱动器)的第一个扇区。一般在这第一个扇区完成操作系统的初步载入。但我们在实践中发现,在一个扇区这么小的空间内(512个字节),将整个系统载入比较困难,且如果安装在PC上会与已经存在的操作系统发生冲突。

在这种情况下,我们想到GNU的GRUB启动装载器。GRUB能够支持多个操作系统的共存,通常我们将系统内核编译成GRUB启动装载器能够识别的文件格式,GRUB便能将系统加载到指定的内存地址中去,然后跳到我们的系统中去运行。

三 编码过程

1.       开发环境

我们尝试了两种开发环境,Linux和Windows。在Linux环境下,程序开发工具丰富好用,但是在对中文的支持上不够。在Windows下,适合操作系统开发的程序开发工具并不是很多,但对中文支持很好,且具有更大的通用性。所以,在进行了一段时间的Linux开发后,我们选用Windows做为开发平台。

2.       C编译器

我们采用GNU的gcc编译器进行C程序的开发。Gcc是Linux下著名的C程序编译器,支持内联的汇编语句,比较适合系统程序的开发。且支持多种目标文件的格式,如coff,elf等,可以将C源程序方便地编译成多种目标文件。在Windows环境下,默认情况下产生coff文件格式,而在Linux环境下,默认产生elf格式的文件。

3.       汇编器

在众多的汇编器中,我们选用nasm来进行汇编部分代码的编译。这是因为nasm非常适合操作系统的开发。如用其它的汇编器,在从实模式到保护模式的过渡过程中,因为涉及到16位与32位指令的过渡,一般要直接写二进制代码来进行jmp的步骤。而在nasm中,直接用jmp dword就可以轻松做到。可以使用nasm –f coff a.asm来产生coff格式的目标文件,-f开关用于选择要产生的目标文件类型。Nasm也支持elf、coff等多种目标文件格式。

4.       连接器

在用编译器产生C和汇编目标文件后,下一步是用连接器将它们连接成一个内核文件。我们选用GNU的ld连接器来进行目标文件的连接工作。

5.       二进制文件格式

在Windows环境下,coff文件格式是得到编译器和连接器较为广泛支持的一种目标文件格式。在coff目标文件中,C与汇编产生的标号(Symbol)略有不同,在开发中应予以重视。即gcc在对C源程序中的标号进行处理时,在前面添加了一个下划线。如果我们在汇编程序中要引用这个标号,就要注意增加一个下划线。如有一个C程序里面有一个void maind(void)函数,如在汇编中引用,则要这样定义:

extern  _maind

如果编译成elf文件格式,则没有此问题。

四 调试过程

1.       使用X86模拟器

作为计算机的基础软件,在编译后的操作系统一定要在真实的机器上运行才能知道程序是否正确。这样,如果要进行操作系统的调试,要么把本机重启,要么找一台专门的机器用于调试。这样做都不是很方便。

我们还有一个选择就是使用X86系统的模拟器。模拟器运行于现有的操作系统之上,其将操作系统内核读入,在其内部摸拟X86系统。这样,我们运用摸拟器就可以直接在开发机上进行操作系统的运行,非常方便快速。

常见的X86模拟器有VMWare、Bochs等。VMWare是商业软件,有Windows和Linux两种版本,易于使用,但其是为一般用户开发的,功能较少。Bochs是开源的优秀模拟器,免费使用,而且它体积小巧,功能强大。在我们的开发中,使用Bochs进行系统的模拟环境,并借用Bochs进行二进制级别的调试。

2.       使用Bochs进行二进制级别的调试

在操作系统的开发中,调试是一件比较困难的事情。因为在开发的初期无法移植一些知名的调试软件之前,调试一般只能依靠二进制级的工具来进行。前面提到的模拟器Bochs,在除了模拟功能以外,还具有一定的调试功能。在Bochs目录下,BOCHSDBG.EXE即为集成了调试功能的Bochs可执行文件。在Bochs运行后,出现了如下的提示后,就可以输入一些进行诸如断点设置,汇编/反汇编,查看CPU状态等调试命令。

Next at t=0

(0) context not implemented because BX_HAVE_HASH_MAP=0

[0x000ffff0] f000:fff0 (unk. ctxt): jmp f000:e05b

<bochs:1>

下面是用Bochs进行调试的一些常用命令,熟练掌握这些命令,对调试系统是非常有帮助的。

命令

说明

c

继续执行(continue)

step  [count]

单步执行,count为步数,默认为1(execute count instructions)

Ctrl-C

停止运行

quit

退出bochs

vbreak seg:off

虚拟地址断点,seg为段地址,off为偏移,用于在指定的虚拟地址处设置断点(virtual address break)

pbreak addr

物理地址断点,addr为物理地址。用于在指定的物理地址处设置断点(physical address break)

info break

显示已经设置的断点情况

delete n

删除断点(Delete a breakpoint)

x  /nuf addr

查看在线性地址处的内存单元内容(Examine memory at linear address addr)
其中:n表示要显示的单元数,u表示单元大小,f表示打印格式

xp /nuf addr

查看在物理地址处的内存单元内容(Examine memory at physical address addr)其中nuf的意义同上

setpmem addr datasize val

设置在物理内存地址addr上的内存单元内容。Datasize为要设置的单元大小,val为要设置的值。

info registers

打印出CPU寄存器的当前值。

set $reg = val

将一个寄存器赋值,其中reg可以换为eax等寄存,如set $eax = 0xA

dump_cpu

将CPU的整个状态全部打印出来

disassemble start end

反汇编指定地址的程序。Start为开始的线性地址,end为结束的线性地址。

参考文献:

1.        Intel,IA-32 Intel® Architecture Software Developer’s Manual Volume 3: System Programming Guide,Intel Corporation,2002

2.        杨季文,80x86汇编语言程序设计教程,清华大学出版社,1998

3.       Peter Abel,IBM PC Assembly Language And Programming(Fourth Edition),Prentice Hall,1998

4.       W.Richard Stevens,Advanced Programming in the UNIX Environment,Addison-Wesley,1993

5.       M.Morris Mano,Computer System Architecture(Third Edition),Prentice Hall,1993

6.       Barry B.Brey,The Intel Microprocessors(Fifth Edition),Pearson Education,2000

7.       Maurice.Bach,The Design of The UNIX Operating System,Prentice Hall,1986

8.       Andrew S.Tanenbaum  Albert S.Wooddhull,Operating System:Design and Implementation(Second Edition), Prentice Hall,1997

本文来源:互联网    作者:华中师范大学城市与环境科学学院 陈斌
关于操作系统 微内核 内存管理 进程管理 模拟器 的文章
  • 一个基于X86的小型中文操作系统的设计、…
  • 一个基于X86的小型中文操作系统的设计、…
  • 对嵌入系统应用中x86CPU的重新评价
  • 利用BIOS定制实现嵌入式产品的差异化
  • 基于X86的信息家电SoC解决方案
资讯今日推荐
  • IDG:开源渐成主流2011收入可达58亿美元
  • WiMAX冲击波:Wi-Fi被指结束黄金时代
  • TD终端招标在即 40亿盛宴中的本土机遇
  • Vativ科技公司近日发布新一代HDMI接收器…
  • AMI推新型无传感器单芯片步进电机驱动器
评一评 已有 0 位网友对此文发表了看法。  我也来评一下
以下网友留言只代表其个人观点,不代表嵌入式在线网的观点或立场

我要登录 >> 提示:请用嵌入式在线帐号登录,以方便您与此处网友进行交流。

验证码:  看不清?换一张

<script src="http://mcuol.com/adjs/Html_Right_1.js" type="text/javascript"></script>
博文推荐
  • MEDC文档:USB启动试验教程
  • 8086FPGA核跑吃豆子游戏开发手记(1)
  • 32位嵌入式系统——IT从业人员的机遇与挑战
  • 白领:如何与咆哮老板面对面
  • 多核、多线程代表着嵌入式系统的未来
社区推荐
  • 学WINCE开发和LINUX开发,哪个容易些?
  • 长篇连载:精彩armlinux演义(转)
  • 超级残忍:暴力解剖iPhone全过程!
  • 硬件设计中一些术语的简称
  • 哈佛结构和冯·诺伊曼结构的区别
<script src="http://mcuol.com/adjs/Html_Right_2.js" type="text/javascript"></script>
下载推荐
  • Linux百科书籍,不下亏了
  • linux基本命令.exe
  • ARM开发详解全集
  • 嵌入式 uClinux及其应用开发
  • 深入uclinux嵌入式操作系统
<script src="http://mcuol.com/adjs/Html_Right_3.js" type="text/javascript"></script>
推荐方案
  • 移动电视系统设计挑战及解决方案大扫描
  • 数码相框方案技术属性
  • 基于IPP的嵌入式音频解码器设计与优化
  • 基于OS20的机顶盒软件体系及其应用设计
  • 基于nRF905的无线数据传输设备设计

一个基于X86的小型中文操作系统的设计、编码与调试http://www.mcuol.com/Tech/207/1289.htm相关推荐

  1. 风力机叶片气动设计 matlab 程序,基于MATLAB的小型风力机叶片设计

    叶片设计 第25卷第5期2007年10月 文章编号:1000-7709(2007)05-0142-03 水电能源科学WaterResourcesandPower V01.25No.50Ct.20 0 ...

  2. matlab风力机叶片仿真教程,基于MATLAB的小型风力机叶片设计

    文章编号: 100027709(2007) 050142203 基于MA TLAB 的小型风力机叶片设计 王 军 周丙超 (华中科技大学 能源与动力工程学院, 湖北 武汉 430074) 摘要: 结合 ...

  3. 关于[一个基于WF的业务流程平台]表设计的说明

    数据库的主键设计说明 在我发布的例子 一个基于WF的业务流程平台 中, N12345B 问到 // 所有的数据结构都几乎使用了Guid这一数据类型作为ID,而这个ID的作用仅仅作为流水号吗?所有表之间 ...

  4. 学习LSM(Linux security module)之四:一个基于LSM的简单沙箱的设计与实现

    转自:cnblog 嗯!如题,一个简单的基于LSM的沙箱设计.环境是Linux v4.4.28.一个比较新的版本,所以在实现过程中很难找到资料,而且还有各种坑逼,所以大部分的时间都是在看源码,虽然写的 ...

  5. 一个基于JDBC的通用DAO的设计参考(北大青鸟课程)

    在S2阶段和Y2阶段的前部分是使用的JDBC来访问数据库,但是通常我们编写的时候在每个工程中都编写代码基本类似却有一点点不同之处的DAO层代码,现在介绍一种相对简化的方式来简化编程 现在我们来分析下S ...

  6. 使用nw.js快速开发一个基于浏览器的小型桌面端(适用于高校学生完成可视化实验小作业)

    首先讲下退坑事项,节约读者时间 虽然入门较为简单,能快速产出在本地的一个桌面端应用,但是 生成的exe会依赖SDK文件夹下的一些dll,所以不能简单的交付这个exe,需要使用额外的软件进行打包,如En ...

  7. 基于Jetson AGX Xavier GMSL9296硬件设计与软硬件调试

    一.需求 1. 支持Jetson Xavier AGX Devkit 开发套件120Pin (QSH-060-01-H-D-A-K-TR Samtec)2. GMSL Deserializer 采用 ...

  8. 基于新闻的高级中文搜索引擎

    摘 要 随着大数据时代来临,互联网信息量海量倍增, 浏览网络新闻也已经成为大家了解社会动态的一个重要渠道.搜索引擎为用户提供了一个找海量新闻信息的快速入口,然而,随着信息搜索技术的不断发展,用户对信息 ...

  9. 嵌入式课程设计linux,嵌入式系统课程设计--基于U盘的linux操作系统的构建

    嵌入式系统课程设计--基于U盘的linux操作系统的构建 1 课程设计报告课程设计报告 课程名称课程名称 嵌入式系统课程设计嵌入式系统课程设计 设计题目设计题目基于基于 U盘的盘的 linux 操作系 ...

最新文章

  1. wordpress acf字段 不同样式_WordPress强大搜索功能如何实现?安装Ivory Search插件
  2. Angular页面里元素class的动态绑定的实现源代码调试
  3. P6122-[NEERC2016]Mole Tunnels【模拟费用流】
  4. LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal 由前序和中序遍历建立二叉树 C++...
  5. spring注解 @Scheduled(cron = 0 0 1 * * *)的使用来实现定时的执行任务
  6. 微软Silverlight==跨浏览器、跨客户平台的技术
  7. Python版24点游戏
  8. poj 1724 有限制的最短距离(优先队列+链表)
  9. 物联网时代下,如何打造智慧新社区?
  10. Flutter基础布局组件及实现
  11. 大文件如何传输到服务器,大文件如何快速传输到云服务器
  12. 显卡更新后重启计算机就没了,在windows10系统更新显卡后黑屏的解决方法
  13. 计算机科学与技术专业需要配电脑吗,大一新生开学,需要配台“电脑”吗?辅导员:这4个专业必须配...
  14. 信捷PLC 批量传送位 MOV DMOV QMOV
  15. 机器学习训练营--快来一起挖掘幸福感吧
  16. 查询网站排名,收录情况
  17. python代码实现卷积示意图快速制作
  18. sql server之T-SQL语句创建数据库创建表
  19. CCM色彩调试黄色块饱和度不够
  20. 量化交易入门阶段——欧奈尔的CANSLIM模型(A 年度净利润同比增长率)

热门文章

  1. FPGA 20个例程篇:18.SD卡存放音频WAV播放(上)
  2. Win 10 WoL 失败检查小记
  3. Solr-Solrj简单使用
  4. solr java 客户端_Solr JAVA客户端SolrJ的使用
  5. layui常用的表单验证
  6. paxos协议的理解及证明推导
  7. 大O大Omega大Theta
  8. 本地搭建maven仓库
  9. checkSession:fail 系统错误,错误码:-13001,session time out, need relogin
  10. 视频编码解码(H264编码实战)