,如果希望加强管理,背后的故事 谢霆锋则会使用C衍生的C++。可能会有一些关键代码片段是以汇编语言编写的,但是,据Barr集团最近的一项研究表明,目前95%的
然而,世界是在变化的。新的程序员、新挑战以及新体系结构让C松开了在嵌入式软件上的“抓手”。据最近的一项研究表明,嵌入式计算语言发展最快的是Python,当然还有很多其他参与竞争的语言,只是这些语言仍然占少数。但是逐渐地,一直使用C/C++的程序员像20年前汇编语言专家那样开始冒险——采用更快、更紧凑和更可靠的程序。 图1提出了新语言能够提高嵌入式计算机领域的效能。
嵌入式算法变革的一个主要推动力量是其他工作的程序员进入了嵌入式领域。这方面最明显的是刚毕业的学生进入职场。以前,刚毕业的学生在C课程中学会了编程,会用C或者C++完成他们的大部分项目。而现在,已经不再如此了。Intel软件工程经理David Stewart注意到,“现在,大部分计算机科学课程使用Python作为他们的入门语言。”计算机科学专业毕业的学生很有可能在Python、Ruby以及几种脚本语言上有丰富的经验,但是他们可能从未认真地使用过C语言。同时,其他影响也越来越多。使用Android作为平台进行相关的或者用户友好的嵌入式设计,为Android的自然语言——Java,带来了机会。在这一复杂景象的另一端,机器人、无人机或者相似的小项目业余爱好开发人员通常都有Arduino或者Raspberry-Pi背景。他们的经验会体现在非常紧凑和简单的程序发生器或者B#等小型语言里。
这一现象对物联网(IoT)的广泛研究也产生了影响,网络开发人员也参与到讨论中。他们认为,如果嵌入式系统的外部接口是RESTful Web,编程语言应该是JavaScript或者其服务器侧相关的Node.js。热衷于使用C语言进行开发的人员应该观察一下node.js——贝宝和沃尔玛等公司在企业规模的开发中大量使用了这一可扩展平台,据调查网站在任何编程语言中,该平台的辅助支持系统增长是最快的。
选择Node.js的动机部分是源自文化,但是也有体系结构方面的因素。IoT会在客户侧、互联网以及服务器侧之间分配其嵌入式系统任务。其中,客户侧连接实际,通常要求尽可能少地采用硬件。客户侧很自然地采用硬件专用库支持的Web应用程序,而服务器侧则是服务器应用程序。这样,对于Web程序员,在IoT系统编程中很显然会使用JavaScript和Node.js。
日益复杂的嵌入式算法是变革的另一推动力量。简单的控制环被卡尔曼滤波器、神经网络以及基于模型的控制功能所替代,高性能计算语言——Python,计算语言(例如OpenCL™)以及MATLAB等基于模型的逐渐发展起来。
那么这些新人们为什么不静下心来学习C语言呢? Stewart说:“真正的原因在于开发人员的效能。”反对C语言的人一直认为这种语言编写慢,容易出错,会带来意想不到的硬件相关问题,并且除了最初的程序员,其他人很难读懂它。这些因素会对提高设计效能产生不利影响。而很多最近出现的语言逐步转向快速学习和高效的代码重用。虽然目前几乎所有语言都受益于C语言高度简洁的语法,但现在的重点已经转回可读性,而不是最少字符数。不但在现代语言中鼓励实现协调一致的文档,而且结构化约定也通常会这样定义文档。C程序员一直把这类文档看成是表述的例子,因为作者自己不会其中。例如,这些约定使得实用工具程序能够从Python组件的结构化注释中生成用户手册。
现代语言还采用了高级数据结构,可以在C++中建立任何对象,并重用它。基于指针,Python还提供自然List和Dictionary数据类型。而Ruby等其他语言,基本上是面向对象的,支持结构和重用,这使其可以融入到程序员的习惯中。
影响了现代语言是否易于重用的另外两个重要因素是动态输入和模块化。动态输入是一个很有争议的因素。当程序员在使用变量时,解释程序确定程序员传送给表达式的数值的当前数据类型——几乎所有这些服务器侧语言都是解释性的,而不是编译的。然后,解释程序会选择相应的操作,评估含有该数据类型的表达式。这样,程序员不用太过担心他要调用的函数需要的是整数变量还是实数变量。但是,嵌入式程序和代码可靠性专家很快指出,动态输入在运行时实际上效率不高。另一个因素是部分程序员对模块化的。有时候会有人说,Python编程实际上不是编程,而是脚本,是把别人用C语言编写的函数调用或串起来。
可读性、协调一致的文档、动态输入以及函数大量的重用等,催化了开源领域中辅助支持系统的爆发。程序员本能地会在巨大的开源库中找到他们能够使用的函数,例如,npm (用于Node.js)、PyPI (用于Python)或者(用于Ruby)。如果他们不用修改组件或者编写新的组件,他们会回到库中工作。结果,库会越来越大(npm目前大概有25万个组件)。这些大规模的辅助支持系统也相应地大幅度提高了程序员的效能。
大部分这些语言最明显的问题是,它们是解释性的,而不是编译的。这意味着它们需要可观的运行时程序包,包括解释程序本身、工作存储、动态输入开销和运行时库等,都要适配到嵌入式系统中。基本上,所有这些会非常紧凑,某些Java虚拟机可以装入到几十K字节中,但是Node.js、Python以及来自服务器侧相似的语言需要自己的空间。一个兼容性还可以的Python虚拟机在加入程序员自己的代码之前可能已经占用了几兆字节。
在性能问题方面,解释程序读取每一行代码(源程序或者预处理过的中间级代码)需要解析它、进行运行时检查以及调用执行所需操作的例程。在C语言中,这会导致一行代码有很多操作,编译成很多机器语言指令。执行时间和能耗的成本都会增加。
在运行时效率方面,可以使用即时(JiT)编译器进行改进。一个JiT编译器可以与解释程序并行工作,为循环中的代码生成编译后的机器指令,因此,后续的代码能够更快地执行。Stewart说:“JiT技术非常有趣,PyPy JiT编译器把Python执行速度提高了两倍。”对于效率方面,还研究了其他方法。例如,如果函数是无阻塞的,或者使用了信令机制,有很多函数调用的程序即使是在采用循环展开等方法来建立更多的线程之前,也可以含有很多线程。因此,可以在一个组件上应用很多多线程内核——这是高性能计算已经研究应用的方向。更进一步,Ruby语言本身支持多线程,因此,即使底层操作系统不支持线程,它也能够产生线程代码。某些团队则寻求在硬件加速器中实现库或者组件,例如,图形处理单元(GPU)、Xeon Phi和FPGA。实际上,解释程序本身就会有适合加速的任务。
服务器侧语言遇到的其他困难是缺少处理实际的结构。在服务器中,除了网络和存储,没有实时,也没有I/O。可以通过几种方式来解决这一问题。
最简单的是,Android以硬件几乎无关的抽象方式包封Java代码:具有图形、触摸屏、音频、视频、多个网络以及物理传感器的虚拟机。对于更强调物理I/O,甚至能够在微控制器上运行的轻型平台,提供嵌入式Java。
Python等语言需要不同的方法。由于CPython解释程序运行在Linux上,因此,原理上能够运行在有足够速度和物理存储器的任何嵌入式Linux系统中。在这方面已经有了工作基础,通过减小装入时间开销,为物理I/O访问提供功能,使用硬件加速器,进一步适应CPython,运行时系统适应实时约束。最新的一个实例是STM32微控制器的裸金属Micro Python。虽然这看起来几乎不可能,但是已经在Node.js下面的JavaScript引擎上有了类似的工作。
安全呈现出更多的问题。很多安全和可靠性标准不鼓励甚至使用未经正式认证或者全面测试的开源代码。这些使得不可能重用组件,或者重用组件过于复杂,对效能的提高不大。同样等级的详细检查也延伸到虚拟机等开源中。在可靠和安全大下,CPython等开源平台很容易受到。
最后,考虑到有众多的推动力量促使新语言进入嵌入式世界中,可以预见到会有多语系统,这种系统含有的组件来自多种源语言,每一种选择要使用的关键库,或者方便某类开发人员使用。当然,您可以在不同的CPU内核上放置几种虚拟机,在一个内核管理程序下相统一,然后,通过函数调用,为任务间消息的传送提供约定。但是,这样的系统最终会非常大。
另一种可能是一组语言相关解释程序,为JiT编译器生成公共中间代码(图2)。当然,还能列出其他问题,例如,不同的任务间具有不同的通信模型、存储器模型和调试,但这些问题总是能够解决的。
如果这些最终会到来,那么,一名经验丰富的嵌入式程序员该如何应对? 您可以从Web编程、服务器甚至业余爱好者使用的开发中研究这些语言。您可以在下一项目中,尝试在C++和解析语言中开发组件。这需要时间学习,但是并行开发是值得的。
本文来源于中国科技核心期刊《电子产品世界》2016年第6期第18页,欢迎您写论文时引用,并注明出处。
本文由海南柴油发电机组 www.hnjqc.cn整理发布