完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1 前言
最近有一组学弟学妹问我一个问题,他们做的飞控系统,实时性总是达不到标准,来问我是怎么回事。 这涉及到了单片机/嵌入式系统实时性的问题,学长在这做一个系统性的解答。 2 单片机和嵌入式 说实话,关于它俩的区分,没有人可以给出一个标准的、正确的答案。每个人理解的单片机与嵌入式系统,都是略有差别的。 抛开硬件,从应用程序开发的角度来看,我是这样来理解的:
2.1 单片机 单片机,全称单片微型计算机(single-chip microcomputer),又称微控制器单元 MCU(microcontroller unit)。 把中央处理器、存储器、定时/计数器、各种输入输出接口等都集成在一块集成电路芯片上的微型计算机。 由于其发展非常迅速,旧的单片机的定义已不能满足,所以在很多应用场合被称为范围更广的微控制器; 2.2 嵌入式系统 嵌入式系统(Embedded System),是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。 嵌入式系统常被用于高效控制许多常见设备,被嵌入的系统通常是包含数字硬件和机械部件的完整设备,例如汽车的防锁死刹车系统。 现代嵌入式系统通常是基于微控制器(如含集成内存和/或外设接口的中央处理单元)的,但在较复杂的系统中普通微处理器(使用外部存储芯片和外设接口电路)也很常见。 2.3 嵌入式Linux 嵌入式Linux(英语:Embedded Linux)是一类嵌入式操作系统的概称,这类型的操作系统皆以Linux内核为基础,被设计来使用于嵌入式设备。 与电脑端运行的linux系统本质上是一样的,虽然经过了一些功能上的裁剪,但是本质上是一样的,主要利用 Linux 内核中的的任务调度、内存管理、硬件抽象等功能。 2.4 RTOS 实时操作系统(RTOS),又称即时操作系统,它会按照排序运行、管理系统资源,并为开发应用程序提供一致的基础。 实时操作系统与一般的操作系统相比,最大的特色就是“实时性”,如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。 3 系统实时性:非实时、软实时、硬实时 首先要明白什么叫实时性? 实时性考虑的不是速度、性能、吞吐量,而是确定性,也就是说:当一个事件发生的时候,可以确定性的保证在多长时间内得到处理,只要能满足这个要求,就可以成为硬实时。比如: 操作系统1:当中断发生时,可以保证在 1 秒内得到这里,那么它就是硬实时系统,虽然响应时间长,但它是确定的; 操作系统2:当中断发生时,几乎都可以在 1 毫秒内完成,那么那就不能成为硬实系统,虽然响应时间短,但是它不确定。 也看到有文章说:应该取消软实时这个模棱两可的说法,要么是实时,要么是非实时! 操作系统包含的功能很多:任务调度、内存管理、文件管理等等,其中最核心的就是任务调度,这也是非实时、软实时、硬实时的最大区别。 也就是说,衡量实时性的指标就是:
比如:我们的桌面系统,需要考虑的是多任务、并发,需要同时执行多个程序,哪个程序慢一点,用户无所谓,甚至觉察不到;但是对于一个导弹控制系统,当一个外部传感器输入信号,触发一个事件时,对应的处理必须立刻执行,否则耽搁 1 毫秒,结果可能就是差之千里! 4 x86 Linux 系统的调度策略 我们日常使用的 PC 机,它的主要目标是并行执行多任务,强调的是吞吐率(尽可能多的执行很多应用程序的代码),因此,采用的是分时操作系统,也就是每个任务都有一个时间片,当一个任务分配的时间片用完了,就自动换出(调度),然后执行下一个任务。 我们平常在写 x86 平台上写普通的客户端程序时,很少需要指定应用程序的调度策略和优先级,使用的是系统默认的调度机制。反过来说,也就是在某些需要的场合下,是可以设置进程的调度策略和优先级的。 例如在 Linux 系统中,可以通过 sched_setscheduler() 系统函数 设置 3 种调度策略:
可能有小伙伴会有疑问:既然 Linux 系统中提供了 SCHED_FIFO 基于优先级的调度策略,为什么仍然不能称之为真正的硬实时操作系统?这就要从 Linux 的发展历史说起了。 Linux 操作系统在设计之初,就是为了桌面应用而开发的,在那个时代,多个终端(电传打字机和屏幕)连接到同一个电脑主机,需要处理的是多任务、并行操作,并不需要考虑实时性,因此,在 Linux 内核中的一些基因,严重影响了它的实时性,例如有如下几个因素: (1) 内核不可抢占 我们知道,一个应用程序在执行时,可以在用户态和内核态执行(当调用一个系统函数,例如:write 时,就会进入内核态执行),此时任务是不可抢占的。 即使有优先级更高的任务准备就绪,当前的任务也不能立刻停止执行。而是必须等到当前这个任务返回到用户态,或者在内核态中需要等待某个资源而睡眠时,高优先级任务才可以执行。 因此,这就很显然无法保证高优先级任务的实时性了。 (2) 自旋锁 自旋锁是用于多线程同步的一种锁,用来对共享资源的一种同步机制,线程反复检查锁变量是否可用。由于线程在这一过程中保持执行,因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显式释放自旋锁。 自旋锁避免了进程上下文的调度开销,因此对于线程只会阻塞很短时间的场合是有效的,也就是说,只能在阻塞很短的时间才适合使用自旋锁。 但是,在自旋锁期间,任务抢占将会失效,这就是说,即使自旋锁的阻塞时间很短,但是这仍然会增加任务抢占延时,让调度变得不确定。 (3) 中断的优先级是最高的 任何时刻,只要中断发生,就会立刻执行中断服务程序,也就是中断的优先级是最高的。只有当所有的外部中断和软终端都处理结束了,正常的任务才能得到执行。 这看起来是好事情,但是想一想,如果有比中断优先级更高的任务呢?假如系统在运行中,网口持续接收到数据,那么中断就一直被执行,那么其他任务就可能一直得不到执行的机会,这是影响 Linux 系统实时性的巨大挑战。 (4) 同步操作时关闭中断 如果去看 Linux 内核的代码,可以看到在很多地方都执行了关中断指令,如果在这期间发生了中断,那么中断响应时间就没法保证了。 4.2 Linux 系统如何改成硬实时? 以上描述的几个因素,对 Linux 实现真正的实时性构成了很大的障碍,但是现实世界又的确有很多场合需要 Linux 具有硬实时,那么就要针对上面的每一个因素提出解决方案。 目前主流的解决方案有 2 个:
这种方式主要是对 Linux 内核进行打补丁,解决了上面所说的几个问题:内核不可抢占、自旋锁、关中断以及终端优先级的问题。 至于每一个问题是如何解决的,由于篇幅关系,这里就不介绍了,感兴趣的小伙伴如果需要的话,可以深入了解一下。 由于是直接在 Linux 内核上打补丁(以后肯定会合并到主分支中的),因此对于应用程序开发来说,操作系统向上层提供的 API 接口函数可以保持不变,这对应用程序开发来说是一件好事情。 (2)Xenomai Xenomai是一个 Linux 内核的实时开发框架,它希望通过无缝地集成到 Linux 环境中来给用户空间应用程序提供全面的,与接口无关的硬实时性能。下面是 Xenomai 的架构图: 在硬件抽象层之上,是 2 个并列的域(内核),这 2 个内核分别向上层提供自己的 API 接口函数。 图中 glibc 是 Linux 系统提供的库函数,应用程序通过调用库函数和系统调用来编写程序。 Xenomai 也提供了相应的库函数 libcobalt ,这个库函数是需要我们在用户层编译、安装的,就像安装第三方库一样。 |
|
|
|
只有小组成员才能发言,加入小组>>
3331 浏览 9 评论
3011 浏览 16 评论
3505 浏览 1 评论
9091 浏览 16 评论
4104 浏览 18 评论
1214浏览 3评论
628浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
614浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2356浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1917浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-7 23:31 , Processed in 1.255501 second(s), Total 78, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号