天天看点

关于_main 和main ,__rt_lib_init的讨论18573103324

根据网上的文章,关于ADS的C程序入口一些问题,矛盾之处甚多,笔记一下,求答。

问题(参照3篇文章):

1.根据A的观点,_main()函数是在我们的主函数main()之前完成一些初始化工作的,由编译系统自动生成,那么_main()是不需要我们调用也是我们无法调用的,既然如此,B,C说法就矛盾了,B说所以我们不用__main()函数初始化运行环境的时候,要自己编写相应的代码来完成相应的内容,C说,如果在C入口没有调用编译器的链接库(__main),不是说_main()不需要我们调用,而且在main()调用前C库已经调用了,怎么存在不调用的情况?

实际问题就是:_main()是否是编译系统自动调用,并且是在main()函数之前?

2.A原文说,用main()函数的返回值作参数调用exit()。 在main()函数返回之后,相当于程序结束了,那返回个值有什么意义?假如说调用exit()是释放资源,直接返回不就行了?

A原文描述:

http://www.west263.com/info/html/chengxusheji/C-C--/20080224/10517.html

ARM应用系统开始执行用户应用程式,必须先将应用程式加载到执行域,建立应用程式的执行环境。使用C库时,这些繁琐的工作就大部分由c函数来完成了。汇编程式完成系统初始化后,跳转到C程式的人口_main()(注意:不是main(),当C程式中定义了main()主函数时,编译器就会生成_main代码)。由_main()引导库函数完成C执行环境的初始化,具体过程如下:

◇将非启动代码的RO和RW执行域代码从加载域地址复制到执行域地址;

◇将ZI域清零;

◇跳转到_rt_entry。

调用_main()将大大简化汇编启动代码的编写,汇编代码仅需完成系统硬件的初始化,而没有必要将代码从加载域地址复制到执行域地址,连同ZI域清零等工作。特别是当使用分布式加载时_main()的作用就更加明显了。但是_main()并没有建立C库运行必须的环境,这项工作由_rt_entry()完成,主要调用过程为:

◇调用_rt_stackheap_init()建立堆和栈;

◇调用_rt_lib_init()初始化引用的库函数;假如需要,建立main()函数的参数argc和argv等;

◇调用main()函数,执行应用程式,能够应用库函数;

◇用main()函数的返回值作参数调用exit()。

_rt_entry并不是C函数,他是用ARM C库编程的起始点。_rt_entry不能用C语言宴现,因为这时候堆栈还没有建立,堆栈由_ rt_stackheap_init()来建立。

B原文描述:

http://patonwang.blog.163.com/blog/static/1228953120098299313621/

在ADS1.2中__main()作为c语言的入口函数,它主要做了以下工作:

1.把RO,RW从他们的加载域复制到他们的运行域中去(可以用在LINKER中设置RO=,RW=,来确定,也可以用scatter文件来定义)

2.初始化ZI域

3.跳到__rt_entry.

而库函数__rt_entry()会完成以下工作:

1.调用__rt_stackheap_init()设置stack和heap

2.调用__rt_lib_init()初始化相应的库函数,

3.调用main(),即是我们自己的应用程序了

4.调用exit()来处理main()函数的返回值

从上面我们可以看到__main()运行时库主要是初始化一些东西,然后跳到用户的main()中去,所以我们不用__main()函数初始化运行环境的时候,要自己编写相应的代码来完成相应的内容

C原文描述:

http://blog.chinaunix.net/u1/38994/showart_303536.html

__rt_lib_init

   在ADS1.2的环境中,如果在C入口没有调用编译器的链接库(__main),那么在C程序一开始要调用该函数以初始化运行时的函数库,以保证对ADS提供的某些库函数能够正常调用。从这个函数开始,我们已经在C语言环境下了。

继续阅读