CRT (C run-time library)简介

来自 https://mp.weixin.qq.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_mainmain,由_start负责调用__libc_start_main初始化libc,然后调用应用程序中定义的main函数。由于类似于全局静态对象这样的代码需要在main函数之前执行,crti.ocrtn.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/32325749

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lhw---9999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值