嵌入式操作系统_嵌入式操作系统怎样支撑C++运行时环境

C++概述

C语言是当今最流行的程序设计语言之一,它的功能丰富、表达力强、使用灵活方便、应用面广、目标程序高、可植入性好,既有高级语言的特点,又有低级语言的许多特点,适合作为系统描述语言,既可以用来编写系统软件,也可以用来编写应用软件。在C的基础上,一九八三年又由贝尔实验室的Bjarne Strou-strup推出了C++。 C++进一步扩充和完善了C语言,成为一种面向 对象的程序设计语言。C++目前流行的集成开发环境最新版本是Borland C++4.5,Symantec C++6.1,和Microsoft VisualC++2017。C++提出了一些更为深入的概念,它所支持的这些面向对象的概念容易将问题空间直接地映射到程序空间,为程序员提供了一种与传统结构程序设计不同的思维方式和编程方法。因而也增加了整个语言的复杂性,掌握起来有一定难度。

C++17 是继 C++14 之后,C++ 编程语言 ISO/IEC 标准的下一次修订的非正式名称。ISO C++ 委员会正式发布了 C++ 17 标准,官方名称为 ISO/IEC 14882:2017。

a13067ca22cd0ca317d21087cbd1e515.png

基于 C++ 11,C++ 17 旨在使 C++ 成为一个不那么臃肿复杂的编程语言,以简化该语言的日常使用,使开发者可以更简单地编写和维护代码。C++ 17 是对 C++ 语言的重大更新,引入了许多新的语言特性。

嵌入式操作系统适配C++

GCC编译器编译 C++ 工程时, 如果存在全局对象, 那么全局对象的构建函数指针会放在可执行 elf 文件的 .ctors 节区(section), 析构函数会放在可执行 elf 文件的 .dtors 节区, 一般标准 gcc 库会引出四个符号:

__CTOR_LIST__

__CTOR_END__

__DTOR_LIST__

__DTOR_END__

其中 __CTOR_LIST__ 表示所有的全局对象构造函数指针数组的首地址, 起始指针为 0xFFFFFFFF, 之后的每一项为一个构造函数的入口, 直到 __CTOR_END__ 为止, __CTOR_END__ 指向的函数指针为 0x00000000。

其中 __DTOR_LIST__ 表示所有的全局对象析构函数指针数组的首地址, 起始指针为 0xFFFFFFFF, 之后的每一项为一个析构函数的入口, 直到 __DTOR_END__ 为止, __DTOR_END__ 指向的函数指针为 0x00000000。

系统在运行用户程序之前, 初始化 C++ 环境, 需运行全局对象的构造函数, 在系统 reboot 时, 运行系统的析构函数。

编译GCC工具链时,GCC源码路径下的libgcc/crtstuff.c会生成两个二进制文件crtbegin.o和crtend.o,其__CTOR_LIST__、__CTOR_END__、__DTOR_LIST__和__DTOR_END__位于上述两个文件。

ec073245a3db72ce8869a19fa3a98d2a.png

构造函数为__do_global_ctors_aux,其实现为循环调用各个全局构造函数,其简化代码如下:


static void __do_global_ctors_aux (void)

{

func_ptr *p, f;

for (p = __DTOR_LIST__ + 1; (f = *p); p++)

f ();

}


0b5a91fa549e05c8fc44dd77b87e56c6.png

但是构造函数__do_global_ctors_aux和析构函数__do_global_dtors_aux为静态函数,无法直接调用,构造函数被包含在.init段中,析构函数被包含在.fini段中。因此我们需要自己实现一个函数包含.init段调用__do_global_ctors_aux构造函数。其实现代码如下:

.section ".init_begin"

.global initCplusplus

initCplusplus:

push %ebp;

mov %esp,%ebp

.section .init_end

leave

ret

连接脚本中.init段位于.init_begin和.init_end中间。其连接示例脚本如下:

*(.init_begin);

*(.init);

*(.init_end);

因此编译出的代码如下:


4003295d :

4003295d: 55 push %ebp

4003295e: 89 e5 mov %esp,%ebp

40032960: e8 7f ed fc ff call 400016e4

40032965: e8 fa b1 ff ff call 4002db64 <__do_global_ctors_aux>

4003296a: c9 leave

4003296b: c3 ret


initCplusplus函数在操作系统启动中调用后C++应用程序的全局构造函数就被调用了,具备了C++的基本运行环境。因为C++会引入很多段信息,因此链接脚本需要添加很多段,为了简化实现,可在代码段的添加 *( .text.* ) ,数据段增加*( .data.* ),bss段增加*( .bss.* )等。

操作系统cout适配

libstdc++库的ios_base::Init::Init()函数中会初始化输入输出流相关操作。代码如下:

new (&buf_cout_sync) stdio_sync_filebuf(stdout);

new (&buf_cin_sync) stdio_sync_filebuf(stdin);

new (&buf_cerr_sync) stdio_sync_filebuf(stderr);

new (&cout) ostream(&buf_cout_sync);

new (&cin) istream(&buf_cin_sync);

new (&cerr) ostream(&buf_cerr_sync);

new (&clog) ostream(&buf_cerr_sync);

上述代码分析知道cout实际调用的是stdio_sync_filebuf类相关接口,最终cout会调用std::fwrite等操作系统相关接口。上述关键在于stdout、stdin、stderr与操作系统相关,因为GCC与newlib绑定。newlib把stdout、stdin、stderr三个指针设置到了_reent结构体里的__FILE *_stdin, *_stdout, *_stderr三个变量。

struct _reent _impure_data = _REENT_INIT(_impure_data);

struct _reent *_impure_ptr = &_impure_data;

_reent结构体里涉及__FILE *_stdin, *_stdout, *_stderr;三个变量,上述三个变量需要设置为自己操作系统的tdout、stdin、stderr。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于Unity保存运行时操作,可以使用Unity中提供的PlayerPrefs功能,它可以在运行时保存数据并在下次运行时恢复数据。使用PlayerPrefs可以保存基本类型、字符串和一些自定义类型。以下是示例代码: ``` // 保存数据 PlayerPrefs.SetInt("score", 100); PlayerPrefs.SetString("playerName", "Tom"); PlayerPrefs.Save(); // 恢复数据 int score = PlayerPrefs.GetInt("score"); string playerName = PlayerPrefs.GetString("playerName"); ``` 至于嵌入式实时操作系统支撑C++17运行时环境,我不太清楚您的具体需求和情境,可以提供更详细的信息吗?同时,如果您需要在Unity中使用C++代码,可以使用Unity的插件系统和Native Code Plugin功能,将C++代码编译为动态链接库并在Unity中调用。 ### 回答2: Unity是一个跨平台的游戏开发引擎,它可以创建2D和3D游戏,支持多种平台,包括PC、移动设备和主机等。对于Unity中的运行时操作,可以通过以下方式进行保存: 1.场景保存:Unity的场景是游戏中的一个环境或关卡,可以包含各种游戏对象、脚本和其他资源。在编辑器模式下,我们可以将场景中的操作保存到硬盘上的场景文件中(.unity文件)。这样,当我们重新打开项目时,可以加载之前保存的场景,继续进行编辑或运行。 2.脚本保存:Unity使用C#作为主要的脚本编程语言,我们可以使用文本编辑器(如Visual Studio)编写C#脚本,并将其保存为.cs文件。这些脚本通常用于实现游戏逻辑和功能性操作。一旦保存,脚本中的修改将被持久保存,可以在需要的时候重新加载使用。 3.资源保存:在Unity中,资源是指可重用的游戏素材,如纹理、模型、声音等。我们可以将这些资源保存到项目目录下的特定文件夹中。通过保存资源,我们可以在任何时候使用这些资源来创建、实例化对象或加载到场景中。 对于嵌入式实时操作系统,Unity同时也可以支持C 17运行时环境。嵌入式实时操作系统被广泛应用于实时交互性较高的场景,如游戏、机器人和自动化控制系统等。Unity提供了与C 17运行时环境的兼容性,使得在Unity中使用嵌入式实时操作系统成为可能。在这种情况下,可以通过Unity的引用和交互方式,将嵌入式实时操作系统与Unity进行集成,并在Unity中进行实时操作系统相关的开发和调试工作。这样,可以更方便、高效地进行实时交互性较高的游戏和应用程序的开发。 ### 回答3: Unity是一款跨平台的游戏开发引擎,它支持将游戏开发和设计的过程从嵌入式实时操作系统(RTOS)中分离出来。Unity引擎提供了多种方式来保存运行时的操作,以便在需要时进行加载和恢复。 首先,Unity提供了场景的保存和加载功能。在开发游戏时,我们可以将场景的状态保存为一个文件,其中包含了场景中所有的对象、组件和其对应的状态信息。这样,当我们需要恢复之前的游戏状态时,只需加载保存的场景文件即可。 其次,Unity还支持保存和加载游戏中的运行时数据。在游戏运行过程中,我们可以将重要的游戏数据保存在特定的位置,如本地硬盘或云端存储。这样,即使游戏关闭或设备重启,我们也能够在下次游戏运行时恢复之前的数据状态。 另外,Unity还提供了序列化和反序列化功能,允许我们将对象或数据结构转换为字节流并保存在存储设备上。通过这种方式保存的数据可以在需要时进行反序列化,以恢复对象的完整状态。 最后,Unity还支持使用PlayerPrefs来保存和加载游戏的一些设置和配置。PlayerPrefs是Unity提供的一种用户偏好设置存储机制,可以保存一些简单的键值对数据。这样,我们可以在游戏中保存用户的一些个性化设置,以便在下次游戏运行时进行加载和应用。 综上所述,Unity提供了多种方式来保存运行时的操作。无论是保存场景状态、游戏数据、对象序列化还是用户设置,都可以通过Unity的相关功能进行实现。这些保存和加载的功能为游戏的长时间运行和用户体验的连续性提供了便利。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值