
第2章-嵌入式系统基本知识.ppt
230页第2章 嵌入式系统基本知识第2章 目录n嵌入式系统硬件基础n嵌入式系统软件基础n嵌入式操作系统n嵌入式系统设计方法第2章 目录n嵌入式系统硬件基础n嵌入式系统软件基础n嵌入式操作系统n嵌入式系统设计方法n冯·诺依曼体系结构和哈佛体系结构nCISC与RISCnIP 核n流水线n存储器系统嵌入式系统硬件基础冯·诺依曼体系结构模型指令寄存器指令寄存器控制器控制器数据通道数据通道输入输入输出输出中央处理器中央处理器存储器存储器程序程序指令指令0 0指令指令1 1指令指令2 2指令指令3 3指令指令4 4数据数据数据数据0 0数据数据1 1数据数据2 2q传统的微处理器采用的冯·诺依曼结构将指令和数据存放在同一存储空间中,统一编址,指令和数据通过同一总线访问哈佛体系结构指令寄存器指令寄存器控制器控制器数据通道数据通道输入输入输出输出中央处理器中央处理器程序存储器程序存储器指令指令0 0指令指令1 1指令指令2 2数据存储器数据存储器数据数据0 0数据数据1 1数据数据2 2地址地址指令指令地址地址数据数据q哈佛结构则是不同于冯·诺依曼结构的一种并行体系结构,其主要特点是程序和数据存储在不同的存储空间中,即程序存储器和数据存储器是两个相互独立的存储器,每个存储器独立编制、独立访问。
与之相对应的是系统中设置的两条总线(程序总线和数据总线),从而使数据的吞吐率提高了一倍CISC和RISCCISCCISC:复杂指令集(:复杂指令集(Complex Instruction Set ComputerComplex Instruction Set Computer))具有大量的指令和寻址方式具有大量的指令和寻址方式8/28/2原则:原则:80%80%的程序只使用的程序只使用20%20%的指令的指令大多数程序只使用少量的指令就能够运行大多数程序只使用少量的指令就能够运行主要用于通用主要用于通用PCPC和服务器领域和服务器领域RISCRISC:精简指令集(:精简指令集(Reduced Instruction Set Computer)Reduced Instruction Set Computer)在通道中只包含最有用的指令在通道中只包含最有用的指令确保数据通道快速执行每一条指令确保数据通道快速执行每一条指令使使CPUCPU硬件结构设计变得更为简单硬件结构设计变得更为简单主要用于嵌入式系统主要用于嵌入式系统 RISC基本设计思想n减小CPI: CPUtime=Instr_Count * CPI * Clock_cyclen精简指令集:保留最基本的,去掉复杂、使用频度不高的指令n采用Load/Store结构,有助于减少指令格式,统一存储器访问方式n采用硬接线控制代替微程序控制典型的高性能RISC处理器nSUN公司的SPARC(1987)nMIPS公司的SGI:MIPS(1986)nHP公司的PA-RISC,nIBM, Motorola公司的PowerPCnDEC、Compac公司的Alpha AXPnIBM的RS6000(1990)第一台Superscalar RISC机 CISC与RISC的对比类别CISCRISC指令系统指令数量很多较少,通常少于100执行时间有些指令执行时间很长,如整块的存储器内容拷贝;或将多个寄存器的内容拷贝到存贮器没有较长执行时间的指令编码长度编码长度可变,1-15字节编码长度固定,通常为4个字节寻址方式寻址方式多样简单寻址操作可以对存储器和寄存器进行算术和逻辑操作只能对寄存器对行算术和逻辑操作,Load/Store体系结构编译难以用优化编译器生成高效的目标代码程序采用优化编译技术,生成高效的目标代码程序for (i = 0; i < 10000; ++i)/* 各种算术运算操作 */实验平台:桌面Intel Pentium4,带硬件浮点支持Operator TimeOperator Time+ -(int)1+- (double) 5* (int)5* (double)5/ (int)12/ (double)10<<(int)2sin48小实验1实验平台:400MHz Intel PXA250 Xscale(ARM)处理器Operator TimeOperator Time+- (int)1+ -(double)140* (int)1* (double)110/ (int)7/ (double)220<<(int)1sin3300小实验2知识产权核(IP核-intellectual property)n知识产权(IP) 电路或核是设计好并经过验证的集成电路功能单元nIP复用意味着设计代价降低(时间,价格) nIP核的类别:q微处理器: ARM, PowerPC;q存储器: RAM, memory controller;q外设: PCI, DMA controller;q多媒体处理: MPEG/JPEG ;qencoder/decoder ;q数字信号处理器(DSP) q通信: Ethernet controller, router,IP核的种类nSoft Cores(“code”)(软核)qHDL语言描述q灵活度高,可修改q与工艺独立,可根据具体的加工工艺重新综合;qIP很难保护nFirm cores(“code+structure”)(固核)q逻辑综合后的描述q与工艺相关nHard cores(“physical”)(硬核)q物理综合后的描述q准备流片q包含工艺相关的布局和时序信息qIP很容易保护q多数的处理器和存储器IP核的商业模型三种模式一、设计者提供设计和工具的许可证qDSP Group (Pine and Oak Cores), 3Soft, ARM q提供包括HDL在内的模拟模型,工具或仿真器q使用者负责设计制造二、核厂商设计并制造集成电路芯片qTI, Motorola, LucentqVLSI, SSI, Cirrus, Adaptec三、核厂商卖核, 负责为客户设计并制造芯片qLSI logic, TI, LucentARM的IP核固化宏单元(硬核)固化宏单元(硬核)ARM920TARM7TDMIARM720TARM1022E可综合内核(软核)可综合内核(软核)ARM926EJ-SARM7TDMI-SARM1026EJ-S测试芯片测试芯片ARM10200E流水线技术流水线技术:几个指令可以并行处理•提高了CPU的运行效率•内部信息流要求通畅流动译码取指执行add译码取指执行sub译码取指执行cmp时间AddSubCmp指令流水线—以ARM为例n为增加处理器指令流的速度,ARM7 系列使用3级流水线.q允许多个操作同时处理,比逐条指令执行要快。
n PC指向正被取指的指令,而非正在执行的指令FetchDecodeExecute从存储器中读取指令解码指令寄存器读(从寄存器Bank)移位及ALU操作寄存器写(到寄存器Bank )PCPCPC - 4PC-2PC - 8PC - 4ARMThumb最佳流水线n该例中用6个时钟周期执行了6条指令n所有的操作都在寄存器中(单周期执行)n指令周期数 (CPI) = 1 操作操作周期周期 1 2 3 45 6 ADD SUB MOV AND ORR EOR CMP RSBFetchDecodeExecuteFetchDecodeExecuteFetchDecodeExecuteFetchDecodeExecuteFetchDecodeExecuteDecodeExecuteFetchDecodeFetchFetchLDR 流水线举例n该例中,用6周期执行了4条指令n指令周期数 (CPI) = 1.5 周期周期 操作操作123456 ADD SUB LDR MOV AND ORRFetchDecodeExecuteFetchDecodeExecuteFetchDecodeExecuteDataWritebackFetchDecodeExecuteFetchDecodeFetch高速缓存(CACHE)1、为什么采用高速缓存 微处理器的时钟频率比内存速度提高快得多,高速缓存可以提高内存的平均性能。
2、高速缓存的工作原理 高速缓存是一种小型、快速的存储器,它保存部分主存内容的拷贝 CPU高速缓存控制器CACHE主存数据数据地址主流的嵌入式处理器结构总线和总线桥CPU低速设备桥数据高速总线存储器高速设备高速设备低速总线存储器系统的层次结构寄存器寄存器高速缓存高速缓存SRAM主存储器主存储器DRAM本地存储器本地存储器 Flash、、ROM、磁盘、磁盘网络存储器网络存储器 Flash、、ROM、磁盘、磁盘时时钟钟周周期期01—1050—10020000000存储器系统nRAM:随机存取存储器qSRAM:静态随机存储器qDRAM:动态随机存储器nSRAM比DRAM快nSRAM比DRAM耗电多nDRAM存储密度比SRAM高得多nDRAM需要周期性刷新nROM:只读存储器nFLASH:闪存NOR技术nNOR技术闪速存储器是最早出现的Flash Memory,目前仍是多数供应商支持的技术架构,它源于传统的EPROM器件n与其它Flash Memory技术相比,具有可靠性高、随机读取速度快的优势,但擦除和写的速度较NAND慢n在擦除和编程操作较少而直接执行代码的场合,尤其是代码(指令)存储的应用中广泛使用。
n由于NOR技术Flash Memory的擦除和编程速度较慢,而块尺寸又较大,因此擦除和编程操作所花费的时间很长,在纯数据存储和文件存储的应用中,NOR技术显得力不从心NAND技术nNAND技术 Flash Memory具有以下特点:q以页为单位进行读和编程操作,1页为256或512字节;以块为单位进行擦除操作,1块为4K、8K或16K字节具有快编程和快擦除的功能,其块擦除时间是2ms;而NOR技术的块擦除时间达到几百msq数据、地址采用同一总线,实现串行读取随机读取速度慢且不能按字节随机编程q芯片尺寸小,引脚少,是位成本(bit cost)最低的固态存储器,突破了每兆字节0.1元的价格限制q芯片包含有失效块,其数目最大可达到3~35块(取决于存储器密度)失效块不会影响有效块的性能,但设计者需要将失效块在地址映射表中屏蔽起来n基于NAND的存储器可以取代硬盘或其它块设备输入输出接口n I/OI/On A/D A/D、、D/AD/An 键盘键盘n LCDLCDn 存储器接口存储器接口n 设备接口设备接口第2章 目录n嵌入式系统硬件基础n嵌入式系统软件基础n嵌入式操作系统n嵌入式系统设计方法嵌入式软件体系结构n 循环轮询系统n 前后台系统n 单处理器多任务系统n 多处理器多任务系统无操作系统有操作系统循环轮询系统-无操作系统情况initialize()while(true) {if (condition_1) action_1();if (condition_2) action_2();......if (condition_n) acition_n();}Check for InputDo Somethingn优点q对于简单的系统而言,便于编程和理解。
q没有中断的机制,程序运行良好,不会出现随机的问题n缺点q有限的应用领域q对于大量的I/O服务的应用,不容易实现q大的程序不便于调试适合于慢速和非常快速的简单系统适合于慢速和非常快速的简单系统循环轮询系统-无操作系统情况前后台系统-无操作系统情况n是中断驱动系统的一种q后台是一个循环轮询系统一直在运行q前台是由一些中断处理过程组成的q当有一前台事件(外部事件)发生时,引起中断, 进行前台处理, 处理完成后又回到后台(通常又称主程序)中断中断1 1中断中断2 2主程序主程序中断中断1 1中断中断1 1中断中断2 2初始化初始化处理处理1 1事件事件1 1处理处理2 2事件事件2 2N NY YY YN N前台处理后台处理ISR1ISR1ISR2ISR2前后台系统-无操作系统情况n需要考虑的是中断的现场保护和恢复,中断嵌套,中断处理过程与主程序的协调(共享资源)问题n系统的性能主要由中断延迟时间(Interrupt latency time), 响应时间(response time)和恢复时间(recovery time)来刻画前后台系统-无操作系统情况 中断请求中断请求 数据传送数据传送 ←← 响应时间响应时间 →→ 主程序主程序 ━━━━━━━━━━━━━━━━━━现场保护现场保护 ━━━━━━━━和恢复和恢复中断服务中断服务 ━━━━━━━━━━━━━━ →→ ←←→→| | ←← 中断延迟时间中断延迟时间 恢复时间恢复时间n例如,很多基于微处理器的产品采用前后台系统设计,如微波炉、机、玩具等。
从省电的角度出发,平时微处理器处在停机状态,所有的事都靠中断服务来完成单处理器多任务系统-有操作系统情况对于一个复杂的嵌入式实时系统来说,q当采用中断处理程序加一个后台主程序这种软件结构难以实时的、准确的、可靠的完成时q存在一些互不相关的过程需要在一个计算机中同时处理时需要采用实时多任务系统!需要采用实时多任务系统!结构 由多个任务,多个中断处理过程,实时操作系统组成的有机的整体 每个任务是顺序执行的,并行性通过操作系统来完成,任务间的相互通信和同步也需要操作系统的支持 单处理器多任务系统-有操作系统情况流程并发多任务::::::后台后台前台前台 ISRsTasks多任务系统q多个顺序执行的程序并行运行q宏观上看,所有的程序同时运行,每个程序运行在自己独立的CPU上q实际上,不同的程序是共享同一个CPU和其它硬件因此,需要RTOS来对这些共享的设备和数据进行管理q每个程序都被编制成无限循环的程序,等待特定的输入,执行相应的任务等q这种程序模型将系统分成相对简单的,相互合作的模块单处理器多任务系统-有操作系统情况n优点q将复杂的系统分解为相对独立的多个线程,达到“分而制之”的目的,从而降低系统的复杂性。
q保证系统的实时性q系统的模块化好,提高系统的可维护性n缺点q需要采用一些新的软件设计方法q需要增加功能:线程间的协调,同步和通信功能q需要对每一个共享资源互斥q导致线程间的竞争q需要使用RTOS,RTOS要增加系统的开销单处理器多任务系统-有操作系统情况多处理器多任务系统q多任务可运行在多个处理器上,由操作系统统一调度,处理q宏观上看是并发的,微观上看也是并发的q多处理机系统分为紧耦合系统(tightly-coupled system)和 松 耦 合 系 统 (loosely-coupled system)两种q多处理多任务系统目前还不成熟硬件板级初始化设备驱动层以太网驱动串口驱动LCD驱动键盘驱动操作系统层中间件层应用软件层TCP/IP网络系统文件系统内核嵌入式GUI嵌入式CORBA嵌入式JAVA嵌入式DCOM面向领域的中间件WWW浏览器MP3播放器电子邮件…n为什么要有设备驱动程序?嵌入式硬件设备本身无法工作,需要软件来驱动,如初始化、控制、数据读写等n什么是设备驱动程序?直接与硬件打交道、对硬件进行控制和管理的软件n在一个嵌入式系统中,设备驱动程序是必不可少的设备驱动程序设备驱动程序的主要功能n硬件启动(Startup):在开机上电或重启的时候,对硬件进行初始化;n硬件关闭(Shutdown):把硬件配置成关机状态;n硬件停用(Disable):暂停使用硬件;n硬件启用(Enable):重新启用硬件;n硬件读操作(Read):从硬件中读取数据;n硬件写操作(Write):往硬件中写数据;n……嵌入式操作系统n嵌入式操作系统包括嵌入式内核、嵌入式TCP/IP网络系统、嵌入式文件系统、嵌入式GUI系统和电源管理等部分;n嵌入式内核是基础和核心,其他部分要根据嵌入式系统的需要来确定。
嵌入式中间件n中间件(Middleware):在OS内核、设备驱动程序和应用软件之外的所有系统软件;n中间件的基本思路:把原本属于应用软件层的一些通用的功能模块抽取出来,形成独立的一层软件,从而为运行在其上的各个应用软件提供一个灵活、安全、移植性好、相互通信、协同工作的平台;n优点:实现软件的可重用,降低应用软件的复杂性,降低开发成本嵌入式C程序设计“which of the following programming languageshave you used for embedded systems in the last12 months”C81%Assembly70%C++39%Visual Basic 16%Java7%Source: “ESP: A 10-year retrospective”, EmbeddedSystems Programming, November, 1998嵌入式软件的目标n函数必须正确;n源代码简洁、可读性好、可维护;n实时性要求较高的代码能够运行得足够快;n目标代码小且高效n总之,要优化对以下三种资源的使用:q执行时间;q存储空间;q开发/维护时间。
数据类型与运算符宏定义:用一个指定的标识符来代表一个字符串define 标识符 字符串如:#define PI 3.1415926,其作用是指定用标识符PI来代替“3.1415926”这个字符串,在编译预处理时,将程序中出现的所有PI都用“3.1415926”代替1)宏定义宏定义的基本思想是:一次定义,多次使用其优点是:可以用简短的标识符来代替长的数据,减少需要输入的字符数;用易于理解的标识符来代替那些不太好记的具体的数据,便于程序的理解和维护;有利于程序的修改和升级,当这个数据需要修改时,只需改动宏定义之处即可if ( myMoney > 80.0 ){ myShoes ++; myMoney = myMoney – 80.0;}#define COST_OF_SHOES 80.0if(myMoney > COST_OF_SHOES){ myShoes ++; myMoney = myMoney – COST_OF_SHOES;}不用不用此法此法一次一次定义定义多次多次使用使用(2)const常量n常量数据:整数(12)、字符(‘a’)、字符串(“hello”)和实数(3.14)等;n以变量的形式来定义的一个量,并且通过使用关键字const,来表明这个变量的值不能被改变。
如:const int x = 1(3)算术运算整数的算术运算最快带有硬件支持的浮点运算较慢用软件来实现的浮点运算非常慢+,- 快×÷ sin, log, sqrt, etc 慢结论:n 尽量使用整数(char、short、int和long)的加法和减法;n 如果没有硬件支持,尽量避免使用乘法;n 尽量避免使用除法;n 如果没有硬件支持,尽量避免使用浮点数;n 数学库函数使用得越少越好(4)位运算C语言有很多位操作运算符:&与操作;|或操作;^异或操作;~取反操作;>>右移操作;<<左移操作a |= 0x4b &= ~0x4c &= ~(1 << 3)d ^= (1 << 5)e >>= 2// 把第2位设置为1// 把第2位设置为0// 把第3位设置为0// 把第5位反转// 把 e 除以4分支语句if (a == 1) ant();else if (a == 2) bar();else if (a == 3) cee();else if (a == 4) due();else if (a == 5) eat();else if (a == 6) foo();switch (a){ case 1: ant(); break; case 2: bar(); break; case 3: cee(); break; case 4: due(); break; case 5: eat(); break; case 6: foo(); break;}Any Differences?结论:n假设a的取值个数为n,对于if-then-else语句,时间复杂度为O(n),而对于switch语句,时间复杂度为O(1);n如果n的值较小,两种语句均可;n如果n的值较大,则switch语句更佳。
函数函数原型main ( ){ …… 函数调用 ……}函数定义函数的使用模式声明该函数定义一个函数使用该函数操作系统代码栈帧2栈帧1全局变量内存分布状况全局变量区域静态分配栈自动分配堆动态分配主函数的执行过程int z;void main( ){ int x, y; x = 1; y = 2; z = x + y;}…main( ){ … }… z = 0全局变量区域全局变量区域栈帧栈帧(main)(main)x = y =程序程序123控制流与数据流控制流:程序当前执行位置的流向;数据流:函数调用发生及结束时,数据在 函数之间流转的过程当一个函数被调用时:1.在内存的栈空间当中为其分配一个栈帧,用来存放该函数的形参和局部变量;2.把实参变量的值复制到相应的形参变量;3.控制转移到该函数的起始位置;4.该函数开始执行;5.控制流和返回值返回到函数调用点函数调用过程控制流的变化void main( ){ double x, y, z; y = 6.0; x = Area( y / 3.0 ); ... z = 3.4 * Area(7.88); ...}/* 给定半径,定半径,计算一算一个个圆的面的面积 */double Area(double r){ return(3.14 * r * r);}一个简单的例子int Times2(int value);main ( ){ int number; printf(“请输入一个整数:请输入一个整数:”); scanf(“%d”, &number); printf(“该数的两倍是:该数的两倍是:%d”, Times2(number));}int Times2(int value){ return(2 * value);}mainnumber3int Times2(int value);main ( ){ int number; printf(“请输入一个整数:请输入一个整数:”); scanf(“%d”, &number); printf(“该数的两倍是:该数的两倍是:%d”, Times2(number));}int Times2(int value){ return(2 * value);}mainnumber3Times2valueTimes2也得到一也得到一个栈帧个栈帧,它的参数看成局部它的参数看成局部变量量int Times2(int value);main ( ){ int number; printf(“请输入一个整数:请输入一个整数:”); scanf(“%d”, &number); printf(“该数的两倍是:该数的两倍是:%d”, Times2(number));}int Times2(int value){ return(2 * value);}mainnumber3Times2value3“值传递”, 把把实参的参的值传给形参。
形参int Times2(int value);main ( ){ int number; printf(“请输入一个整数:请输入一个整数:”); scanf(“%d”, &number); printf(“该数的两倍是:该数的两倍是:%d”, Times2(number));}int Times2(int value){ return(2 * value);}main3把把Times2的的栈帧栈帧叠在主叠在主函数的函数的栈帧栈帧之上,之上,说明明在在执行行Times2函数函数时,,主函数中的主函数中的变量是不可量是不可见的Times2value3int Times2(int value);main ( ){ int number; printf(“请输入一个整数:请输入一个整数:”); scanf(“%d”, &number); printf(“该数的两倍是:该数的两倍是:%d”, Times2(number));}int Times2(int value){ return(2 * value);}mainnumber36Times2函数的返回函数的返回值被被放在函数的放在函数的调用位置上,用位置上,然后,分配然后,分配给Times2函函数的堆数的堆栈区域被区域被释放。
放变量的存储与作用域/* 全局变量,固定地址,其他源文件可见 */int global_static;/* 静态全局变量,固定地址,但只在本文件中可见 */static int file_static;/* 函数参数:位于栈帧当中,动态创建,动态释放 */int foo(int auto_param){ /*静态局部变量,固定地址,只在本函数中可见 */ static int func_static; /* 普通局部变量,位于栈帧当中,只在本函数可见 */ int auto_i, auto_a[10]; /* 动态申请的内存空间,位于堆当中 */ double *auto_d = malloc(sizeof(double)*5); return auto_i;}可重入函数-1可以被一个以上的任务调用,而不必担心数据的破坏可重入型函数任何时候都可以被中断,一段时间以后又可以运行,而相应数据不会丢失可重入型函数只使用局部变量,即变量保存在CPU寄存器或栈中一个不可重入型函数的例子int temp;void swap(int *x, int *y){ temp = *x; *x = *y; *y = temp;}可重入函数-2一个可重入型函数的例子void swap(int *x, int *y){ int temp; temp = *x; *x = *y; *y = temp;}不可重入函数被中断破坏第2章 目录n嵌入式系统硬件基础n嵌入式系统软件基础n嵌入式操作系统n嵌入式系统设计方法嵌入式操作系统概述An Embedded Operating System (EOS) isan Operating System (OS) in an Embedded System environment.Being an OS means…n系统软硬件资源的管理者:q进程管理q存储管理qI/O设备管理q文件管理Being an EOS means…n完成某一项或有限项功能,非通用型;n在性能和实时性方面可能有严格限制;n能源、成本和可靠性通常是影响设计的重要因素;n占有资源少,适合在有限存储空间运行;n系统功能可针对需求进行裁剪、调整,以便满足最终产品的设计要求。
按响应时间分类…n嵌入式实时操作系统当事件/请求发生时,相应的任务应该在规定的时间内完成;n分时操作系统基于公平性原则,各个进程分享处理器,获得大致相同的运行时间当一个进程在进行I/O操作时,交出处理器,让其他进程运行n实时操作系统(RTOS) qA real-time operating system (RTOS) is an operating system whose correctness includes its response time as well as its functional correctness.qhard real time and soft real timesoft real timehard real time按软件结构分类…n单体结构(Monolithic Structure)n分层结构(Layered Structure)Out of date…n微内核结构(Microkernel Model)单体结构n最常用的组织结构;n整个系统只有一个可执行文件,包含所有的操作系统组件;n系统的结构就是无结构,由一组函数组成,相互之间可以随意地调用。
应用软件 文件I /O 存储管理 进程管理 I/O驱动 存储驱动 中断驱动 硬件 单体内核 分层结构n在分层结构(layered)中,一个操作系统被划分为若干个层次(0..N),各个层次之间的调用关系是单向的,即某一层次上的代码只能调用比它低层的代码n这种结构要求在每个层次上都要提供一组API接口函数,这就会带来额外的开销 微内核结构n操作系统内核只包含最少的功能,如存储管理和进程管理;n其他的操作系统组件以中间件的形式存在于内核之外;n设备驱动程序完全从内核中剥离,独立成为一层微内核 设备驱动程序 中间件、应用软件 存储管理 进程管理 I/O驱动 存储驱动 中断驱动 硬件 多道程序技术为了提高计算机系统中各种资源的利用率,现代操作系统广泛采用多道程序技术(multi-programming),使多个程序同时在系统中存在并运行CPUI/O单道程序:单道程序:多道程序:多道程序:CPUI/O作业甲(作业甲(红红黄黄))作业乙(作业乙(蓝蓝绿绿))进程、线程和任务在多道程序系统中,各个程序之间是并发执行的,共享系统资源CPU需要在各个运行的程序之间来回地切换,这样的话,要想描述这些多道的并发活动过程就变得很困难。
为此,操作系统设计者提出了进程的概念什么是进程?A process == a program in execution 一个进程应该包括:n 程序的代码;n 程序的数据;n PC中的值,用来指示下一条将运行的指令;n 一组通用的寄存器的当前值,堆、栈;n 一组系统资源(如打开的文件) 总之,进程包含了正在运行的一个程序的所有状态信息nA program is C statements or commands静态的静态的;;nA process is program + running context动态的动态的.main( ){…..}A( ){…..}PROGRAMmain( ){…..}A( ){…..}PROCESSheap StackA MainRegisters,PCProcess ≠ Program 进程的特性n动态性:程序的运行状态在变,PC、寄存器、堆和栈等;n独立性:是一个独立的实体,是计算机系统资源的使用单位每个进程都有“自己”的PC和内部状态,运行时独立于其他的进程(逻辑PC和物理PC);n并发性:从宏观上看各进程是同时独立运行的四个进程在并发地运行什么是线程?自从60年代提出进程概念以来,在操作系统中一直都是以进程作为独立运行的基本单位,直到80年代中期,人们又提出了更小的能独立运行的基本单位 线程。
Why线程?【案例】编写一个MP3播放软件核心功能模块有三个:(1)从MP3音频文件当中读取数据;(2)对数据进行解压缩;(3)把解压缩后的音频数据播放出来单进程的实现方法 main( ){ while(TRUE)) { Read( ); Decompress( ); Play( ); }}Read( ) { … }Decompress( ) { … }Play( ) { … }问题:n 播放出来的声音能 否连贯?n 各个函数之间不是 并发执行,影响资 源的使用效率;I/OCPU多进程的实现方法 程序程序1main( ){ while(TRUE)) { Read( ); }}Read( ) { … }问题:进程之间如何通信,共享数据?程序程序3main( ){ while(TRUE)) { Play( ); }}Play( ) { … }程序程序2main( ){ while(TRUE)) { Decompress( ); }}Decompress( ) { … }怎么办? 需要提出一种新的实体,满足以下特性:(1)实体之间可以并发地执行;(2)实体之间共享相同的地址空间;这种实体就是:这种实体就是:线程线程((ThreadThread))什么是线程? Thread:n A sequential execution stream within a process; n A thread of execution;n 进程当中的一条执行流程。
从两个方面来理解进程:n 从资源组合的角度:进程把一组相关的 资源组合起来,构成了一个资源平台 (环境),包括地址空间(代码段、数据 段)、打开的文件等各种资源;n 从运行的角度:代码在这个资源平台上的 一条执行流程(线程)资源平台资源平台 线程线程 进程进程 == 线程线程 ++ 资源平台资源平台优点:n 一个进程中可以同时存在多个线程;n 各个线程之间可以并发地执行;n 各个线程之间可以共享地址空间线程所需的资源(本图摘自(本图摘自Silberschatz, Galvin and Gagne:: “Operating System Concepts”)) 什么是任务? 在许多嵌入式操作系统当中,一般把能够独立运行的实体称为“任务”(Task),那么这里所说的任务到底是进程还是线程呢?任务的实现n在多道程序(多任务)的嵌入式操作系统中,任务之间的结构为层状结构,存在着父子关系;n当嵌入式内核刚刚启动时,只有一个任务存在,然后由该任务派生出所有其他的任务任务的层次结构OSOS初始任务初始任务 任务任务 任务任务 任务任务 任务任务 任务任务 任务任务 任务任务 任务的创建n在嵌入式操作系统当中,任务的创建主要有两种模型:fork/exec和spawn;nfork/exec:符合IEEE/ISO POSIX 1003.1标准,先用fork系统调用创建与父任务完全相同的一份内存空间,然后再用exec系统调用来移除父任务的内容,并调入子任务的程序代码。
优点:允许继承;nspawn:直接为子任务创建一个全新的地址空间,并装入其程序代码任务的描述问题:如果让你来设计OS当中的任务机制,那么你将如何来描述一个任务? 描述任务的数据结构:任务控制块(Task Control Block,TCB)系统为每个任务都维护了一个TCB,用来保存与该任务有关的所有信息任务控制块的内容n任务ID、任务的状态、任务的优先级;nCPU上下文信息:通用寄存器的值、PC寄存器的值、程序状态字、栈指针的值;n如果在该OS中,任务描述的是进程,则还应包括其他的一些内容,如段表地址、页表地址等存储管理方面的信息;根目录、文件描述字等文件管理方面的信息任务的创建:为该任务生成一个TCB;任务的终止:回收它的TCB;任务的组织管理:通过对TCB的组织管理来实现系统用TCB来描述任务的基本情况以及运行变化的过程,TCB是任务存在的唯一标志任务的状态任务的三种基本状态:任务在生命结束前处于且仅处于三种基本状态之一不同系统设置的任务状态数目不同n运行状态(Running):任务占有CPU,并在CPU上运行处于此状态的任务数目小于等于CPU的数目;n就绪状态(Ready):任务已经具备运行条件,但由于CPU忙暂时不能运行,只要分得CPU即可执行;n阻塞/等待状态(Blocked/Waiting):任务因等待某种事件的发生而暂时不能运行(如I/O操作或任务同步),此时即使CPU空闲,该任务也不能运行。
任务的状态及其转换RunningBlockedReady1 3 2 41.任务由于I/O操作被阻塞;2.调度器选择了另一个任务;3.调度器选中该任务4.任务的I/O操作完成了两个任务的状态转换过程状态队列n由操作系统来维护一组队列,用来表示系统当中所有任务的当前状态;n不同的状态分别用不同的队列来表示(运行队列、就绪队列、各种类型的阻塞队列);n每个任务的TCB都根据它的状态加入到相应的队列当中,当一个任务的状态发生变化时,它的TCB从一个状态队列中脱离出来,加入到另外一个队列就绪队列和各种I/O队列选择谁去运行?选择谁去运行?任务的调度n在操作系统中,负责去做这个选择的那部分程序,称为调度程序或调度器(scheduler);n调度程序在决策过程中所采用的算法,称为是调度算法;n调度程序是CPU资源的管理者何时进行调度?n当一个新的任务被创建时,是执行新任务还是继续执行父任务?n当一个任务运行完毕时;n当一个任务由于I/O、信号量或其他的某个原因被阻塞时;n当一个I/O中断发生时,表明某个I/O操作已经完成,而等待该I/O操作的任务转入就绪状态;n在分时系统中,当一个时钟中断发生时。
两种调度方式n不可抢占(non-preemptive)调度方式:一个进程若被选中就一直运行下去,直到它被阻塞(I/O,或正在等待其他进程),或主动地交出CPU以上的情形1-3均可发生调度;n可抢占(preemptive)调度方式:当一个进程在运行时,调度程序可以打断它以上的情形1-5均可发生调度,另外,在其他一些情形下,如就绪队列中有新进程的优先级高于当前正运行的进程,也可能立即进行调度嵌入式调度算法的评价指标n响应时间(response time):调度器为一个就绪任务进行上下文切换的时间,以及任务在就绪队列中等待的时间;n周转时间(turnaround time):一个任务从提交到完成所经历的时间;n调度开销(overhead):调度算法在执行时所需要的时间和空间开销;n公平(fairness):大致相当的两个进程所得到的CPU时间也应是大致相同的,防止饥饿(starvation);n均衡:尽可能使整个系统的各部分(CPU、I/O)都忙起来,提高系统资源的使用效率;n吞吐量(Throughput):单位时间内完成的任务数先来先服务调度算法n先来先服务(First Come First Served,FCFS;First In First Out,FIFO):按照任务到达就绪队列的先后次序进行调度;n不可抢占方式:当前任务占用CPU,直到执行完或被阻塞,才让出CPU给另外一个任务;n在任务被唤醒后(如I/O完成),并不立即恢复执行,而是放在就绪队列的末尾;n优点:简单、公平,易于理解也易于实现。
现实生活中应用广泛:排队FCFS算法的问题平均周转时间取决于各任务到达的顺序,若短任务位于长任务之后,将增大平均周转时间例如,三个任务A、B、C的运行时间为24、3、3时间 24 27 30ABC平均周转时间=(24+27+30)/3=27时间 3 6 30ABC平均周转时间=(3+6+30)/3=13短作业优先调度算法n短作业优先(Shortest Job First,SJF),设计目标是改进FCFS算法,减少平均周转时间;nSJF算法要求任务在开始执行时预计执行时间,对预计执行时间短的任务优先分派处理器;n两种实现方案:q不可抢占方式:当前任务在运行时不会被打断,只有运行完毕或阻塞时,才让出CPU;q可抢占方式:如果一个新的短任务到来,其运行时间小于当前正在运行任务的剩余时间,则抢占CPU运行,称为SRTF(Shortest Remaining Time First)可以证明:对于一组同时到达的任务,采用SJF算法将得到一个最小的平均周转时间D时间ACa a+b a+b+c a+b+c+d 例如,考察4个任务A、B、C、D,其运行时间分别为a、b、c、dBA、B、C、D的周转时间分别为a、a+b、a+b+c和a+b+c+d,因此平均周转时间为:(4a+3b+2c+d)/4显然,当a b c d时,平均周转时间最小。
时间片轮转调度算法n在时间片轮转算法(Round-Robin,RR)中,将所有的就绪任务按照FCFS原则,排成一个队列;n每次调度时将处理器分派给队首任务,让其执行一小段CPU时间(时间片,time slice);n在一个时间片结束时,如果任务还没有执行完的话,将发生时钟中断,在时钟中断中,调度程序将暂停当前任务的执行,并将其送到就绪队列的末尾,然后执行当前的队首任务;n如果一个任务在它的时间片用完之前就已结束或被阻塞,那么立即让出CPU开始时,任务B位于队列之首,因此被调度执行当它的时间片用完后,就把它送到就绪队列的末尾同时,任务F成为新的队首,被调度运行Round robin, too….时间片轮转法的特点n优点:q公平性:各个就绪任务平均地分配CPU的使用 时间假设有n个就绪任务,时间片大小为q, 那么每个任务将得到1/n的CPU时间;q活动性:每个任务最多等待(n-1)q时间就能够 再次得到CPU去运行;n缺点:q的大小难以确定(一般在20-50ms)太大:退化为FCFS算法,进程在一个时间片 内都执行完,响应时间长如q=100ms;太小:每个任务都需要更多的时间片才能处理 完,任务切换次数增加,增大系统开销。
如q=4ms优先级调度算法n 轮转法有一个缺省的前提,即各任务同等重要;n “人人生而平等”? 恐怕不太现实!同样,并不是每个任务都同等重要, 怎么办?分等级!n 优先级算法(Priority Scheduling):给每个任务设置一个优先级,然后在所有就绪任务中选择优先级最高的那个任务去运行;n SJF就是一个优先级算法,每个任务的优先级是它的CPU运行时间(时间越短,优先级越高);n 分为可抢占和不可抢占两种方式;各任务优先级的确定方式可分为静态和动态两种可抢占方式任务任务1 1 任务任务2 2 任务任务1 1 优先级优先级 高高低低时间时间 任务任务2 2 任务任务3 3 表示抢占表示抢占 表示结束表示结束 n静态优先级方式:指在创建任务时即确定任务的优先级,并保持不变到任务运行结束–缺点:如果一直有高优先级的任务出现,则它们一直占用着CPU,而低优先级的任务“饥饿”n动态优先级方式:指在创建任务时赋予给进程的优先级,在任务运行过程中可以动态改变,以便获得更好的调度性能–为防“饥饿”,根据任务的等待时间调整优先级在就绪队列中,等待时间延长则优先级提高,从而使优先级较低的任务在等待足够的时间后,其优先级提高到可被调度执行。
优先级类别(本图摘自(本图摘自Andrew S. Tanenbaum:: “Modern Operating Systems” ))可以把进程按照不同的优先级别分组,然后在不同级别之间使用优先级算法,而在同一级别的各个进程之间使用时间片轮转法实时系统调度n对于RTOS调度器来说,公平性并不重要例如:如果老师给你布置了五个家庭作业,其中有一个作业必须在一个小时内完成,显然先做那个作业;nRTOS调度器的主要目标就是要使得每个任务都必须在其最终时间期限(deadline)之前完成优先级反转n大多数RTOS调度器都采用基于优先级的可抢占调度算法;n但在具体实现上:n如何设定各个任务的优先级?n优先级是静态设置的还是动态可变的?n算法的性能如何,能否满足实时要求?任务模型(周期性任务)n启动时间r(i,j):第i个任务的第j次执行的开始时间;n时间期限Deadline,D(i):第i个任务所允许的最大响应时间(从任务启动到运行结束所需的时间);n周期Period,P(i):第i个任务的连续两次运行之间的最小时间间隔;n执行时间Execution Time,E(i):对于第i个任务,当它所需要的资源都已具备时,它的执行所需要的最长时间。
单调速率调度算法ö单调速率调度(Rate Monotonic Scheduling,RMS) 算法;öRMS是一种静态优先级调度算法,也是最常用的一种确定任务优先级的算法;ö思路:单位时间内任务被执行的次数越多,优先级越高即任务的周期越短,优先级越高周期优先级101(最高)122153204(最低)例如:nRMS算法是一种最优算法:如果存在一种基于静态优先级的调度顺序,使得每个任务都能够在期限时间内完成,那么RMS算法总能找到一种可行的调度方案;n对于一组任务,这种调度方案不一定存在;n处理器的利用率:n如果U 1,则RMS调度方案不存在(处理器不可能一天工作25小时);n如果U n(21/n1),n为任务的个数,则RMS调度方案一定存在最早期限优先调度算法n最早期限优先(Earliest Deadline First, EDF) 调度算法:nEDF是一种动态优先级调度算法,也是性能最好的一种调度算法;n基本思路:对时间期限最近的任务,分配最高的优先级任务间通信n任务间通信(Intertask Communication):任务之间为了协调工作,需要相互交换数据和控制信息;n任务间通信的方式:n共享内存(shared memory);n消息传递(message passing);n管道(pipe);n异步信号(signal)。
共享内存n各个任务共享它们地址空间当中的某些部分,即共享内存在此区域,可以任意读写和使用任意的数据结构(缓冲区);n一组任务向共享内存中写数据,另一组任务从中读数据,通过此方式实现它们之间的信息交换内存共享数据任务1任务2任务3消息传递n消息:由若干数据位组成;n消息传递:任务之间通过发送和接收消息来交换信息;n消息机制由OS来维护,包括定义寻址方式、认证协议、消息的大小等一般提供两个操作:nsend( ),发送一条消息;nreceive( ),接收一条消息n如果两个任务P和Q想要进行通信,它们需要n在两者之间建立一个通信链路;n使用send( )和receive( )交换信息直接通信n直接通信:通信双方必须指明与之通信的对象nsend(P, message):发送一条消息给任务P;nreceive(Q, message):从任务Q那里接收一条消息如果没有收到消息,可以阻塞起来等待消息的到来,也可以立即返回;n通信双方之间存在一条通信链路n通信链路是自动建立的,由OS来维护;n每条链路只涉及两个任务,每对任务之间仅存在一条链路;n通信链路可以是单向或双向的间接通信1n间接通信:通信时不必指明发送或接收的对象,而是通过共享的邮箱来发送和接收消息。
nsend(A, message):发送一条消息给邮箱A;nreceive(A, message):从邮箱A接收一条消息n间接通信的特点n对于一对任务,只有当它们共享一个公共邮箱时才能进行通信;n一个邮箱可以被多个任务访问,每对任务也可以使用多个邮箱来通信;n可以是单向或双向的间接通信2n邮箱只能存放单条消息,其状态只有两种:空或满另一种间接通信机制是:消息队列n消息队列与邮箱类似,但可以同时存放若干条消息,提供了一种任务间缓冲通信的方法任务1 任务2 消息 消息队列1消息 消息队列2管道(pipe)n管道通信由UNIX首创,由于其有效性,后来的一些系统相继引入了管道技术;n管道通信以文件系统为基础,所谓管道即连接两个任务之间的一个打开的共享文件,专用于任务之间的数据通信;n发送任务从管道的一端写入数据流,接收任务从管道的另一端按先进先出的顺序读出数据流;n管道的读写操作即为文件操作fwrite/fread,数据流的长度和格式没有限制管道(pipe)Task1Task2管道管道中的数据写描述符读描述符向管道写数据从管道读数据数据在管道内像一个非结构字节流,按FIFO的次序从管道中读出。
当管道空时,阻塞读任务,当管道满时,阻塞写任务 异步信号(signal)n异步信号机制用于任务与任务之间、任务与ISR之间的异步操作,它被任务(或ISR)用来通知其它任务某个事件的出现 ;n异步信号标志可以依附于任务需要处理异步信号的任务由两部分组成,一个是与异步信号无关的任务主体,另一个是ASR(异步信号服务例程) ;n一个ASR对应于一个任务当向任务发送一个异步信号,如果该任务正在运行则中止其自身代码的运行,转而运行与该异步信号相关的服务例程;或者当该任务被激活时,在投入运行前执行ASRn异步信号机制也可以称作软中断机制,异步信号又被称为软中断信号Task1ISRTask2 ( ){使能异步信号;使能异步信号;……………………}Signal_routine ( ){……Return();}100000异步信号异步信号标标志志异步信号机制与中断机制的比较n相同点n具有中断性:对中断的处理和对异步信号的处理都要先暂时地中断当前任务的运行n有相应的服务程序n根据中断向量,有一段与中断信号对应的服务程序,称为ISR(Interrupt Service Routine)n根据异步信号的编号,有一段与之对应的服务程序,称为ASR(Asynchronious Service Routine)n可以屏蔽其响应n外部硬件中断可以通过相应的寄存器操作被屏蔽n任务也可以屏蔽对异步信号的响应异步信号机制与中断机制的比较n不同点n实质不同:中断由硬件或特定的指令产生,信号由系统调用产生; n处理时机不同:中断触发后,硬件会根据中断向量找到相应的处理程序去执行;信号通过发送信号的系统调用触发,但系统不一定马上对它进行处理;n执行环境不同:中断处理程序是在系统内核的上下文中运行,是全局的;而信号处理程序是在相关任务的上下文中运行,是任务的一个组成部分。
同步与互斥n多数操作系统(包括分时和实时)都是多任务系统,允许多个任务同时运行;n当两个或多个任务在访问共享资源(如共享内存)的时候,如何确保它们不会相互妨碍 —— 任务互斥问题;n当两个或多个任务之间存在着某种依存关系时,如何来调整它们的运行次序 —— 任务同步问题任务互斥两个任务同时在内存运行任务1任务2count = 2count = 3请问:count变量最后的结果是多少?2还是3?两个任务,一个读,一个写任务1任务2if(count==2)count = 2 return TRUE;else return FALSE请问:如果在这些任务执行之前,count变量的值为3,那么任务1最后返回的结果是什么?两个任务,读-修改-写n任务1ntmp1 = count;ntmp1 ++;ncount = tmp1;nprintf("count :%d",count);n任务2ntmp2 = count;ntmp2 = tmp2+2;ncount = tmp2; nprintf("count :%d",count);请问:如果在这些任务执行之前,count变量的值为1,那么它最后的结果是多少?任务1 任务2tmp1 = count;(=1)interrupt... tmp2 = count;(=1) tmp2 = tmp2+2;(=3) count = tmp2;(=3)tmp1 ++;(=2)count = tmp1;(=2)printf("count :%d",count);情形1count:2count:2任务1 任务2 tmp2 = count;(=1) interrupt...tmp1 = count;(=1)tmp1 ++;(=2)count = tmp1;(=2) tmp2 = tmp2+2;(=3) count = tmp2;(=3) printf("count :%d",count); 情形2count:3count:3任务1 任务2tmp1 = count;(=1)tmp1 ++;(=2)count = tmp1;(=2) tmp2 = count;(=2) tmp2 = tmp2+2;(=4) count = tmp2;(=4)printf("count :%d",count); 情形3count:4count:4竞争条件(竞争条件(race conditionrace condition):):两个或多个任务对同一共享数据同时进行读写操作,而最后的结果是不可预测的,它取决于各个任务的具体运行情况。
解决之道:解决之道:在同一时刻,只允许一个任务访问该共享数据,即如果当前已有一个任务正在使用该数据,那么其他任务暂时不能访问这就是互斥的概念把一个任务在运行过程中所做的事情分为两类:n任务内部的计算或其他的一些事情,肯定不会导致竞争条件的出现;n对共享内存或共享文件的访问,可能会导致竞争条件的出现我们把完成这类事情的那段代码称为“临界区”(Critical Region),把需要互斥访问的共享资源称为“临界资源”如果我们能设计出某种方法,使得任何两个任务都不会同时出现在临界区中,就可以避免竞争条件的出现竞争条件问题的抽象描述关闭中断的解决方案当一个任务进入临界区后,关闭所有的中断;当它退出临界区时,再打开中断q 把关闭中断的权力授予用户任务,是很不聪明的而且假设系统有多个CPU,则此法无效;q 对内核任务而言,是一种方便有效的办法结论:适用于内核任务,但不适用于用户任务,不能作为一种普遍适用的互斥实现方法基于繁忙等待的解决方案while(TestAndSet(lock));临界区lock = FALSE;非临界区基于繁忙等待策略的方法 浪费CPU时间可以采用各种基于繁忙等待(busy waiting)的策略,基本思路是:当一个任务想要进入它的临界区时,首先检查一下是否允许它进入,若允许,就直接进入了;若不允许,就在那里循环地等待,一直等到允许它进入。
信号量(semaphore)n1965年由著名的荷兰计算机科学家Dijkstra提出,其基本思路是用一种新的变量类型(semaphore)来记录当前可用资源的数量n有两种实现方式:1)semaphore的取值必须大于或等于00表示当前已没有空闲资源,而正数表示当前空闲资源的数量;2)semaphore的取值可正可负,负数的绝对值表示正在等待进入临界区的任务个数n信号量是由操作系统来维护的,任务只能通过初始化和两个标准原语(P、V原语)来访问初始化可指定一个非负整数,即空闲资源总数n P、V原语作为操作系统内核代码的一部分,是一种不可分割的原子操作(atomic action),在其运行时,不会被时钟中断所打断;n P、V原语包含有任务的阻塞和唤醒机制,因此在任务等待进入临界区时不会浪费CPU时间;n P原语:P是荷兰语Proberen(测试)的首字母申请一个空闲资源(把信号量减1),若成功,则退出;若失败,则该任务被阻塞;n V原语:V是荷兰语Verhogen(增加)的首字母释放一个被占用的资源(把信号量加1),如果发现有被阻塞的任务,则选择一个唤醒之信号量和P、V原语的实现信号量结构体类型的定义typedef struct{ int count;// 计数变量计数变量 struct TCB *queue;// 进程等待队列进程等待队列} semaphore;P原语:申请一个资源原语:申请一个资源P( semaphore S){ --S.count;//表示申请一个资源表示申请一个资源; if (S.count < 0)//表示没有空闲资源表示没有空闲资源; { 该任务进入等待队列该任务进入等待队列S.queue末尾末尾; 阻塞该任务阻塞该任务; }} V原语:释放一个资源原语:释放一个资源V( semaphore S){ ++S.count;//表示释放一个资源表示释放一个资源; if (S.count <= 0) //表示有进程被阻塞表示有进程被阻塞; { 从等待队列从等待队列S.queue中取出一个进程中取出一个进程; 把该进程改为就绪状态,插入就绪队列把该进程改为就绪状态,插入就绪队列 }}•Windows 2000•CreateSemaphore(创建信号量)(创建信号量)•WaitForSingleObject((P操作)操作)•ReleaseSemaphore((V操作)操作)•uCOS•osSemCreate(创建信号量)(创建信号量)•osSemPend ((P操作)操作)•osSemPost((V操作)操作)semaphore mutex;;mutex.count = 1;// N = 1P(mutex);临界区临界区V(mutex);非临界区非临界区利用信号量来实现进程互斥任务同步任务间的同步是指多个任务中发生的事件存在某种时序关系,因此在各个任务之间必须协同合作,相互配合,使各个任务按一定的速度执行,以共同完成某一项工作。
【例子】 司机与售票员while(上班时间){ 发动汽车; 正常运行; 到站停车;}while(上班时间){ 关闭车门; 售票; 打开车门;}公车司机售票员只有关闭车门以后,才能启动汽车;只有停车以后,才能打开车门while(上班时间){ P(S_DoorClose); 发动汽车; 正常运行; 到站停车; V(S_Stop);} 公车司机while(上班时间){ 关闭车门; V(S_DoorClose); 售票; P(S_Stop); 打开车门;}售票员semaphore S_DoorClose;// 初始为0semaphore S_Stop;// 初始为0先关门后开车先停车后开门基于信号量的任务同步semaphore S, Q; //初始值均为1任务1 任务2P(S); P(Q);P(Q); P(S);V(S); V(Q);V(Q); V(S);信号量使用不当造成死锁死锁!死锁n死锁也称作抱死,指两个任务无限期地互相等待对方控制着的资源设任务T1正独享资源R1,任务T2在独享资源T2,而此时T1又要独享R2,T2也要独享R1,于是哪个任务都没法继续执行了,发生了死锁。
最简单的防止发生死锁的方法是让每个任务都:q先得到全部需要的资源再做下一步的工作q用同样的顺序去申请多个资源q释放资源时使用相反的顺序内存布局n.text:代码段,包含操作系统和应用程序的所有代码;n.data:数据段,存放了操作系统和应用程序当中所有带有初始值的全局变量;n.bss:bss段,存放了操作系统和应用程序当中所有未带初始值的全局变量;n堆空间:动态分配的内存空间,malloc/free;n栈空间:保存运行上下文以及函数调用时的局部变量和行参text.data.bss堆空间栈空间n对于.text、.data和.bss段,它们的大小在编译时即可确定,称为静态段;n对于堆和栈,它们的大小在编译时不能确定,而且在运行时会发生变化,称为动态段(有些嵌入式系统以静态数组的方式来实现任务的栈空间,其大小是固定的);I/O地址n按交互方向分类:n输入设备:键盘、鼠标、扫描仪;n输出设备:显示器、打印机;n输入/输出:磁盘、网卡n按数据组织分类:n块设备:以数据块来作为信息的存储和传输单位,每个数据块都有一个地址,如磁盘;n字符设备:以字符来作为信息的存储和传输单位,如打印机I/O设备的类型设备控制器机械部分机械部分电子部分电子部分一个I/O单元由两部分组成:机械部分和电子部分。
机械部分即为I/O设备本身;电子部分称为:设备控制器或适配器,它的功能是完成设备与主机间的连接和通讯I/O地址每个设备控制器都有一些寄存器用来与CPU通信通过往这些寄存器中写入不同的值,OS能命令该设备去执行发送数据、接收数据、打开、关闭等操作;OS也能通过读取这些寄存器的值来了解设备的当前状态此外,许多设备还有一个数据缓冲区供OS读写CPU外部设备控制逻辑电路控制寄存器状态寄存器数据寄存器现在的问题是:CPU如何与设备控制器当中的寄存器以及数据缓冲区来进行通信?因为这不是普通的内存访问!方法有三种:nI/O独立编址;n内存映像编址;n混合编址I/O独立编址n基本思路:给控制器中的每一个寄存器分配一个唯一的I/O端口(I/O port)编号,称为I/O端口地址,然后用专门的I/O指令对端口进行操作;n这些端口地址所构成的地址空间是完全独立的,与内存的地址空间没有关系例如:IN R0 [4] 表示读入I/O端口地址为4的内容;MOV R0 [4] 表示读入内存地址为4的内容;n优点:I/O设备不占用内存地址空间,而且程序设计时,易于区分是对内存操作还是对I/O端口操作n例子:8086/8088,给I/O端口分配的地址空间64K,0000H~FFFFH, 只有IN和OUT指令进行读写操作。
内存映像编址n基本思路:把所有控制器当中的每一个寄存器都映射为一个内存单元,专门用于I/O操作(功能上),对这些单元的读写操作即为普通的内存访问操作n端口地址空间与内存的地址空间统一编址,前者是后者的一部分,一般位于后者的顶端部分n优点:n编程方便,无需专门的I/O指令;n对普通的内存单元可进行的所有操作指令均可作用于I/O端口,如TEST指令;n无须专门的保护机制来防止用户进程执行I/O混合编址n基本思路:对于设备控制器中的寄存器,采用独立编址的方法;而对于设备的数据缓冲区,采用内存映像编址的方法n例如:Pentium,把内存地址空间640K-1M保留作为设备的数据缓冲区,另外,还有一个独立的I/O端口地址空间,从0-64KI/O独立编址内存映像编址混合编址到目前为止,已经介绍了I/O设备的类型、设备的控制器、I/O的端口地址现在的问题是:根据已有的这些知识,现在能否开始使用这些I/O设备,完成相应的输入输出功能呢?若能,如何来使用?答案是能!方法:程序循环检测I/O(Programmed I/O)I/O控制n程序循环检测方式(Programmed I/O);n中断驱动方式(Interrupt-driven I/O);n直接内存访问方式(DMA, Direct Memory Access);程序循环检测方式n基本思路:在程序(设备驱动程序)中通过不断地检测I/O设备的当前状态,来控制I/O操作的完成。
具体来说,在进行I/O操作之前,要循环地检测设备是否就绪;在I/O操作进行之中,要循环地检测设备是否已完成;在I/O操作完成之后,还要把输入的数据保存到内存(输入操作)从硬件来说,控制I/O的所有工作均由CPU来完成n也称为繁忙等待方式(busy waiting)或轮询方式(polling)n缺点:在进行I/O操作时,一直占用CPU时间一个例子已知I/O地址采用内存映像编址的方式,现需要在打印机上打印一个字符串“ABCDEFGH”基本思路:把这8个字符逐个送到打印机设备的I/O端口地址(内存地址)…A B C D E F G Hprinter_status_regprinter_data_register内存pfor (i = 0; i < count; i++){ while(*printer_status_reg != READY); *printer_data_register = p[i];}程序循环检测方式逐个打印每一个字符:先判断打印机是否空闲,若不空闲则循环等待然后把第 i 个字符复制给打印机的数据寄存器(内存单元)中断驱动方式循环检测的控制方法占用了太多的CPU时间,可能会造成CPU时间的浪费。
例如:假设打印机的打印速度为100字符/秒,在循环检测方式下,当一个字符被写入到打印机的数据寄存器中后,CPU需要等待10毫秒才能写入下一个字符一种解决的办法:中断驱动的控制方式中断机制在硬件一级,当一个I/O设备完成任务时,它的控制器会通过总线向中断控制器发出一个信号,如果中断控制器接受了该信号,就把标明该设备的一个编号放在地址线上,并向CPU发出一个中断信号 CPU就中断当前工作,并以该编号为索引去访问中断向量表,取出中断处理程序的起始地址,并在该程序运行后向中断控制器发出确认信号用户进程用户进程strcpy(buffer, “ABCDEFGH”);print(buffer, strlen(buffer)); 系统调用函数系统调用函数printcopy_from_user(buffer, p, count);enable_interrupts( );while(*printer_status_reg != READY);*printer_data_register = p[0];scheduler( );中断驱动方式 中断处理程序中断处理程序if(count == 0){ unblock_user( );}else{ *printer_data_register = p[i]; count --; i++;}acknowledge_intereupt( );return_from_interrupt( );中断驱动方式的基本思路是:用户进程通过系统调用函数来发起I/O操作,并在发起后阻塞该进程,调度其他的进程使用CPU。
在I/O操作完成时,设备向CPU发出中断,然后在中断处理程序中做进一步的处理在中断驱动方式下,数据的每次读写还是通过CPU来完成,但是当I/O设备在进行数据处理时,CPU不必等待,可以继续执行其他的进程直接内存访问方式n要使用直接内存访问(Direct Memory Access,DMA)的控制方式,首先在硬件上要有一个DMA控制器该控制器可集成在设备控制器中,也可集成在主板上nDMA控制器可以直接去访问系统总线,它能代替CPU去指挥I/O设备与内存之间的数据传送nDMA控制器包含了一些寄存器,可被CPU来读或写包括:一个内存地址寄存器、一个字节计数器,以及一个或多个控制寄存器(指明了I/O设备的端口地址、数据传送方向、传送单位,以及每一次传送的字节数)DMA工作原理(本图摘自(本图摘自Andrew S. Tanenbaum:: “Modern Operating Systems” ))5.第2章 目录n嵌入式系统硬件基础n嵌入式系统软件基础n嵌入式操作系统n嵌入式系统设计方法嵌入式系统的开发——流程选择主要芯片确定编程语言选择开发环境RTOS的使用测试工具与其他辅助设备确定产品需求选择开发方案选择开发方案设计与调试测试产品桌面应用程序的编译和加载过程嵌入式应用程序的编译和加载过程嵌入式系统的开发——设计与调试设计生产编译器链接器调试器IDE操作系统软件测试评估板仿真器逻辑分析仪边界扫描测试仪编程器开发环境n什么是嵌入式开发环境:源程序编译器目标文件链接器可重定位程序定位器可执行文件u编译器/汇编器/链接定位器u调试器/仿真器u主机(Host)及其工作平台u实时操作系统(可选)u目标评估系统(可选)u测试工具(软件/硬件/协议等,可选)u其他辅助设备(可选)n 典型的开发环境ARM的编译器(1)nADS1.2qARM公司出品qIDE环境,包括nARM/Thumb汇编器:armasmnANSI C 编译器 - armcc 和 tccnISO / Embedded C++ 编译器 - armcpp and tcppn链接器 – armlinknWindows 集成开发环境 – CodeWarriorn格式转换器 – fromelfn库管理器 - armarn调试器q模拟调试器:ARMulatorqJTAG调试:AXD(与Multi-ICE配合)q支持所有ARM内核,最新版本:RealView2.0ARM的编译器(2)nEW-ARMq瑞典IAR公司出品n著名的嵌入式工具提供商,以提供编译器/协议栈/统一建模工具著称n主要产品:Embeded Workbench(EW)、Make APP、Visual State等qEW-ARM:针对ARM的集成开发环境:nC/C++编译器nC-SPY 模拟调试器nROM-Monitorn多种级别代码优化方法,满足用户在速度、文件大小方面的要求n内建ARM特性优化器n支持多种断点模式n支持Nucleus, VxWorks等RTOSnGreenhillsnGNU嵌入式系统的调试(1)嵌入式系统的调试有四种基本方法: q模拟调试(Simulator)q软件调试(Debugger)qBDM/JTAG调试(BDM/JTAG Debugger)q全仿真调试(Emulator)嵌入式系统的调试(2)n模拟调试(Simulator) 调试工具和待调试的嵌入式软件都在主机上运行,由主机提供一个模拟的目标运行环境,可以进行语法和逻辑上的调试。
q优点:简单方便,不需要目标板,成本低q缺点:功能非常有限,无法实时调试大多数调试工具都提供Simulator功能嵌入式系统的调试(3)n软件调试(Debugger) 主机和目标板通过某种接口(通常是串口)连接,主机上提供调试界面,待调试软件下载到目标板上运行 这种方式的先决条件是要在Host和Target之间建立起通信联系(目标板上称为监控程序Monitor)q优点:纯软件,价格较低,简单,软件调试能力较强q缺点:需要事先烧制Monitor(往往需多次试验才能成功)且目标板工作正常,功能有限,特别是硬件调试能力较差 PCTargetMonitor串口嵌入式系统的调试(4)nBDM/JTAG调试 这种方式有一个硬件调试体该硬件调试体与目标板通过BDM、JTAG等调试接口相连,与主机通过串口、并口、网口或USB口相连待调试软件通过BDM/JTAG调试器下载到目标板上运行q优点:方便、简单,无须制作Monitor,软硬件均可调试q缺点:需要目标板,且目标板工作基本正常(至少MCU工作正常),仅适用于有调试接口的芯片 TargetPC接口BDM/JTAG Debugger嵌入式系统的调试(5)n全仿真调试(Emulator) 这种方式用仿真器完全取代目标板上的MCU,因而目标系统对开发者来说完全是透明的、可控的。
仿真器与目标板通过仿真头连接,与主机有串口、并口、网口或USB口等连接方式由于仿真器自成体系,调试时既可以连接目标板,也可以不连接目标板(Stand alone)q优点:功能非常强大,软硬件均可做到完全实时调试q缺点:价格昂贵ARM的调试方式n模拟调试qSDT2.52: ARMulatorqADS1.2:ARMulatorqTrace32:SimulatorqEW-ARM:C-spyn软件调试qADS1.2:Angel(串口)qSDT2.52 Angel(串口)nJTAG调试qARM:Multi-ICE,简易型仿真器qTrace32-ICD for ARMqHitex:Tanto for ARMn全仿真调试qTrace32-FIRE/ICEARM调试工具nMulti-ICEqARM公司出品q与ADS配套使用q支持不同的ARM内核q另有Multi-trace模块可选选择实时操作系统RTOSn对于复杂的嵌入式系统应考虑使用RTOSnRTOS的作用:q提供API(应用编程接口):操作系统为应用程序员提供可供调用的API,允许程序员致力于应用程序的开发 q简化系统设计:实时嵌入式系统比非实时系统更难设计. 使用实时多任务的内核能简化系统设计,可将复杂的应用程序分为几个不同的任务,由内核去对他们协调处理嵌入式系统的测试n新技术,新方法q使用边界扫描测试技术可以有效地解决这些问题!q边界扫描来源于IEEE Std 1149.1,是由联合测试行动小组(Joint Test Action Group)制定的一种测试逻辑,所以又称JTAG标准。
qJTAG作为集成电路的一部分,可以完成以下功能: 测试器件间的相互连线; 测试集成电路本身; 编程CPLD、FPGA、FLASH; JTAG仿真调试嵌入式开发工具与开发环境。
