天天看點

關于_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語言環境下了。

繼續閱讀