自己操作系统_自己写操作系统 - CSDN
精华内容
参与话题
  • 自己动手写操作系统》(一)

    千次阅读 2019-04-26 10:15:51
    2019-4-26 AM 9:15 前言:记得上初中时,在一张英语报上看到一篇关于史蒂夫乔布斯的文章,那时他才20多岁,就已经达到人生的巅峰,可谓意气风发,我的内心对其充满崇敬之意。联想到表哥家的那台windows95大块头电脑...

    2019-4-26 AM 9:15

    前言:记得上初中时,在一张英语报上看到一篇关于史蒂夫乔布斯的文章,那时他才20多岁,就已经达到人生的巅峰,可谓意气风发,我的内心对其充满崇敬之意。联想到表哥家的那台windows95大块头电脑,时常偷偷玩上两把魔兽争霸,那时,已经对这个魔术般奇幻的机器充满好奇。再后来一直到大学,在偌大的图书馆看到关于计算机的书籍,里边总是浮现一些不明所以的代码,既感到神奇的同时也暗下决心一探究竟,我记得第一次运行hello world程序的狂喜心情,然后这种对计算机技术的热爱就一直延续至今。很纯粹的热爱,就想弄明白操作系统的运作原理,便想依照于渊老师的《自己动手写操作系统》做一个小的系统内核,真正属于自己的!想想都有种莫名的激动。

    基本上,书中都是在虚拟机上运行,我手边有一个基本上不用的联想Y460的笔记本电脑,我决定直接在这个机器上做实验,不知是不是对不起我的爱机?

    以前实际上是有过类似的写操作系统的经验的,但因为没有任何文档记录,现在得一切从头开始。这两天已经摸索出基本测试思路:1.使用notepad++文本编辑器编辑好系统代码,asm格式。2.使用NASM转为格式为bin文件 3.直接使用rawrite写入U盘 4.使用真机测试

    第一章--最小的“操作系统”

    最最简单的“操作系统”就是一个最最简单的引导扇区(Boot Sector)。虽然它不具有任何功能,但是它却能够直接在裸机上运行,不依赖其他软件。一个引导扇区是512个字节,并且以0xAA55为结束标识的扇区。

    /****************************************************************************************************************************************************引导扇区(Boot Sector) 通常指设备的第一个扇区,用于加载并转让处理器控制权给操作系统。

    0x07C00相当于十进制中的:31744

    ***************************************************************************************************************************************************/

    1. org 07C00h                          ; 告诉编译器程序加载到07C00处  
    2.        mov ax, cs  
    3.        mov ds, ax  
    4.        mov es, ax  
    5.        call DispStr                     ; 调用显示字符串例程  
    6.        jmp $                    ; 无限循环  
    7. DispStr:  
    8.        mov ax, BootMessage  
    9.        mov bp, ax                       ; es:bp = 串地址  
    10.        mov cx, 16                       ; cx = 串长度  
    11.        mov ax, 01301h               ; ah = 13, al = 01h  
    12.        mov bx, 000Ch                ; 页号为0(bh = 0) 黑底红字 (bl = 0Ch,高亮)  
    13.        mov dl, 0  
    14.        int 10h                          ; 10h号中断  
    15.        ret  
    16. BootMessage:  db "Hello,OS world!"  
    17. times 510-($-$$)   db   0               ; 填充剩下的空间,使生成的二进制代码恰好为512字节  
    18. dw 0xaa55                               ; 结束标志  

    1、org 07C00h

    org伪指令: org + 数值表达式

    其中,org是操作码,不可省略。数值表达式给出偏移地址值,即org语句后的指令或数据以数值表达式给出的值作为起始的偏移地址。数值表达式必须是一个可计算得到的正整数,数值范围在0~65535之间。

    org伪指令用来指出其后的程序段或数据块存放的起始地址的偏移量。汇编程序汇编时把语句中表达式的值作为起始地址,连续存放org语句之后的程序和数据,直到出现一个新的org指令。若省略org语句,则从本段起始地址开始连续存放。

    在大多数情况下,不需要用org语句设置位置指针。由于段定义语句是段的起点,它的偏移地址为0000H,以后每分配一个字节,位置指针自动加1,所以每条指令都有确定的偏移地址。只有程序要求改变这个位置指针时,才需要安排org语句。通常org语句可以出现在程序中任何位置上。   

    org示例:

    在数据段中依次定义以下变量,由于此时没有使用org语句,则变量word1的偏移地址为0。
    word1 DW  1234h
    byte1  DB   56h
    word2 DW  abcdh
    其在数据段中word1,byte1,word2的存储位置如下图所示(采用小端存储,按单字节对齐)。

    在数据段中依次定义以下变量,由于此时使用org语句,则变量word1的偏移地址为1。
    org 0001h
    word1 DW  1234h
    byte1  DB   56h
    word2 DW  abcdh
    其在数据段中word1,byte1,word2的存储位置如下图所示(采用小端存储,按单字节对齐)。

    我们知道编译器本身在汇编时对指令的地址计算是相对地址,而对于引导扇区,是按绝对地址执行,那么对于用相对地址编译的执行码就要换算成绝对地址。一般而言,“真实开始执行的引导扇区”都会固定装载到07C00h处。

    由于编译器在编译时的地址是从第一行开始用0000h开始相对计算的,而且我们要写的是“引导扇区”程序,所以我们要将下面的代码加载到地址07C00h处,所以我们需要org 07C00h,通过该伪指令,将代码和数据加载到07C00h地址。

    2、jmp $

    $被称为当前位置计数器

    在汇编程序对源程序进行汇编的过程中,使用地址计数器来保证当前正在汇编的指令地址。地址计数器值可用“$”来表示,汇编语言也允许用户直接用“$”来引用地址计数器的当前值,因此,org $+5可表示从当前地址开始跳过5个字节存储单元,在指令和伪指令中,也可直接用“$”表示地址计数器的当前值。故jmp $进入了一个无限循环。

    3、int  10h

    int  10H号中断

    int 10H 是由BIOS 对屏幕及显示器所提供的服务程序。使用int 10H 中断服务程序时,先指定 AH 寄存器为下表编号其中之一,该编号表示欲调用的功用,而其他寄存器的详细说明,参考表后文字,当一切设定好之后再调用 int 10H。

    在这里我们只详细讲解本程序中的10号中断。由于ah=13,故调用编号为13的功能:即显示字符串。其中ES:BP=串地址,CX=串长度 ,AH=13,当AL=01h时,光标会跟随显示移动。BH为页号,BH=0表示页号为0,BL=0CH,表示属性,即黑底红字高亮。因此在调用10号中断之前,无非就是对各个寄存器进行初始化。

    4、times 510-($-$$)  db  0

    times:重复指令或数据

    times前缀引起指令被汇编多次。其中

    )次。也就是用0来填充剩下的空间,达到510字节。

     

    打开计算机电源;加电自检(POST);寻找启动盘,该系统设置从软盘启动,计算机检查软盘的0面0磁道1扇区,如果发现它以0xAA55结束,则BIOS会认为它是一个引导扇区;BIOS将该512字节扇区内容加载到内存地址0000:7c00;跳转到0000:7C00出将控制权交给这段引导代码。到此为止,计算机不再由BIOS中固有的程序来控制,而变成由操作系统的一部分来控制。

     

    展开全文
  • ”其实,在很多其他国家的网友肯定也如同我们一样,产生这样的疑问,拥有自己操作系统,而事实上,编者也在很多报道中,见到了诸如此类操作系统出现。  为何一直以来都有国家希望自主开发操作系统呢?原因大概...

    国内两款Linux操作系统

      很多人在使用一些操作系统的时候,经常会发问:“我们什么时候能有自己的操作系统?”其实,在很多其他国家的网友肯定也如同我们一样,产生这样的疑问,拥有自己的操作系统,而事实上,编者也在很多报道中,见到了诸如此类操作系统出现。

        为何一直以来都有国家希望自主开发操作系统呢?原因大概有两个,一个是可能带来的安全隐患。(尽管这种可能性有些“莫须有”,但是很多国家仍然在政府机构和军方IT系统上拒绝外国操作系统,正如美国官方拒绝华为设备进入美国政府机构IT系统一样),这是最重要的原因;另外,救活国内一批软件企业,打造自己的产业链,强大软件研发能力。

        就国内来说,其实2000前后多年间,有很多种操作系统诞生。国内大约从1999年开始在Linux操作系统上,也投入了大量的研究和市场化工作。当年的冲浪、蓝点、中软、中科红旗等企业都随着国际Linux热潮投身于Linux国产化研发,并先后发布了各自的国产Linux操作系统。随着Xteam Linux、BluePoint Linux、红旗Linux、COSIX Linux等国产Linux操作系统的出现,Linux从舶来品开始逐渐变为国产操作系统的主流,出现在大众视野。

       众所周知,目前Windows在桌面系统的排名在全球占绝对的领先优势,尽管因为Vista饱受诟病,但是Windows 7有帮助微软稳固了操作系统的霸主地位,这个数值已经超过了90%,其他所有的操作系统的市场占有率去瓜分剩下的10%。只不过,这些个操作系统很快就灰飞烟灭了。如今,官方提供支持的民用操作系统要属中科红旗的“红旗Linux”和中标软件最新推出的“中标麒麟”了。

        国内两款Linux操作系统

        国内Linux操作系统,编者在其他一些文章中也做过一些介绍。这里再重点剖析中科红旗的“红旗Linux”和中标软件最新推出的“中标麒麟”两款官方支持的操作系统。

        红旗Linux一直以来探索和迎合市场需求,坚持性能提升和创新。红旗Linux桌面操作系统6.0 SP3用户界面风格依然与Windows相似,支持中文和英文两种语言,基于X86平台对Intel EFI的支持;Linux下网页嵌入式多媒体插件的支持,实现了Windows Media Player和RealPlayer的标准JavaScript接口,参考Windows ASF格式规范编写了ASF/WMV Marker的支持,保证了基于Windows编写的在线多媒体播放网页的支持;前台窗口优化调度功能,通过内核级资源调度和前台窗口的自动跟踪工具,保证了前台窗口在合理的范围内以最大的系统资源运行。

        在云计算时代到来之际,红旗Linux操作系统也果断地选择了适应这一市场需求。同时,红旗Linux在嵌入式系统方面也与国内的IT厂商进行合作,在汽车行业内推出了很多独到的解决方案。

    盘点:2011年国内Linux OS那些发行版
    “红旗Linux”桌面操作系统

        由中标软件推出的中标普华Linux操作系统在2010年6月份面向全国开始推广中标普华5.0系列产品,希望能够成为"中国操作系统产业推动者"。这是一个积极的信号,同时启动面向全国个人用户的免费产品体验活动,同时他们也提出了这款Linux桌面操作系统的定位"简单、易用、高效的桌面系统"。

    无奇不有!盘点各国自己开发的操作系统
    “中标麒麟”Linux桌面操作系统

        不过,自2010年12月底,随着中标普华和国防科技大学的合作,中标普华Linux操作系统的名称将更改为“中标麒麟”,而且也进一步更换了新操作系统的Logo。官方对此的看法是,此次合作加强了中标普华Linux操作系统的安全性。

        介绍完国内操作系统的情况,下面让我们来仔细看一下国外都有哪些国家在研发自己的操作系统。按照时间顺序,编者按照先后顺序进行介绍。

    2日本的操作系统TRON

      日本这样的发达国家,也在很多年前,开始自主研发操作系统TRON,并且已经在国内广泛应用了。

        日本的操作系统TRON

        早在1984年,日本"TRON"操作系统就诞生了。当时,日本业界称这种自制的软件系统将可使日本计算机企业不必再为使用其他国家操作系统付费了,给予这个系统很高的期望值。

        准确地说,"TRON"是一种内嵌式操作系统,在微处理器中运行。"TRON"在个人电脑领域知名度几乎为零,但"TRON"现在却占据了全球微处理器操作系统市场上大约60%的份额。TRON”的主要开发者坂村健教授估计这一系统已经安装到了全球30亿到40亿台家用电子产品当中,远远超过其他操作系统的普及程度。

        同时,"TRON"系统从成本合算方面考虑是非常理想的,因为它是一个"公开源代码"的软件,就象Linux操作系统一样。这意味着"TRON"的源代码可以免费得到,使得工程师们根据自己的需求对其进行改动,就象一位大厨对已有的菜谱进行改进一样。

        目前,在日本,"TRON"面向社会是一种免费提供的软件。每个使用这种系统的用户对其性能方面用户都会深有感触。  

        坂村健其人

      坂村健,日本一名计算机工程师,坂村健在计算机行业内部可是大名鼎鼎,在日本国内知名度相当于比尔-盖茨。坂村健在20年前研发的一种操作系统名为"TRON"的系统可以免费嵌入到很多设备中,目前在日本国内手机、数码相机、汽车都设备中应用很广泛。

    无奇不有!盘点各国自己开发的操作系统
    坂村健,日本一名计算机工程师

      

    3古巴自主操作系统

        社会主义国家古巴,在自主开发操作系统的道路上做出了很多努力。

        古巴自主操作系统

      在2009年2月,古巴宣布他们已经自行开发了一套Linux操作系统Nova,用以抗争一些国家的霸权主义。据古巴政府表示,这套自行开发的Linux操作系统主要用以取代国内个人计算机上的微软系统。因为该国政府认为,其他国家的操作系统存在潜在的威胁。

      Nova操作系统就是古巴自行配置和捆绑打包的Linux分发版本,一些政府和大学系统已经转为Linux,但是一些国营公司没有采用这样的做法,因为其担心转换后一些专业程序无法使用。

        Nova操作系统是从自由软件(用户可自由使用和修改的软件)Linux操作系统开发而来的。除操作系统本身外,“诺瓦”还提供含有多个Linux应用软件的程序包。这一新系统目前已经在古巴海关、高等教育部和信息部使用。官方数据显示,古巴80%的网络和20%的终端目前已采用“诺瓦”系统。与一些商业软件不一样的是,Linux操作系统属于免费软件,而且其源代码对用户开放,允许用户根据自身需要进行修改。

        预计在五年内,古巴50%的PC机将迁移到Linux平台,特别是不少大学和政府部门正向Linux转移。古巴政府认为,转换到Linux后除了可以解决安全问题,自由软件也更适合古巴的世界观。

      据古巴信息科技大学软件学院的Hector Rodriguez院长表示,目前古巴销售给公众的电脑中,20%使用了Linux操作系统。

      Hector Rodriguez预计:"5年内古巴将有50%的计算机使用Linux系统。"他说:"私人软件(Windows等商业软件)可能包含他人所不知的漏洞和恶意代码,而免费软件则不然。"

    4法国轻量级操作系统

        法国轻量级操作系统

        2009年,一个法国的轻量级操作系统SliTaz GNU/Linux诞生了。

      SliTaz GNU/Linux是一个法国的轻量级操作系统,它能够完全在内存中运行。SliTaz以Live CD的形式发布,你可以把它刻到一张CD上,然后用这来启动你的电脑。在启动之后,你就可以把它从光驱中拿出来了,整个系统已经载入了内存当中,你可以把其它要用的光碟放进光驱里了。同时,SliTaz还提供了免费的技术支持,你可以通过发送邮件或者是到社区论坛提问来获得支持。

    无奇不有!盘点各国自己开发的操作系统

      SliTaz GNU/Linux是一份迷你发行,它是一张被设计为能在仅有128MB RAM的硬件上流畅运行的自启动运行光盘。SliTaz使用了BusyBox,一份新近的Linux内核,以及GNU软件。它以Syslinux引导,提供超过200个Linux命令、lighttpd网页服务器、SQLite数据库、灾难恢复工具、IRC客户端、基于Dropbear的SSH客户端和服务器、 X窗口系统、JWM(Joe's Window Manager)、gFTP、Geany IDE、Mozilla Firefox、AlsaPlayer、GParted,以及一份声音文件编辑器等。SliTaz的光盘镜像文件可载入到30MB大小的媒质中,它只需 80MB的硬盘空间就能运行。

      尽管SliTaz的体积很小(每个版本都控制在30M以内),但它的功能却一点也不弱。SliTaz使用的是JWM(Joe's Window Manager)桌面环境,并且默认是有四个虚所桌面。SliTaz集成了很多有用的软件,你可以用它来完成各种任务,详细的软件列表请看稳定版软件列表和测试版软件列表。如果你已经运行了SliTaz系统,你可以在 /var/lib/tazpkg/packages.txt这个文件中看到你系统中包含的软件。

      SliTaz使用的是Tazpkg软件包管理器,你可以通过Tazpkg来获得安全更新。你也可以通过安装别的软件来扩展SliTaz的功能,SliTaz安装软件的命令是tazpkg get-install package_name(是不是感觉和apt有点相似啊!)。如果你使用的是测试版的话,你还可以像使用Synaptic(新立得)一样,在图形化的界面上安装软件。当你想自己定制SliTaz时,你可以通过系统自带的一个Tazlito工具来重新定制你的系统

      

    5俄罗斯自主操作系统

        尚未解体的苏联与美国冷战了多年,所以如今的俄罗斯拥有最大的理由发展自主的操作系统。

        俄罗斯自主操作系统

      2009年1月24日,俄罗斯政府筹划开发一个全国性的操作系统,目的是减少对国外操作系统的依赖,更好地监管计算机系统安全。目前,俄罗斯政府的自主操作系统的的计划仍然是基于开源的Linux之上。

      接着,在2010年10月,俄罗斯政府这一计划落实到具体投资金额上——1.5亿卢布(约合490万美元),开发一款基于Linux的自主的国家的操作系统。俄罗斯政府计划在其IT部门采用一种“Windows替代系统”,以减少对美国软件巨人微软的依赖。 

        目前我们还很难见到一款称之为俄罗斯国家操作系统的软件问世,不过俄罗斯国人在基于Linux的操作系统上是早有作为。

    无奇不有!盘点各国自己开发的操作系统

        如,ALT Linux是一款始于2001年的操作系统,由两个大的俄罗斯自由软件计划合并而来。2008年它成为了一个大的组织,从事自由软件的开发和部署、文档和技术资料撰写、用户支持及定制产品开发工作。ALT Linux面向不同的目的生产不同类型的发行。这包括面向家庭、办公计算机、企业服务器的各种桌面发行,广泛包含各种开发工具和文档的通用发行,认证产品,面向教育机构的专用发行,以及面向低端计算机的发行。ALT Linux拥有自己的基础开发设施和软件仓库,称为Sisyphus,它为所有不同类型的ALT Linux提供基础。

        不过,俄罗斯政府官员也承认一点,开发自主操作系统存在完全照搬Linux的风险。

       

    6韩国自主的操作系统

        韩国自主的操作系统

        与其他国家的磨磨蹭蹭相比,韩国推出自主的操作系统要积极主动很多。2009年7月,韩国已经率先推出自己的操作系统。

      韩国TmaxCore公司耗时四年研发的自主操作系统Tmax Windows的问世也让业界一片哗然。不过,据报道,Tmax Windows操作系统可完全兼容微软Windows系列操作系统。

      据了解,TmaxCore公司隶属于韩国最大的软件公司TmaxSoft,是韩国独家操作系统开发公司。韩国研发自主操作系统已经有16年历史,最早的操作系统为K-DOS。Tmax Windows发布会上有上万名公众、媒体、分析家、博客作者以及IT人员参加,足以表明他们对可兼容微软Windows的首个操作系统的兴趣。

      目前该公司演示的Tmax Windows产品虽然只是测试版本,但是在开发上他们是以100%兼容微软Windows为目标。TmaxCore预期该产品发布后,会对微软垄断的操作系统市场造成冲击。

      TmaxCore现在主要在与PC制造商、芯片组、显卡、其他硬件制造商进行兼容性测试。10月份将发布一个月的免费测试版,11月份该产品将正式上市。

      Tmaxcore是韩国软件巨头TmaxSoft的下属公司,此次截图内容包括Tmax操作窗口、Scoutor浏览器以及Tmax Office办公软件。另外,这款十六年来韩国软件公司自主开发的操作系统售价要比Windows系统低廉超过50%。   

        据悉,在Tmacore公司发布Tmax的截图之后,不少用户质疑图片被PS处理过。Tmaxcore对传言表现得相当自信,并坚称所有真相会在7月7日,Tmax OS发布当天揭晓。

      Tmax Windows系统的特点将包括:

      1、与微软Windows及Office程序高度兼容

      2、利用Micro kernel保证稳定性

      3、程序移植性高,支持各种操作系统上运行的程序。

      4、内置数据库管理系统(DBMS,Database management system)

      5、可根据企业及用户需求定制安全设置

      6、为用户提供熟悉的操作界面

      因为如上优势,微软Windows用户可以很容易切换到Tmax Windows平台,同时Tmax Windows的价格预计只有微软Windows价格的一半左右,从而成为微软Windows的竞争对手。

      据悉,Tmax Windows的启动速度比微软Windows更快,同时Tmax Windows还可以运行微软Office办公软件、IE浏览器。从而证明该产品可以完美兼容微软Windows上的各种应用程序。

    7印度自主操作系统

        印度自主操作系统

        2010年10月,印度政府表示,印度计划开发一种新型的计算机操作系统,希望能提高该国计算机系统的安全性能。印度国防部长科技顾问、国防研究与发展组织(以下简称"DRDO")发言人Ravi Kumar Gupta表示,这个新的操作系统正由DRDO进行开发。

      DRDO是印度国防部的一个分支,拥有约50个专门进行技术开发的实验室,覆盖的领域包括航空、军事装备、电子、战斗车辆、工程系统、仪器仪表、导弹、先进的计算和模拟、特殊材料、海军系统、生命科学、培训、信息系统和农业。

        印度国防研究发展机构(DRDO)的最高领导VK.Saraswat表示,印度的这种新操作系统能在很大程度上提升网络安全。"我们还没有自己的操作系统,现在,各种实体,包括银行和国防组织,都需要网络安全。拥有自己的操作系统,将有效的帮助我们的系统阻止黑客入侵。在开始阶段,我们在班加罗尔和新德里建立软件工程中心,每个中心有25名科学家,印度科学院,马德拉斯理工学院,C-DOT公司和其它的高校以及私立学院都将会加入这项研究任务"

      据了解,印度这项本土化计算机工程于9月份启动,工程发展的路线图也已经准备开始实施。

      从经验来看,几乎所有国家开发自主的操作系统,都自称是基于安全方面的考虑。不过,这一考虑,可能也意味这国家要为此付出沉重的经济代价。印度官方也表示,尽管这个新的操作系统一开始将开发用于国防应用,但是可能适用于商业领域。这也是应用推广的一种措施。

      不过,印度官方并没有该操作系统的其他细节并未公布,包括上市日期。

    8伊朗自制电脑操作系统

        伊朗自制电脑操作系统

      2011年5月30日,中东北非借互联网掀起的反政府浪潮似乎对伊朗产生了触动,为了应对西方利用互联网对其进行渗透,伊朗已开发出新型的"内联网"(Internal network)系统,并准备在两年内将其推广至全国。

      有媒体报道,在伊朗电信部长Reza Taghipour领导下,伊朗成功开发了这种新型网络系统,可以将伊朗国内的网络与外部世界彻底切断。

      伊朗经济事务主管阿里·阿加莫罕马迪表示,这一新型的内联网开始将与普通互联网同时运行,银行、政府部门及大企业仍可以接入普通互联网。但它最终将在伊朗取代互联网,其他穆斯林国家也可以这样。"伊朗国有的网络将是真正的伊斯兰教义的网络,在宗教和道德层面面向广大穆斯林。"他说。伊朗电信部下属的研究院院长Reza Bagheri Asl2月曾表示,伊朗全国60%的家庭和企业将用上这一新型的"内联网"。

      另据伊朗媒体报道,伊朗还计划于未来数月内推出自制电脑操作系统,替换现有的微软WINDOWS系统。

      伊朗与美国等西方国家长期对立。自1979年建立伊斯兰共和国以来,伊朗就一直认为美国等西方国家的价值观念、文化和影响力是对其国家利益的重大威胁,而互联网则是西方传播其价值观和文化的重要手段。

      不过外界并不认为伊朗真的能够仅仅使用"内联网",因为虽然伊朗受西方制裁,但互联网仍是该国与俄罗斯等贸易伙伴做生意的重要工具,所以内联、互联并行似乎更实际。

        所以,从这些消息看来,伊朗自主操作系统还只是一个想法,甚至还没用筹措到具体的经费,路漫漫其修远。

    9朝鲜自主操作系统

      朝鲜自主操作系统

        在网友的眼中朝鲜是一个相对闭塞的国家,所以,关于朝鲜开发的自主操作系统红星操作系统还是从一些其他国家媒体活动的。

        2010年3月,朝鲜已研发出基于Linux的自主操作系统 ,该操作系统也拥有与Windows操作系统非常相似的图形用户界面,分为分为客户端和服务器两种版本。

    无奇不有!盘点各国自己开发的操作系统

      这个操作系统被认为是稳定的,而且启动速度很快,大约只需要15分钟就可安装好全部系统,但只提供单一的语言:朝鲜语。屏幕显示的桌面界面与Windows非常相似,似乎是基于新发行的KDE版本。被称为“我的国家”的红星浏览器,是基于火狐浏览器而开发的,它允许用户访问朝鲜网络系统“我的国家论坛”。

      据了解,“红星操作系统”的其他部分包括文字处理器、电子邮件客户端、反病毒软件、多媒体播放器以及一些游戏。

     

        小结:环顾国内外各国自主开发操作系统的环境,编者发现,政府组织人力和物力开发出来一种基于Linux的自主操作系统,而更多是出于国家安全上的考虑,更多用于政府的重要部门内部。有些国家开发了商用的版本,但是真正在推广的时候却遇到了用户的决绝,关键问题是对于普通用户来说仍然不够便捷、简单易操作、应用性也不够等。所以,即使是开发了自主操作系统,我们看到也并没有见到一边倒的趋势:民众都自愿去选择自己国家的操作系统安装,而仍然是选择全球最好用的操作系统(暂且不论正版还是盗版)。很显然,这不是哪个国家的民众的觉悟高低问题。

        可以说,要发展国产操作系统最好的方式,还是要走出去接受市场的考验。不过,在当前Windows、Mac OS等操作系统的巨大压力下,走出去则生死未卜,退回来则发展绵力,这是一个进退两难的问题。经过这些年的发展,通过政府采购,政府专项的扶持,自主操作系统也在渐渐尝试丢掉拐杖,更多地走向实现与市场需求的良好互动,靠市场牵动发展,而不是专项扶持资金。这是一个好的迹象。


    展开全文
  • 在STM32上创建一个自己操作系统

    千次阅读 2019-08-22 11:02:47
    之前看了蛮多帖子,不过苦于自己对着基本上是门外汉,基本上只明白个大概,幸亏找到一个分享源码的帖子,在这上面我也实现了一个操作系统的移植;同时我也感觉到了自己学习的不足,以前总以为会用几款单片机就觉得...

    参考文章:http://www.cnblogs.com/ansersion/p/4328800.html

     

    二维码是我创建的QQ群,欢迎新朋友加入。

     

    之前看了蛮多帖子,不过苦于自己对着基本上是门外汉,基本上只明白个大概,幸亏找到一个分享源码的帖子,在这上面我也实现了一个操作系统的移植;同时我也感觉到了自己学习的不足,以前总以为会用几款单片机就觉得单片机学完了,这段时间看系统的内容才发现自己原来在技术方面的欠缺这么大;

     

     

    我的代码基本上和参考文章差不多,毕竟自己也不是很明白,门外汉嘛。

     

    硬件平台:秉火开发板

    软件平台:野火STM32工程模板(103系列)

    系统参考来源:UCOS

     

    我看源码的方式可能不一样,我是从ASM开始的

    1.首先是:

     

        IMPORT     OSTCBCur
        IMPORT    OSTCBNext
        
        EXPORT    OS_ENTER_CRITICAL
        EXPORT    OS_EXIT_CRITICAL
        EXPORT    OSStart
        EXPORT    PendSV_Handler
        EXPORT    OSCtxSw

    这里涉及到一个ASM的语法,就是IMPORT和EXPORT不能顶格写,我自己因为从来没接触过汇编,查了蛮久的资料才晓得的;

     

     

    这有两个函数:

    IMPORT ,定义表示这是一个外部变量的标号,不是在本程序定义的
    EXPORT ,表示本程序里面用到的变量提供给其他模块调用的。

    先说下IMPORT 的内容,汇编里面,他是从外面调用的

     

        IMPORT     OSTCBCur
        IMPORT    OSTCBNext

    看一下我的代码里面这两个变量的来源(虽然是抄袭的别人的代码,我也不害臊的称之为我的吧)

     

     

    typedef struct os_tcb {
        OS_STK    *OSTCBStkPtr;     // (OS Task Control Block Stack Pointer)
        INT8U     OSTCBStat;        // (OS Task Control Block Status)
    } OS_TCB;                       // (OS Task Control Block)
    
    extern OS_TCB *OSTCBCur;  // Pointer to the current running task(OS Task Control Block Current)
    extern OS_TCB *OSTCBNext; // Pointer to the next running task(OS Task Control Block Next)

    这里给结构体OS_TCB传入了两个参数,OSTCBCur指向当前运行任务的指针  OSTCBNext指向下一个运行任务的指针

     

    这个东西其实我们早有接触,不知道大家有没没有注意,我们做硬件仿真的时候,点击复位,指针的指向位置:

     

    ; Reset handler
    Reset_Handler   PROC
                    EXPORT  Reset_Handler             [WEAK]
                    IMPORT  __main
                    IMPORT  SystemInit
                    LDR     R0, =SystemInit
                    BLX     R0               
                    LDR     R0, =__main
                    BX      R0
                    ENDPLDR     R0, =SystemInit
                    BLX     R0               
                    LDR     R0, =__main
                    BX      R0
                    ENDP

    我们32运行的时候首先执行了一个sysyteminit,然后再去执行我们的main函数
     

     

    然后是EXPORT 内容,这是本函数自己定义的,就没什么好说的了;

     

        EXPORT    OS_ENTER_CRITICAL
        EXPORT    OS_EXIT_CRITICAL
        EXPORT    OSStart
        EXPORT    PendSV_Handler
        EXPORT    OSCtxSw

     

     

    2.NVIC中断向量

     

    NVIC_INT_CTRL    EQU         0xE000ED04    ; Address of NVIC Interruptions Control Register
    NVIC_PENDSVSET   EQU         0x10000000    ; Enable PendSV
    NVIC_SYSPRI14    EQU         0xE000ED22  ; System priority register (priority 14).
    NVIC_PENDSV_PRI  EQU         0xFF        ; PendSV priority value (lowest).

     

     

    ;/******************OSStart************/
    OSStart
        ; disable interruptions
        CPSID    I                            ; OS_ENTER_CRITICAL();
        ; initialize PendSV
        ; Set the PendSV exception priority
        LDR     R0, =NVIC_SYSPRI14            ; R0 = NVIC_SYSPRI14;
        LDR     R1, =NVIC_PENDSV_PRI          ; R1 = NVIC_PENDSV_PRI;
        STRB    R1, [R0]                      ; *R0 = R1;
        
        ; initialize PSP as 0
        ; MOV    R4, #0
        LDR R4,  =0x0                            ; R4 = 0;
        MSR    PSP, R4                           ; PSP = R4;
        
        ; trigger PendSV
        LDR    R4, =NVIC_INT_CTRL              ; R4 = NVIC_INT_CTRL;
        LDR    R5, =NVIC_PENDSVSET             ; R5 = NVIC_PENDSVSET;
        STR    R5, [R4]                        ; *R4 = R5;
        
        ; enable interruptions
        CPSIE    I                            ; OS_EXIT_CRITICAL();


    这里我参考的帖子是:http://www.cnblogs.com/13chfang/p/6151565.html

     

     

    这是一段从ucos截取出来的代码,这段汇编程序其实特别简单,做了以下几个事情:

    1.将pendSV中断设置为最低优先级

    LDR ...=:伪指令,参数、地址传递用的

    STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。

    1      LDR     R0, =NVIC_SYSPRI14                                  ; Set the PendSV exception priority
    2      LDR     R1, =NVIC_PENDSV_PRI
    3      STRB    R1, [R0]

    2.将PSP置0

    特权级下用MSP,用户级用PSP。

    1     MOVS    R0, #0                                              ; Set the PSP to 0 for initial context switch call
    2     MSR     PSP, R0

    3.分配堆栈给MSR,这个堆栈的作用其实是在中断嵌套的时候可以将寄存器和局部变量等进行入栈。如果中断程序较大的话或者中断嵌套较多的话,建议将这个堆栈空间设置得更大一些,我们不能只是关心任务堆栈。PS.取最后一个数组元素地址的原因是因为我们CM3的堆栈方向是从高到低的。

    简单普及一下:MSR的意思是move to special register from  register的缩写,可以将普通寄存器的数值保存到xpsr寄存器中。

    复制代码

    1 ;/*在前面的头文件里定义的,这里这是写出来容易看*/
    2 ;unsigned int* OS_CPU_ExceptStackBase = &CPU_ExceptStack[1023];
    3 
    4 
    5     LDR     R0, = OS_CPU_ExceptStackBase                          ; Initialize the MSP to the OS_CPU_ExceptStkBase
    6     LDR     R1, [R0]
    7     MSR     MSP, R1    

    复制代码

    4.触发pendSV异常,实现任务切换,顺便enable interrupts.

    (查了资料CPSID/CPSIE就是开关终端的东西)

        LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
        LDR     R1, =NVIC_PENDSVSET
        STR     R1, [R0]
        
        CPSIE   I                                                   ; Enable interrupts at processor level

     


    根据这段内容,知道我的代码里面内容的含义:

     

    CPSID    I                            ; OS_ENTER_CRITICAL();

    关闭中断
     

    LDR     R0, =NVIC_SYSPRI14            ; R0 = NVIC_SYSPRI14;
        LDR     R1, =NVIC_PENDSV_PRI          ; R1 = NVIC_PENDSV_PRI;
        STRB    R1, [R0]                      ; *R0 = R1;

    设置中断优先级

     

     

       ; initialize PSP as 0
        ; MOV    R4, #0
        LDR R4,  =0x0                            ; R4 = 0;
        MSR    PSP, R4                           ; PSP = R4;

    通用寄存器把参数0送到状态寄存器里面

     

     

    ; trigger PendSV
        LDR    R4, =NVIC_INT_CTRL              ; R4 = NVIC_INT_CTRL;
        LDR    R5, =NVIC_PENDSVSET             ; R5 = NVIC_PENDSVSET;
        STR    R5, [R4]                        ; *R4 = R5;

    使能PENSV悬起寄存器

     

     

    ; enable interruptions
        CPSIE    I                            ; OS_EXIT_CRITICAL();

    开中断

     

     

    这个内容在我的代码里面只执行一次

    位置是主函数:

     

    OSStart(); // start os!

    开启系统任务

     

     

    3.任务切换的实现

    用的是OSStart(); // start os!里面初始化的PENSV异常服务;
    先来段别人的解释吧,我解释的可能比较词穷

     

    10.SVC(系统服务调用,亦简称系统调用)和 PendSV(可悬起系统调用),它们多用在上了操作系统的软件开发中。 SVC 用于产生系统函数的调用请求。例如,操作系统通常不让用户程序直接访问硬件,而是通过提供一些系统服务函数,让用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就要产生一个SVC 异常,然后操作系统提供的 SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。    

        这种“提出要求——得到满足”的方式,很好、很强大、很方便、很灵活、很能可持续发展。首先,它使用户程序从控制硬件的繁文缛节中解脱出来,而是由 OS 负责控制具体的硬件。第二,OS 的代码可以经过充分的测试,从而能使系统更加健壮和可靠。第三,它使用户程序无需在特权级序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,从而简化了开发的难度和繁琐度,并且使应用程序跨硬件平台移植成为可能。开发应用程序唯一需要知道的就是操作系统提供的应用编程接口( API),并且在了解了各个请求代号和参数表后,就可以使用 SVC 来提出要求了。SVC 异常通过执行”SVC”指令来产生。该指令需要一个立即数,充当系统调用代号。 SVC 异常服务例程稍后会提取出此代号,从而获知本次调用的具体要求,再调用相应的服务函数。例如,

                                                     SVC 0x3 ; 调用 3 号系统服务
          在 SVC 服务例程执行后,上次执行的 SVC 指令地址可以根据自动入栈的返回地址计算出。找到了 SVC 指令后,就可以读取该 SVC 指令的机器码,从机器码中萃取出立即数,就获知了请求执行的功能代号。如果用户程序使用的是 PSP,服务例程还需要先执行 MRS Rn, PSP 指令来获取应用程序的堆栈指针。通过分析 LR 的值,可以获知在 SVC指令执行时,正在使用哪个堆栈。

      11.另一个相关的异常是 PendSV(可悬起的系统调用),它和 SVC 协同使用。一方面, SVC 异常是必须在执行 SVC 指令后立即得到响应的(对于 SVC 异常来说,若因优先级不比当前正处理的高,或是其它原因使之无法立即响应,将上访成硬 fault),应用程序执行 SVC 时都是希望所需的请求立即得到响应。另一方面, PendSV 则不同,它是可以像普通的中断一样被悬起的(不像SVC 那样会上访)。 OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动作。悬起 PendSV 的方法是:手工往 NVIC 的 PendSV 悬起寄存器中写 1。悬起后,如果优先级不够高,则将缓期等待执行。PendSV 异常会自动延迟上下文切换的请求,直到其它的 ISR 都完成了处理后才放行。为实现这个机制,需要把 PendSV 编程为最低优先级的异常。

        

    以上内容为基于CM3内核开发一个实时操作系统我们需要知道的一些关于CM3的知识,建议去看《CM3权威指南Cn

     

    这就是前辈对这个异常服务的解释,在代码里面如果把这内容拆解:

     

    ;/******************PendSV_Handler************/
    PendSV_Handler
        CPSID    I                            ; OS_ENTER_CRITICAL();
        ; judge if PSP is 0 which means the task is first invoked
        MRS     R0, PSP                            ; R0 = PSP;
        CBZ     R0, PendSV_Handler_NoSave          ; if(R0 == 0) goto PendSV_Handler_NoSave;
        
        ;     R12, R3, R2, R1
        SUB     R0, R0, #0x20            ; R0 = R0 - 0x20;
        
        ; store R4 
        STR     R4 , [R0]                ; *R0 = R4;
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;
        ; store R5 
        STR     R5 , [R0]                ; *R0 = R5;
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;
        ; store R6 
        STR     R6 , [R0]                ; *R0 = R6;
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;
        ; store R7 
        STR     R7 , [R0]                ; *R0 = R7;
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;
        ; store R8 
        STR     R8 , [R0]                ; *R0 = R8;
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;
        ; store R9
        STR     R9, [R0]                ; *R0 = R4;
        ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
        ; store R10 
        STR     R10, [R0]               ; *R0 = R10;
        ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
        ; store R11 
        STR     R11, [R0]               ; *R0 = R11;
        ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
    
    
        SUB     R0, R0, #0x20           ; R0 = R0 - 0x20;
        
        ; easy method
        ;SUB     R0, R0, #0x20
        ;STM     R0, {R4-R11}
        
        LDR     R1, =OSTCBCur            ; R1 = OSTCBCur;
        LDR     R1, [R1]                 ; R1 = *R1;(R1 = OSTCBCur->OSTCBStkPtr)
        STR     R0, [R1]                 ; *R1 = R0;(*(OSTCBCur->OSTCBStkPrt) = R0)
    
    
    PendSV_Handler_NoSave
        LDR     R0, =OSTCBCur           ; R0 = OSTCBCur;
        LDR     R1, =OSTCBNext          ; R1 = OSTCBNext;
        LDR     R2, [R1]                ; R2 = OSTCBNext->OSTCBStkPtr;
        STR     R2, [R0]                ; *R0 = R2;(OSTCBCur->OSTCBStkPtr = OSTCBNext->OSTCBStkPtr)
        
        LDR     R0, [R2]                 ; R0 = *R2;(R0 = OSTCBNext->OSTCBStkPtr)
        ; LDM     R0, {R4-R11}
        ; load R4 
        LDR     R4, [R0]                 ; R4 = *R0;(R4 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        ; load R5 
        LDR     R5, [R0]                 ; R5 = *R0;(R5 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        ; load R6
        LDR     R6, [R0]                 ; R6 = *R0;(R6 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        ; load R7 
        LDR     R7 , [R0]                ; R7 = *R0;(R7 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        ; load R8 
        LDR     R8 , [R0]                ; R8 = *R0;(R8 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        ; load R9 
        LDR     R9 , [R0]                ; R9 = *R0;(R9 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        ; load R10 
        LDR     R10 , [R0]               ; R10 = *R0;(R10 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        ; load R11 
        LDR     R11 , [R0]               ; R11 = *R0;(R11 = *(OSTCBNext->OSTCBStkPtr))
        ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
        
        MSR     PSP, R0                 ; PSP = R0;(PSP = OSTCBNext->OSTCBStkPtr)
        ; P42
        ; P139 (key word: EXC_RETURN)
        ; use PSP
        ORR     LR, LR, #0x04           ; LR = LR | 0x04;
        CPSIE     I                     ; OS_EXIT_CRITICAL();
        BX    LR                        ; return;

     

     

    太长了,我根据注解自己尝试着修改了下

     

     

    ;/******************PendSV_Handler************/
    PendSV_Handler
        CPSID    I                            ; OS_ENTER_CRITICAL();
        ; judge if PSP is 0 which means the task is first invoked
        MRS     R0, PSP                            ; R0 = PSP;
        CBZ     R0, PendSV_Handler_NoSave          ; if(R0 == 0) goto PendSV_Handler_NoSave;
        
        SUB     R0, R0, #0x20            ; R0 = R0 - 0x20;
        
        ; easy method
        STM     R0, {R4-R11}
        
        LDR     R1, =OSTCBCur            ; R1 = OSTCBCur;
        LDR     R1, [R1]                 ; R1 = *R1;(R1 = OSTCBCur->OSTCBStkPtr)
        STR     R0, [R1]                 ; *R1 = R0;(*(OSTCBCur->OSTCBStkPrt) = R0)
    
    PendSV_Handler_NoSave
        LDR     R0, =OSTCBCur           ; R0 = OSTCBCur;
        LDR     R1, =OSTCBNext          ; R1 = OSTCBNext;
        LDR     R2, [R1]                ; R2 = OSTCBNext->OSTCBStkPtr;
        STR     R2, [R0]                ; *R0 = R2;(OSTCBCur->OSTCBStkPtr = OSTCBNext->OSTCBStkPtr)
        
        LDR     R0, [R2]                 ; R0 = *R2;(R0 = OSTCBNext->OSTCBStkPtr)
        LDM     R0, {R4-R11}
        ADDS    R0, R0, #0x20
    
        MSR     PSP, R0                 ; PSP = R0;(PSP = OSTCBNext->OSTCBStkPtr)
        ; P42
        ; P139 (key word: EXC_RETURN)
        ; use PSP
        ORR     LR, LR, #0x04           ; LR = LR | 0x04;
        CPSIE     I                     ; OS_EXIT_CRITICAL();
        BX    LR                        ; return;
    


    这样汇编部分基本做完了,

     

    我代码里面其他的汇编内容好像影响不是特别大,不是核心的,就不说了

    4.任务创建

     

    OS_STK* OSTaskStkInit(void (*task)(void *p_arg),
              void *p_arg,
              OS_STK *p_tos)
    {
        OS_STK *stk;
        stk = p_tos;
    
        *(stk)    = (INT32U)0x01000000L;             // xPSR                                               
        *(--stk)  = (INT32U)task;                    // Entry Point  
    
        // Don't be serious with the value below. They are of random
        *(--stk)  = (INT32U)0xFFFFFFFEL;             // R14 (LR) 
        *(--stk)  = (INT32U)0x12121212L;             // R12                                                
        *(--stk)  = (INT32U)0x03030303L;             // R3                                                 
        *(--stk)  = (INT32U)0x02020202L;             // R2                                                 
        *(--stk)  = (INT32U)0x01010101L;             // R1                                                 
    
        // pointer of the argument
        *(--stk)  = (INT32U)p_arg;                   // R0
    
        // Don't be serious with the value below. They are of random
        *(--stk)  = (INT32U)0x11111111L;             // R11 
        *(--stk)  = (INT32U)0x10101010L;             // R10 
        *(--stk)  = (INT32U)0x09090909L;             // R9  
        *(--stk)  = (INT32U)0x08080808L;             // R8  
        *(--stk)  = (INT32U)0x07070707L;             // R7  
        *(--stk)  = (INT32U)0x06060606L;             // R6  
        *(--stk)  = (INT32U)0x05050505L;             // R5  
        *(--stk)  = (INT32U)0x04040404L;             // R4  
        return stk;
    }

    借用别人的一个描述

     

     

     void vTaskCreate(TCB* tcb,void (*task)(void),unsigned int* stack)
    16 {
    17         unsigned int *pstrStack;
    18         pstrStack = stack;
    19         pstrStack = (unsigned int*)    ((unsigned int)(pstrStack)&0xfffffff8u);/* 8字节对齐 */
    20         *(--pstrStack) = (unsigned int)0x01000000ul; /* XPSR*/
    21         *(--pstrStack) = (unsigned int)task;       /* r15 */
    22         *(--pstrStack) = (unsigned int) Task_End;       /* r14 */
    23         *(--pstrStack) = (unsigned int)0x12121212ul;    /*r12*/
    24         *(--pstrStack) = (unsigned int)0x03030303ul;    /*r3*/
    25         *(--pstrStack) = (unsigned int)0x02020202ul;    /*r2*/
    26         *(--pstrStack) = (unsigned int)0x01010101ul;    /*r1*/
    27         *(--pstrStack) = (unsigned int)0x00000000ul;    /*r0*/
    28     
    29         *(--pstrStack) = (unsigned int)0x11111111ul;    /*r11*/
    30         *(--pstrStack) = (unsigned int)0x10101010ul;    /*r10*/
    31         *(--pstrStack) = (unsigned int)0x09090909ul;    /*r9*/
    32         *(--pstrStack) = (unsigned int)0x08080808ul;    /*r8*/
    33         *(--pstrStack) = (unsigned int)0x07070707ul;    /*r7*/
    34         *(--pstrStack) = (unsigned int)0x06060606ul;    /*r6*/
    35         *(--pstrStack) = (unsigned int)0x05050505ul;    /*r5*/
    36         *(--pstrStack) = (unsigned int)0x04040404ul;    /*r4*/
    37         
    38         tcb->pstrStack = pstrStack;
    39 }

    复制代码

     

    我们程序做得工作主要如下:
    (1)传进了三个参数,参数1:任务TCB指针,这是一个结构体指针,此时首地址是我们存的是pstrStack;参数2是任务函数指针,也就是我们希望调用一个任务后他执行的函数; 参数3是我们分配的堆栈栈顶,可以使用动态分配或者静态分配,我们这里其实是定义了一个数组,传进来的数组的最后一个元素的地址(因为栈的生长方向是从高到低的)。

    (2)定义一个变量pstrStack指针指向栈顶,接下来程序里做的事情是初始化中断返回后从栈中恢复的8个寄存器。首先初始化的是xPSP寄存器,将它的第24位置1,表示处于Thumb状态;在c语言中,我们的函数名就是函数的首地址,从这个地址开始存放着函数的指令,我们只需跳转到这个地址就可以执行函数,所以我们开始运行一个任务需要做的事情就是跳转到这个任务的函数名,所以我们接下来做的事就是让PC寄存器指向该函数的首地址;接下来我们初始化的是LR寄存器,用来保存函数的返回地址, 我们任务执行到最后会跳转到LR寄存器指向的地址,所以如果我们的任务没有写成无限循环的形式的话,最后就会跳转到LR指向的地址。为了防止因为我们忘记将任务写成无限循环而出现系统奔溃情况,我们将LR寄存器指向了一个无限循环的函数Task_End()的地址,这增加了我们代码的健壮性。在ucos中,系统在这个函数里面可以将任务删除掉。

    (3)后面的寄存器我们都是简单地随便赋值,其实是为了debug可以方便点。但是其实我们还是要关注R0~R3这四个寄存器的。在ARM中(如果我没记错的话),函数传参的时候,前四个形参都是直接都过R0~R3这四个寄存器实现参数传递的,当形参个数大于4个的话,其余的入口参数则依次压入当前栈,通过栈传参。还有一个比较重要的,我们子函数通过R0寄存器将函数返回值传递给父函数。所以,我们如果要给我们的任务函数传参,我们需要把传进来的形参存放到R0~R3寄存器中。比如uCOS和freeRTOS就都用R0寄存器传参给任务函数,uCOS还通过R1存放堆栈限制增长到的内存地址。

    (4)最后,我们将我们初始化好的任务堆栈地址赋值给我们任务TCB的pstrStack指针。我们只要将这个指针指向的地址赋值给我们的OSTCBHighRdyPtr就可以任务的切换了。

    看一下在主函数里面对任务的创建

     

    OSTaskCreate(Task1, (void*)0, (OS_STK*)&Task1Stk[TASK_STACK_SIZE-1]); // create task 1
        OSTaskCreate(Task2, (void*)0, (OS_STK*)&Task2Stk[TASK_STACK_SIZE-1]); // create task 2
        OSTaskCreate(Task3, (void*)0, (OS_STK*)&Task3Stk[TASK_STACK_SIZE-1]); // create task 3


    主函数里面就是很普通的系统使用了,跟UCOS差不多,没什么好讲的;

     

    本文上传代码:(可能大神们觉得这很简单吧,都不传代码,那我这种小白就乖乖的发出来了)
    资源名称:我的第一个实时操作系统

     

     

    展开全文
  • 操作系统操作系统内核

    万次阅读 多人点赞 2017-07-07 16:21:37
    总的说来,一个操作系统包含了内核(是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件)以及其他计算机系统所必须的组件(如函数库、编译器、调式工具、文本编辑器、网站服务器,以及一个Unix的...

    一、前言

        最近看了一篇将Unix和Linux历史的帖子,虽然有点水,但是还是放个链接吧花了一天时间,终于把unix、linux、ios、android区别大致联系搞清楚,好像很复杂的,这个帖子写的比较口水话,但是对于了解Unix与Linux的发展与历史还是蛮有帮助的,看了这篇帖子之后,尽管知道了Unix与Linux从无到有的过程,但是发现自己对操作系统这个东西的认识更加模糊了,因为前期大致读过《深入理解计算机系统》和《操作系统》两本书,了解过一些操作系统的内容,但由于是非科班出身,有很多本质的概念并不理解,所以这里就回顾了上面两本书中的一些内容,再加上网上的一些资料,对操作系统和操作系统内核这两个概念进行了整理。


    二、操作系统理解

       一句话理解操作系统:操作系统就是为用户(使用计算机的人)提供服务,使用户能在计算机上使用各种应用程序(QQ、浏览器)来操作计算机资源(如QQ需要使用显示器资源、用浏览器下载资料需要硬盘资源,同时所有这些应用程序都需要使用CPU这个最主要的资源)。

        可以从两方面理解上面这句话,一方面从操作系统本身来理解。其实说起操作系统这个概念,作为非科班出身的我们大多都是比较模糊的,同时感觉跟这个东西就很近,因为在每台计算机中都有一个操作系统,你运行的任何应用软件都离不开操作系统,为什么离不开操作系统呢?其实说白了,一台计算机就是一组资源,你运行在计算机上的应用程序本质上是离不开计算机的各种资源(如处理器、内存、I/O设备等),只是为了方便,人们就构造了操作系统这种东西,因为每一台计算机的各种资源都来自不同的厂家,它们有不同的标准,有不同的差别,所以你针对某一类的I/O设备开发的应用程序就不能在另一台装有不同I/O设备的计算机上运行,而操作系统就完美的消除了这种差别与无法扩展的缺点,所以从逻辑上来说,操作系统位于应用程序与计算机资源的中间层


        同时,作为中间层,必须要干好中间层的工作,所以总的来说,操作系统有两个基本功能

            (1)防止硬件被失控的应用程序滥用;

            (2)向应用程序提供简单一致的机制来控制复杂而又通常大相径庭的低级硬件设备

       另一方面,从计算机CPU(处理器)来看,操作系统实际上不过是一组计算机程序(可以理解成很多个应用程序的集合,而这些应用程序基本都是与硬件打交道的),与其他计算机程序类似(不管是你自己写的HelloWord小程序还是像QQ这样的应用程序,以及大型的服务器程序),它们都给处理器提供指令,然后处理器就执行这些指令,完成这些程序的功能,最大的区别在于操作系统和其他程序的意图不同:操作系统程序通过控制处理器使用其他计算机资源,并控制其他程序的执行时机,这促使处理器完成系统任务的调度。但是(刚刚也说明了,操作系统除了和其他程序的意图不同,其他都一样,所以)处理器为了做任何一件这样的事情(指的是执行另一个程序),都必须停止执行操作系统程序,转而去执行其他程序(这其实是进程切换),因为既然操作系统也是一个程序(进程),而任何处理器同时只能处理一个进程,所以操作系统同样和其他程序(进程)一样需要调度,只是操作系统是处于主动调度的位置,而其他程序是被动的由操作系统的控制来实现调度。


    三、操作系统内核

        关于操作系统和操作系统内核这两个概念,很多人尝试去区分与解释,但是发现很难得解释的完全(包括我自己,这里只是把我自己的理解整理出来,有什么不对的地方,希望大家批评指正,共同进步)。

        查看了一些网上和CS系列书籍中的关于操作系统内核的概念解释,总结之后,我的理解是:

            (1)操作系统包括操作系统内核(这是必然的),也就是说内核程序是操作系统所包含的一组计算机程序中的一个子集,所以内核程序也是一组计算机程序,而这些内核程序是操作系统中最常使用基本模块,直接与硬件打交道,主要由用于管理存储器、文件、外设和系统资源的那些部分组成。

            (2)内核程序一直占据内存中的一段内存,这样处理器可以随时调用这些内核程序;

            (3)而操作系统除了内核程序外,还有包括其他一些基本组件,如文本编辑器、编译器、用来与用户进行交互的程序等

        对于第(2)点,可以引入《深入理解计算机系统》这本书中关于“虚拟存储器”(P12)解释的一幅图来说明,如下:


    上图中,关于进程的虚拟地址空间的说明中,最上面的子区域“内核虚拟存储器”就是用来存储内核程序和数据的,这个地址空间是一个固定的结构,所以对于每一个应用程序(进程)来说,都具有同样结构的虚拟地址空间,这就可以保证每个进程都能调用操作系统内核程序来完成自己的功能。

        下面再用一幅图说明操作系统内核是操作系统的一组子程


    上图中,操作系统的内核包围硬件,同时,其外层是系统调用接口,这就是操作系统中除内核以外的其他组件。

        下面整理两个网友关于操作系统与操作系统内核的解释,个人觉得解释的还是比较好的:

            (1)内核,是操作系统的基础模块,用于管理系统资源。例如提供对软件层面的抽象(例如对进程、文件系统、同步、内存、网络协议等对象的操作和权限控制),和对硬件访问的抽象(例如磁盘,显示,网络接口卡(NIC));操作系统,在内核的基础上有延伸,包括了提供基础服务的系统组件。

            (2)内核,就是计算机学科意义上的操作系统,直接与硬件交互,提供CPU时间片管理、中断、内存管理、IO管理等等;一般意义上的操作系统包含的东西要更多一些,至少要有用户交互的基本程序,比如一个命令行界面和基本的指令(文件遍历、进程管理等等),或者图形界面的桌面和文件浏览器。


    四、总结

        总的说来,一个操作系统包含了内核(是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件)以及其他计算机系统所必须的组件(如函数库、编译器、调式工具、文本编辑器、网站服务器,以及一个Unix的使用者接口(Unix shell)等,这些都是操作系统的一部分,而且每一个模块如编译器都是一个单独的进程,运行在操作系统中)。所以一个内核不是一套完整的操作系统,拿Linux来说,Linux这个词本身只表示Linux内核,但现在大家已经默认的把Linux理解成整个Linux系统,这是由于历史原因造成的(具体可以看本文前言中提到的那篇文章),也就是说人们已经习惯了用Linux来形容整个基于Linux内核,并且使用GNU 工程各种工具和应用程序的操作系统(也被称为GNU/Linux),而基于这些组件的Linux软件被称为Linux发行版。一般来讲,一个Linux发行版本出来包括Linux内核之外,还包含大量的软件(套件),比如软件开发工具,数据库,Web服务器(例如Apache),X Window,桌面环境(比如GNOME和KDE),办公套件(比如OpenOffice、org)等等。

    展开全文
  • 自己动手写操作系统-经典书籍

    千次阅读 2013-09-09 20:21:33
    汇编语言,王爽编写。  王爽老师这本书,绝对是经典中的经典,比其他介绍汇编语言的书强很多。这本书以例子贯穿整本书。不像其他书罗列一堆...的确一个操作系统的实现是自己动手写操作系统的升级版。本人看到了进程
  • 开发一套自己操作系统

    千次阅读 2017-03-19 16:16:01
    操作系统一般指电脑上使用的系统,比如咱们常用的Windows,Linux,Mac OS 等。在投资圈操作系统是指,一套买卖操作的标准。比如"均线之上做多,均线之下做空"。就是一条非常简单的规则,也可以说是一个操作系统或...
  • 如何安装Windows操作系统

    万次阅读 多人点赞 2020-04-28 17:34:14
    博主喜欢以最原始最直接的方式安装系统,并且不喜欢安装Ghost、精简、修改等等各种操作系统,在这里分享一个一直在用,看起来麻烦博主却觉得最适合个人安装操作系统的方式,请往下看,欢迎指正交流分享 一、关于...
  • 操作系统知识点总结(第一章 操作系统引论)

    千次阅读 多人点赞 2019-03-07 20:36:22
    操作系统的分类:批处理操作系统,分时操作系统,实时操作系统,嵌入式操作系统,个人计算机操作系统,网络操作系统,分布式操作系统 操作系统的发展过程: 人工操作方式:硬件非常昂贵,没有操作系统。 批处理...
  • 小编这几天下载试用了几款国产操作系统,分别是:中兴新支点操作系统、红旗操作系统、优麒麟操作系统、普华操作系统!经过不断的测试发现:这几款操作系统流畅度都不错!不过要说适于普通人使用的国产操作系统,目前...
  • 自己写的小型嵌入式操作系统

    千次阅读 2016-12-17 08:47:48
    写一个自己操作系统是我一直以来的愿望,一来,学习,二来吗,装装X了。。哈哈 进过一段时间的学习,今天我写的代码终于实现了任务切换,也就是多任务环境了,虽然任务本身只是很简单那的闪烁你的LED小灯,但是...
  • 我看鸿蒙操作系统

    万次阅读 多人点赞 2019-06-19 02:14:26
    华为宣布推出鸿蒙操作系统。其实我觉得能理解,但也蛮无奈的,所谓不得已而为之,google不提供后续版本授权,不提供新的支持,怎么办,硬着头皮也要上。有些自媒体说什么安卓慌...
  • 操作系统引论 操作系统是配置在计算机硬件上的第一层软件,是对硬件系统的第一次扩充。其主要功能为管理计算机设备,提高他们的利用率和系统吞吐量,并为用户和应用程序提供简单的接口,便于用户使用。OS是现代...
  • 自编STM32轻量级操作系统(一)------操作系统实现

    万次阅读 多人点赞 2017-08-28 20:54:35
    16年寒假那段时间开始接触UCOS实时操作系统,感觉真的很神奇,还借了任哲和邵贝贝的书的来看,原来代码还可以写得那么美妙。 后来,在知乎上看到一位答主的文章...
  • 构筑基于物联网操作系统的物联网生态环境

    万次阅读 多人点赞 2014-04-08 21:01:36
    最近跟物联网行业和移动互联网行业的一些资深从业人员做了深入交流,就物联网操作系统的概念和必要性、定位等进行了充分深入的沟通。首先说明的是,物联网操作系统的概念被广泛认同。同时,对物联网操作系统在整个...
  • ARM——操作系统—最小操作系统

    万次阅读 2013-11-13 16:56:35
    自己动手写最小的ARM操作系统。能够看到自己的代码,真的控制着硬件启动起来,心情是不一样的。 ARM是嵌入式设备,想写个操作系统就需要了解硬件。在X86时代有BIOS帮我们,大部分东西简化了。在ARM时代,最小的...
  • 操作系统基础知识复习总结

    万次阅读 多人点赞 2019-08-17 20:59:38
    操作系统 操作系统概述 操作系统作用 存储管理 处理机管理 设备管理 文件管理 用户接口 操作系统的定义 是管理和控制计算机系统中各种硬件和软件资源、合理地组织计算机工作流程的...
  • 分时操作系统与实时操作系统

    万次阅读 2018-10-20 09:44:20
    计算机操作系统从20世纪50年代中期第二代计算机的单道批处理系统到20世纪60年代中期第三代计算机的多道批处理系统(IBM公司研发的OS/360系统是第一个能运行多道程序的批处理系统),都主要致力于提高资源利用率和...
  • 众所周知,我们通常说操作系统是32位还是64位说的是32位处理器或64位处理器,windows系统有32位和64位,但是最近被问到32位操作系统和64位操作系统有什么区别?一时间只能想到64位操作系统更快,其他具体区别却说不...
  • 漫谈如何学习操作系统原理

    千次阅读 多人点赞 2016-03-02 10:38:07
    本人学习计算机技术至今,对于如何学习操作系统原理有一点自己的看法,现在写出来,希望对大家能有所助!  操作系统怎么学,首先要想操作系统是怎么来的,在没有操作系统的年代里,人们是怎么编程的。这是首要...
  • 单片机上操作系统的好处

    万次阅读 2019-04-02 09:24:27
    自己在上学的时候,搞过2年的单片机STM32编程,当时还记得一心想在上面跑个操作系统,UCOS操作系统,但是当时自己为什么要上这个操作系统,不是特别的清楚,后来自己在实际工作中,做了应用软件,感觉有了一些深刻的...
1 2 3 4 5 ... 20
收藏数 2,378,087
精华内容 951,234
关键字:

自己操作系统