历史上的今天

今天是:2024年09月16日(星期一)

2021年09月16日 | Freestanding C与交叉编译器的生成原理分析

发布者:科技创客 来源: eefocus关键字:交叉编译器 手机看文章 扫描二维码
随时随地手机看文章

0 问题由来

以前也用过C51写过简单的裸机程序,但是并没有认真的考虑过其与Linux环境下一般C语言程序的不同,只是想当然地认为C是跨平台的语言,并没有考虑过C语言的标准问题。


今天在编译GCC交叉编译器时,遇到了种种问题,不得不重新考虑C语言的实现标准,否则很难清晰的了解交叉编译器的编译过程。


1 C编译器的两种实现要求

C语言标准的正式文档中明确提出了C编译器的两种实现标准:


1.1 conforming freestanding implementation

所谓的Freestanding,C编译器只需提供C语言语句的编译,外加



等基本的类型与数值范围定义头文件。


可以看出,在这种级别的编译器下写程序时,基本的printf都是不能够直接使用的。

此种实现,主要用于裸机开发,比如OS开发,bootloader,以及C库本身的开发。


1.2 conforming hosted implementation

这是一种更加全面的实现,除了包含Freestanding要求的功能外,必须包含完整的标准C库实现。这也是大多数应用程序员能接触到的环境。由于中的输入输出函数的实现需要OS系统调用的支持,Hosted编译器都是依赖于具体的操作系统而存在。


1.3 小结

可以看出,Hosted是比Freestanding更加全面的C实现要求,Hosted本身包含了Freestanding。例如Hosted的GCC实现,提供了-freestanding参数来作为Freestanding降级使用。


gcc -ffreestanding


C语言这种把语言本身和库独立对待的方式,使得它能够适应更广泛的开发环境。从单片机裸机开发到大型数据库系统,C语言的身影无处不在。


2 C语言的两种执行环境

与C语言的两种实现等级相对应,C语言的程序的执行环境也有两种,这里直接贴出C语言标准原文。


5.1.2 Execution environments

Tw o execution environments are defined: freestanding and hosted. In both cases,

program startup occurs when a designated C function is called by the execution

environment. All objects with static storage duration shall be initialized (set to their

initial values) before program startup. The manner and timing of such initialization are

otherwise unspecified. Program termination returns control to the execution

environment.


在Hosted环境下,C程序入口点必须是命名为main的函数,而且其函数原型必须符合标准。


而在Freestanding环境下,C程序的入口点没有指定的名称,由程序员自行决定。


3 C语言交叉编译器制作过程原理分析

3.1 为什么需要单独生成不同目标平台的编译器

理论上一个编译器可以通过命令行参数来编译生成各种不同平台的可执行程序。例如:


mycompiler -platform=arm-linux 1.c  # 生成可以运行在ARM平台上的Linux程序

mycompiler -platform=mips-linux 1.c # 生成可以运行在MIPS平台的Linux程序

mycompiler -platform=i386-linux 1.c # 生成可以运行在Intel X86平台的Linux程序


然而实际上,这种做法的代价是十分巨大的,因为


不同平台差异巨大,代码转换逻辑完全不同,在一个可执行程序中包含所有平台转换代码,导致编译器程序本身体积巨大


不同平台的C库实现严重依赖于平台,在一个库中包含所有平台的实现代码,造成C库体积巨大,管理混乱。


汇编器、连接器也存在同样的问题

所以在现实中,虽然GCC,GLIBC,binutils这样的项目本身能够支持很多的软硬件平台,但是支持方式是通过配置来进行选择性的编译部分源代码来生成针对具体平台二进制工具。


3.2 交叉编译器生成步骤原理分析

理论上一个C交叉编译器的生成非常简单:

(0)编译生成交叉汇编器和交叉链接器

之所以会存在这个步骤是因为,像GCC这样的C编译器本身只负责把C语言代码编译为汇编代码。把汇编代码转换为二进制机器码,以及把二进制对象文件链接为可执行文件的功能需要其他程序来实现。对Unix世界来说,提供汇编链接功能的就是著名的binutils包。


gcc编译器在生成时,需要使用binutils来测试相关功能,以动态生成各种配置与代码。所以,在编译GCC之前,必须要有可用的binutils。


对于汇编程序员来说,binutils已经提供了一个完整的汇编开发环境,完全可以停留这里享受汇编程序设计的美好。

然而,对于C程序员来说,这才刚刚开始。


(1)编译生成Freestanding的交叉编译器;

这个交叉编译器完全可以用来编译裸机C程序,编译OS,编译BootLoader,对于嵌入式底层开发者来说,这样一个编译器就足够了,完全可以到此为止。


然而对于一个在OS环境下的应用开发者来说,就需要一个功能更完整的编译器,以及完整的标准C库,这就需要进入步骤(2)。


(2)用刚生成的交叉编译器编译生成标准C库;

Freestanding编译器可以用来编译标准C库,这个是很重要的。


此时虽然编译器和C库都有了,却存在两个缺陷:


编译器可执行文件本身并不知道对应的C库的路径,所以编译程序时就需要额外的命令行参数来提供这些信息。


编译器不能提供Hosted类型C程序初始化环境,因为Hosted环境的建立需要标准C库的支持,而Freestanding编译器在生成时还没有可用的标准C库。这就是一个“鸡生蛋蛋生鸡”的问题了。


为了解决上述问题,需要额外的一个步骤:

(3)重新编译生成Hosted的交叉编译器。

这次编译时,可以有(2)生成的标准C库的支持了,所以可以产生出一个完整的Hosted交叉编译器了。

关键字:交叉编译器 引用地址:Freestanding C与交叉编译器的生成原理分析

上一篇:TQ2440开发板学习纪实(3)--- 设置时钟频率,让CPU运行的更快
下一篇:原来程序是这样从NandFlash拷贝并跳转到SDRAM的

推荐阅读

去年的十月份,谷歌在发布会上发布了旗下的笔记本产品:Pixelbook,第一代的Pixelbook搭载了12.3寸的触控屏,QHD分辨率,像素密度235ppi可以说表现不俗了。此外,软触键盘支持背光,多个版本的酷睿i5/i7处理器可供选。此外,内存组合上,拥有最高16GB内存+512GB 的存储组合,可以说存个片都够用了。10小时电池续航,双USB-C接口。第一代的Pixelbook可...
2018年全球芯片销售额约为4688亿美元,中国进口芯片3120亿美元,占比2/3。这意味着世界上每生产3颗芯片就有2颗运往中国。进口到中国的芯片中,大约有一半又被装到整机中出口到全区各地。清华大学微电子所所长魏少军教授在接受采访时表示,中国本土去年生产了大概370亿美元的芯片,所以实际上真正用到的进口芯片只占进口额的40%,这是中国融入全球化的重要...
智能手机为了机身更加轻薄,慢慢开始取消耳机孔,无线蓝牙耳机市场慢慢扩大,一般我们使用的都是手机同品牌的蓝牙耳机,其实还有更好的选择。QCY 推出的T1C真无线蓝牙耳机将蓝牙耳机做到了百元以内,性价比和Redmi差不多,续航和音质都很不错,耳机仓充满电可续航一周左右。今天我们来看看这款蓝牙耳机有什么特别之处。器件分析:提起QCY这个品牌,大家可...
微机继电保护测试仪自带大屏幕液晶显示器以及灵活方便的旋转鼠标控制器。继电保护测试仪可以进行大多数试验,连接电脑运行则具有更强大的操作功能,体积小,精度高,这块仪器在电力方面使用的比较常见。在美国,应用了三种不同类型的继电器:机电式、固态和微处理器,在美国,约有50%的继电器是机电产品,其中50%包含8-10%的固态继电器,随着继电器的多样...

史海拾趣

问答坊 | AI 解惑

232烧坏咋办

.串口插拔最好要断电,不能热插拔,否则容易烧坏串口:如插拔时候有时是TXD先电脑串口连接,而GND后面才连上,导到压差大于12V,导致串口损坏。所以以上问题也可以是你经常热插拔引起的,(理解:PC与设备有共地,造成信号线上电压过大。 )  ...…

查看全部问答∨

关于SD卡读写速度的问题

各位大侠,请问一下大家没有有谁碰到过SD卡写单一块后出现读速度变慢的情况. 如果有出现过,是否知道是什么原因引起的?…

查看全部问答∨

【求助】求orcad书籍推荐

        想找一本关于Orcad电路设计的书,能提高与实践的,求各位推荐下,有心得的介绍下,谢谢!…

查看全部问答∨

针式打印机如何打印曲线

请问各位大哥:      单片机如何控制针式打印机打印出曲线图来?有没有做过的?曲线是展示温度随时间变化的曲线,由单片机采集数据然后发送到打印机!…

查看全部问答∨

关于wince5 串口中断服务函数SerialDispatchThread的疑问

在SerialDispatchThread函数中有下面语句,请问: /* Wait for the event that any serial port action creates.      */     while ( !pSerialHead->KillRxThread ) {         DEB ...…

查看全部问答∨

小菜鸟问个PIC单片机的基础问题。。。。。。

用PIC单片机控制一个LED的亮灭。程序如下:  #include<pic.h>  void delay() {unsigned char a,b,c; for(a=20;a>0;a--) for(b=20;b>0;b--) for(c=248;c>0;c--); } void main() {TRISA=0x00; while(1) {POR ...…

查看全部问答∨

关于stm32系统时钟的一些问题

关于系统时钟有几个疑问,想请教大家 1,一个系统的系统时钟的大小是由什么来决定的阿?比如我刚开始建系统时选择使用了最高频率72M,等到现在整个系统的功能写的差不多了,老板问我能不能将频率调低一点,减少功耗,我就有点焉了,不知道怎 ...…

查看全部问答∨

模拟系统加混合式DVR应用要点及未来发展

 模拟和IP视频的优劣是行业的一个热点,争议点包括了相对的可靠性、方便性、成本和性能。不管争论的结果如何,传统模拟系统+混合式DVR的应用有两种情况不容忽视。 需要高清晰度的视频 IP摄像机可实现高清晰度(百万像素)视频,每帧可以传100 ...…

查看全部问答∨

TI原装6416开发板USB接口能往外传数吗?

买了一个TI原装的tms320c6416 dsk,USB接口是用来做仿真调试用的,不知道能否用来往pc机传数据。理论上是可以。不知道怎么操作。 [ 本帖最后由 dsp_comm 于 2011-4-30 07:30 编辑 ]…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved