大家好,欢迎来到IT知识分享网。
来自 https://mp.weixin..com/s/qg1mFzMEYv7GDDM72H1DOQ 操作系统学习
1. 什么是CRT
crt是C run-time library的简称,称为C运行时库,它诞生于20世纪70年代,是程序在运行时所需要的库文件,属于C语言世界的概念。
C语言是由贝尔实验室的Dennis Ritchie从1969年到1973年开发的。1973年,Ken Thompson和Ritchie使用C语言重写了90%以上的UNIX系统函数,并且把其中最常用的部分独立出来,形成头文件和对应的LIBRARY,C运行时库就这样形成的。
随着C语言的流行,各个C编译器的生产商/个体/团体都遵循老的传统,在不同平台上都有相对应的Standard Library,但大部分实现都是与各个平台有关的。由于各个C编译器对C的支持和理解有很多分歧和微妙的差别,所以就有了ANSI C。ANSI C(主观意图上)详细的规定了C语言各个要素的具体含义和编译器实现要求,引进了新的函数声明方式,同时订立了StandardLibrary的标准形式。所以C运行时库由编译器生产商提供,至于由其他厂商/个人/团体提供的头文件和库函数,应当称为第三方C运行库(Third party C run-time libraries)。
Glibc(The GNU C Library)是GNU发布的libc库,即C运行库。Glibc是Linux系统中最底层的API,几乎其它任何运行库都会依赖于glibc。Glibc除了封装Linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。由于glibc囊括了几乎所有的UNIX通行的标准,可以想见其内容包罗万象。而就像其他的UNIX系统一样,其内含的档案群分散于系统的树状目录结构中,像一个支架一般撑起整个操作系统。在 GNU/Linux系统中,其C函数库发展史点出了GNU/Linux演进的几个重要里程碑,用glibc作为系统的C函数库,是GNU/Linux演进的一个重要里程碑。
Glibc有几个辅助程序运行的运行库,分别是/usr/lib/crt1.o、/usr/lib/crti.o和/usr/lib/crtn.o,这些目标文件的作用分别是启动、初始化和结束,它们通常会被自动链接到应用程序中。其中crt1.o中包含程序的入口函数_start以及两个未定义的符号__libc_start_main和main,由_start负责调用__libc_start_main初始化libc,然后调用应用程序中定义的main函数。由于类似于全局静态对象这样的代码需要在main函数之前执行,crti.o和crtn.o负责辅助启动这些代码。同样,在gcc中还有crtbegin.o和crtend.o这两个目标程序用于配合glibc来实现C++的全局构造和析构。
注:crt1.o是crt0.o的后续演进版本。
crt1.o中有非常重要的.init段、.fini段以及_start函数的入口。.init段和.fini段实际上是靠crti.o以及crtn.o来实现的,.init段是main函数之前的初始化工作代码, 比如全局变量的构造。.fini段则负责main函数之后的清理工作。
2. 举例说明
将源程序hello.c在Linux环境下按下面步骤编译运行。
编译为.o
gcc -c -o test.o test.c
链接:
ld -dynamic-linker/lib64/ld-linux-x86-64.so.2 -o hello /usr/lib64/crt1.o /usr/lib64/crti.o/usr/lib64/crtn.o hello.o -lc
运行:./hello
如果在链接时不选择crt1.o,则链接错,找不到_start。
如果在链接时不选择crti.o,则在函数__libc_csu_init中找不到_init,链接错。
如果在链接时不选择crtn.o ,链接通过,但执行时出现“Segmentation fault (core dumped)”错。
如果在链接时不选择hello.o ,出现错误,在crt1.o中函数_start找不到main。
如果在链接时不选择-lc,即c库,libc,链接错误,找不到__libc_start_main 等参数。
总结:在crt1.o中,包含有代码的运行入口_start,程序进入_start后进行初始化后会调用main,而main在crt1.o中未定义,它是在hello.o中定义,由此可见,main主函数的执行是由于_start的调用而引起的。crt1.o还有未定义符号__libc_start_main .__libc_csu_…等,这些符号是在libc中定义的。libc并不像其它目标文件一样链接到可执行文件main中,而是在运行时做动态链接的。
crt1.o的前身叫crt0.o, 它的作用是作为连接的首个模块。为了实现C++的全局构造和析构。改进crt0.o 为crt1.o。运行库引入了.init和.finit段,.init在main函数前运行,.finit在main函数后运行。链接器将所有目标文件的init段和finit段合并,并产生两个函数:_init()和_finit()。.init段,.finit段所需要的一些辅助代码,分别位于crti.o和crtn.o。
程序的执行始于crti.o,终止于crtn.o,中间才是真正程序的运行。简单描述如下:
_start函数调用__libc_start_main函数
__libc_start_main调用__libc_csu_init, main,__libc_csu_fini函数。
__libc_csu_init, 负责调用_init()
__libc_csu_fini, 负责调用_finit()
参考资料:
[1] https://www.cnblogs.com/iTeck/p/4159202.html
[2] https://blog.csdn.net/hejinjing_tom_com/article/details/
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/152168.html