首页 > 其他分享 >C语言运行库及glibc介绍

C语言运行库及glibc介绍

时间:2023-10-29 16:44:55浏览次数:40  
标签:运行库 函数 libc glibc C语言 Linux

C语言运行库

任何一个C程序,它的背后都有一套庞大的代码来进行支撑,以使得该程序能够正常运行。这套代码至少包括入口函数,及其所依赖的函数所构成的函数集合。当然,它还理应包括各种标准库函数的实现。

这样的一个代码集合称之为运行时库(Runtime Library)。而C语言的运行库,即被称为C运行库(CRT)。

一个C语言运行库大致包含了如下功能:

  • 启动与退出:包括入口函数及入口函数所依赖的其他函数等。
  • 标准库函数:山C语言标准规定的C语言标准库所拥有的函数实现
  • I/0:I/0功能的封装和实现,参见上一节中I/0初始化部分。
  • 堆:堆的封装和实现,参见上一节中堆初始化部分。
  • 语言实现:语言中一些特殊功能的实现。

C语言标准款

ANSIC的标准库由24个C头文件组成。与许多其他语言(如Java)的标准库不同,C语言的标准库非常轻量,它仅仅包含了数学函数、字符/字符串处理,I/O等基本方面,例如:

  • 标准输入输出(stdio.h)。
  • 文件操作(stdio.h)。
  • 字符操作(ctype.h)。
  • 字符串操作(string.h)。
  • 数学函数(math.h)。
  • 资源管理(stdlib.h)。
  • 格式转换(stdlib.h)。
  • 时间/日期(time.h)。
  • 断言(assert.h)。
  • 各种类型上的常数(limits.h float.h)。

除此之外,C语言标准库还有一些特殊的库,用于执行一些特殊的操作,例如:

  • 变长参数(stdarg.h)。
  • 非局部跳转(setjmp.h)。

glibc

历史

glibc即GNUCLibrary,是GNU旗下的C标准库。最初由1自由软件基金会FSF(FreeSoftware Foundation)发起开发,目的是为GNU操作系统开发一个C标准库。GNU操作系统的最初计划的内核是Hurd,一个微内核的构架系统。Hurd因为种种原因开发进展缓慢,而Linux因为它的实用性而逐渐风靡,最后取代Hurd成了GNNU操作系统的内核。于是glibc从最初开始支持Hurd到后来渐渐发展成同时支持Hurd和Linux,而且随着Linux的越来越流行,glibc也主要关注Linux下的开发,成为了Linux平台的C标准哇。

20世纪90年代初,在glibc成为Linux下的C运行库之前,Linux的开发者们因为开发的需要,从Linux内核代码里面分离出了一部分代码,形成了早期Linux下的C运行库。这个C运行库又被称为Linuxlibc。这个版本的C运行库被维护了很多年,从版本2一直开发到版本5。如果你去看早期版本的Linux,会发现/lib目录下面有1ibc.so.5这样的文件,这个文件就是第五个版本的Linux libc。1996年FSF发布了glibc2.0,这个版本的glibc开始支持诸多特性,比如它完全支持POSIX标准、国际化、IPv6、64-位委数据访问、多线程及改进了代码的可移植性。在此时Linux libc的开发者也认识到单独地维护一份Linux下专用的C运行库是没有必要的,于是Linux开始采用glibc作为默认的C运行库,并且将2.x版本的glibc看作是Linux libc的后继版本。于是我们可以看到,glibc在/lib目录下的.so文件为libc.so.6,即第六个libc版本,而且在各个Linux发行版中,glibc往往被称为libc6。glibc在Linux平台下占据了主导地位之后,它又被移植到了其他操作系统和其他硬件平台,诸如FreeBSD、NetBSD等,而且它支持数十种CPU及嵌入式平台。目前最新的glibc版本号是2.8(2008年4月)。

glibc的发布版本主要由两部分组成,一部分是头文件,比如stdio.h、stdlib.h等,它们往往位于/usr/include:另外一部分则是库的二进制文件部分二进制部分主要的就是C语言标准库,它有静态和动态两个版本。动态的标准库我们及在本书的前面章节中碰到过了,它位于/lib/libc.so.6;而静态标准库位于/usr/lib/libc.a。事实上glibc 除了C标准库之外,还有几个辅助程序运行的运行库,这几个文件可以称得上是真正的"运行库"。它们就是/usr/lib/crt1.o、/usr/lib/crti.o和/usr/lib/crtn.o。

启动文件

crt1.o里面包含的就是程序的入口函数_start,由它负责调用_libc_start_main初始化libc_start_main初始化
并且调用main函数进入真正的程序主体。实际上最初开始的时候它并不叫做crt1.o,而是叫做crt.o,包含了基本的启动、退出代码。由于当时有些链接器对链接时目标文件和库的顺序有依赖性,crt.o这个文件必须被放在链接器命令行中的所有输入文件中的第一个,为了强调这一点,crt.o被更名为crt0.o,表示它是链接时输入的第一个文件。

后来由于C++的出现和ELF文件的改进,出现了必须在main()函数之前执行的全局/静态对象构造和必须在main()函数之后执行的全局/静态对象析构。为了满足类似的需求,运行库在每个目标文件中引入两个与初始化相关的段".init"和".finit"。运行库会保证所有位于这两个段中的代码会先于/后于main()函数执行,所以用它们来实现全局构造和析构就是很自然的事情了。链接器在进行链接时,会把所有输入目标乐文件中的".init"和".finit"按照顺序收集起来,然后将它们合并成输出文件中的".init"和".finit"。但是这两个输出的段中所包含的指令还需要一些辅助的代码来帮助它们启动(比如计算GOT之类的),于是引入了两个目标文件分别用来帮助实现初始化函数的crti.o和crtn.o

与此同时,为了支持新的库和可执行文件格式,crt0.o也进行了升级级,变成了crt1.o。crt0.0和crt1.0之间的区别是crt0.0为原始的,不支持".init"和".finit"的启动代码,而crt1.0是改进过后,支持".init"和".finit"的版本。这一点我们从反汇编crt1.0可以看到,它向libc启动函数_libc_start_main()传递了两个函数指针"_libc_csu_init"和"_libc_csu_fini",这两个函数负责调用_init()和_finit()。

标签:运行库,函数,libc,glibc,C语言,Linux
From: https://www.cnblogs.com/lvzh/p/17795997.html

相关文章

  • c语言代码练习41
    问:实现在另一个数组中查找子字符串#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>#include<assert.h>#include<string.h>intmain(){char*p1="abcdefgdef";char*p2="def";char*ret=strstr(p1,p2);if(r......
  • C语言笔记1
    标识符命名规则:1>标识名只能由字母、数字、下划线组成;2>不能以数字开头(只能以字母或下划线开头);3>不能与系统关键字冲突;C语言语法规定:变量要定义在当前代码的最前面extern声明外部符号局部变量的作用域是变量所在的局部范围全局变量的作用域是整个工程    ......
  • C语言项目——简易版贪吃蛇
    使用工具CLion2022前期准备导入第三方库Easyx,详细教程=>在CLion、Dev-C++或Code::Blocks下面配置EasyX(2023-7-23更新)-CodeBus运行效果代码实现/**1.定义蛇结构*2.定义食物结构*3.游戏初始化*4.蛇行进*5.按键控制(方向,暂停)*6.吃食物*7.死亡判......
  • B站C语言第四课
    1,EOF -endoffile-文件结束标志-12,结构体//创建一个结构体类型structBook{ charname[20];//C语言程序设计 shortprince;//55};intmain(){ //利用结构体类型-创建一个该类型的结构体变量 structBookb1={"C语言程序设计",55}; structBook*pb=&b1; //利......
  • C语言二分查找法新手
    如果有一天我们想通过输入一个数去查找这个数在数组的下标。我们应该怎么去实现呢?首先我们肯定要创建一个数组组,我们知道数组的数组是从零开始的,首先呢,我们要了解二分查找法可以在百度里面查到。二分查找也称折半查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采......
  • C语言入门之数组之一维和二维----小白
    今天的介绍C语言数组的概念。数组的分类一维数组和多维数组。一维数组和二维数组,这是我们今天主要介绍的两种。一数组的概念。数组是一组相同类型元素的集合,我们在前面介绍了数据类型。他可以将多个相同类型的数据,放到一起。1.数组的数据不能为0,至少要放一个元素。或者对他进行初始......
  • c语言学习的第三天
    intmain()//{// externintg_val;// printf("g_val=%d\n",g_val);//extern--申明外部符号+// return0;//static修饰全局变量改变了变量的作用域,让静态的全局变量只能在自己所在的源文件内部使用,出了源文件就没法在使用了//static修饰函数改变了函数的链接属性 //st......
  • 【每日例题】蓝桥杯 C语言 凯撒加密
    凯撒加密题目题目描述给定一个单词,请使用凯撒密码将这个单词加密。凯撒密码是—种替换加密的技术,单词中的所有字母都在字母表上向后偏移3位后被替换成密文。即α变为d,b变为e,·,w变为z,Z变为a,g变为b,z变为c。输入描述输入格式:输入一行,包含一个单词,单词中只包含小写英文字母,单词中......
  • 【C语言Coding】第二十八天
    【例题1】2744.最大字符串配对数目-力扣(LeetCode)intmaximumNumberOfStringPairs(char**words,intwordsSize){intans=0;for(inti=0;i<wordsSize-1;i++){for(intj=i+1;j<wordsSize;j++){//字符串长度不相等intlen1=st......
  • C语言小案例
    1.从键盘输入3个实数,输出其中的最大值、最小值和平均值#include<stdio.h>intmain(){ doublenumber[3]; doublemax,min,average=0; inti; printf("Pleaseinputthreenumbers:"); for(i=0;i<3;i++){ scanf("%lf",&number[i]); } max=min=number[0]; ......