提问人:Dainank 提问时间:10/31/2023 最后编辑:trincotDainank 更新时间:11/11/2023 访问量:70
为什么一些较小的嵌入式设备无法运行操作系统(它们究竟运行什么)?
Why are some smaller embedded devices unable to run an operating system (and what exactly do they run off of instead)?
问:
作为上下文,这是从一本书的摘录中摘录的: 最后,有时你甚至不能使用堆内存!如果你在 Rust 中为一个小型嵌入式设备编程,你将只需要使用堆栈内存。没有操作系统可以在小型嵌入式设备上请求堆内存。
来自嵌入式知识有限的人,为什么一些较小的设备无法运行操作系统。肯定有为这些类型的设备设计的超轻量级操作系统吗?
如果没有操作系统,那么设备到底运行了什么?
我想在没有操作系统的机器上运行的任何程序都将无法利用堆,而只能求助于堆栈(是否有解决方法; 虚拟堆?[或者我们是在创建一个操作系统?
如果缺乏上下文,那么我们可以关闭这个问题(因为这是本书提供的关于“小型嵌入式设备”和“无操作系统”的所有信息),尽管对我来说,问题只是变成了,在什么时候嵌入式设备被认为不再运行在操作系统上,而只是遵循一组原始指令?
答:
没有操作系统可以在小型嵌入式设备上请求堆内存。
这是第一个谬论。虽然在具有操作系统的系统中,是操作系统按需提供该内存,但这并不意味着没有操作系统就不能拥有堆。你可以而且经常这样做。在某些嵌入式系统中,何时以及是否适合使用堆是一个不同的问题。例如,存在不确定的时序、碎片化、故障处理等问题,这些问题不适合关键任务、安全关键或实时关键型应用。使用堆(或至少通过标准库访问的标准堆)通常是不明智的,但缺少操作系统不是其中之一。
为什么一些较小的设备无法运行操作系统
这取决于您对操作系统的定义,但许多微控制器只有几十千字节或更少的内存。操作系统提供各种服务,其中可能只有一小部分将由特定于应用程序的嵌入式系统使用,因此仅包含实际需要的服务以最小化占用空间是有意义的。
也就是说,许多 RTOS(实时操作系统)是可销售的,并且仅链接应用程序引用的目标代码。在这种情况下,RTOS 作为常规静态链接库提供,而 RTOS 和应用程序是单个单体链接实体。这可能不符合您或作者对操作系统的定义。最小的 RTOS 提供线程调度内核和进程间通信、定时和同步原语,可以扩展到 < 10Kb ROM 的占用空间,并支持受可用 RAM 和线程堆栈大小要求限制的线程数量。
RTOS 通常不会提供您可能与操作系统相关的功能,例如命令 shell、应用程序加载器、文件系统、网络。在小型嵌入式系统中,这些组件通常独立于 RTOS,可以根据需要从内部开发的各种第三方添加。SOme RTOS 供应商提供了这样的“中间件”,可以很容易地与他们的特定内核集成。
嵌入完整的操作系统需要更多的资源。GPOS(通用操作系统),例如 Linux,即使是最小的系统也需要 4Mb ROM 和 16Mb RAM。此外,它将在几十秒内启动,而不是许多更简单的嵌入式系统通常需要几十毫秒。
肯定有为这些类型的设备设计的超轻量级操作系统吗?
是的,有许多不同复杂程度和可扩展性的 RTOS,从低端(如 uC/OS-III、FreeRTOS、ThreadX 和 embOS)到中端(如 eCOS),再到高端(如 VxWorks、OS/9 和 QNX)。
如果没有操作系统,那么设备到底运行了什么?
为什么你认为你需要一个操作系统来运行代码?毕竟,操作系统就是代码。嵌入式系统是在特定应用硬件上运行的特定应用软件。该应用程序可以在自身中嵌入所有必要的硬件支持,以及所有必要的过程计时和管理。如果嵌入某种标准架构的 COTS(商用现成)板,操作系统可能很有用,但通常这种支持将由板供应商作为 SDK、框架或库提供,而不是真正的操作系统。例如,Arduino和Mbed框架在许多现成的嵌入式硬件设备上运行。
我想在没有操作系统的机器上运行的任何程序都将无法利用堆,而只能求助于堆栈(是否有解决方法; 虚拟堆?[或者我们是在创建一个操作系统?
正如我所说,事实并非如此。例如,嵌入式系统中使用的通用 C 库是 Newlib,它包括一个堆实现,并提供一组用户可替换的存根(称为 syscalls)来将库映射到平台(主要用于内存管理和标准 I/O)。要支持堆,只需要实现 syscall,即用于“请求”堆内存的 syscall。这可以实现为调用操作系统以获取内存,也可以实现为简单地返回静态块以用作堆。例如,下面是一个最小的实现,它只需要链接器符号并定义要使用的空间(堆)即可工作:_sbrk()
__heap_start
__heap_end
void* _sbrk (int incr)
{
extern char __heap_start;//set by linker
extern char __heap_end;//set by linker
static char *heap_end; /* Previous end of heap or 0 if none */
char *prev_heap_end;
if (0 == heap_end) {
heap_end = &__heap_start; /* Initialize first time round */
}
prev_heap_end = heap_end;
heap_end += incr;
//check
if( heap_end < (&__heap_end)) {
} else {
errno = ENOMEM;
return (char*)-1;
}
return (void *) prev_heap_end;
}
如果缺乏上下文,那么我们可以关闭这个问题(因为这是本书提供的所有信息
唯一缺乏上下文的是您从未引用过相关出版物。姓名、作者、版本、ISBN 等。这本书似乎缺乏权威性,但这对作者来说可能是不公平的,因为我们只有你对作者所说内容的简要总结。
在什么情况下,嵌入式设备不再被视为在操作系统上运行,而只是遵循一组原始指令?
没有操作系统并不一定意味着“原始”。尽管任何没有正式操作系统的成功/高效的大型应用程序本质上都可能是其自己的应用程序特定操作系统,但设备/硬件抽象层、进程调度、进程通信、内存管理等作为应用程序的一部分。
评论