不得不说的LinuxC下,多模块的编译和链接(原理)

不得不说的LinuxC下,多模块的编译和链接

  1. C程序的编译和运行
  2. 多模块编译
  3. 静态库和共享库

C程序的编译和运行(编译原理)

C程序的编译和运行过程(编译器自动完成的过程):

编译到链接的整个过程:
1:预处理
    gcc -E -o example.i example.c
    将声明在头文件中的内容加到生成的.i文本文件中去 
    -E只是进行预处理阶段,不会进行编译
    执行步骤:
        1:将头文件的内容包含到.c的源文件中
        2:删除掉.c源文件中的注释
        3:进行宏替换
        4:进行条件编译过程

2:编译
    gcc -S -o example.s example.i
    将.i的文本文件编译成汇编语言后生成.s文本文件
    -S只是进行编译阶段,不会进入下一阶段;

3:汇编
    gcc -o example.o -c example.s
    将.s文件内容汇编成机器语言后生成.o二进制文件

4:链接
    gcc -o example example.o
    将.o文件链接生成可执行二进制文件

    .o的链接文件要比可执行文件要小很多;

5:生成可执行文件

注意:
在编译的整个过程中,编译的内容,在中间都会放到对应的缓存中去,等生成可执行文件之后,再去整体删除掉

反汇编过程(反汇编二进制文件)

使用objdump可以进行对二进制文件进行反汇编;
    objdump -xd example.o

这里写图片描述

编译环境:

        将C的源程序转换成特定平台的可执行程序

运行环境:

        运行可执行程序的环境

多模块的编译(思想更重要)

1:概念:

多数软件被分割成多个源文件,每个文件称为一个模块

2:多模块的建立:

首先将一个大型程序根据其功能合理的划分为若干个小的源程序,每个小的源程序都是以程序文件(.c)形式保存在磁盘上面
这些若干个源文件可以进行单独编译,生成.o目标文件
最后将这个.o目标文件链接生成一个大的可执行程序

3:多模块软件设计思路
将整个大问题化成各个小模块,再利用模块之间的联系来完整整个流程

4:带来什么样子的优缺点:

优点:
    1:较小程序文件更容易管理和维护,也就是说编辑,编译,测试和调试较小的程序文件所花的时间更少了
    2:只需要修改经过修改的源文件,而不是去编译整个软件系统

缺点:
    必须知道构成整个系统的所有文件,这些文件的相互依赖性(即那些文件需要重编译)以及最终生成的可执行系统后哪些文件被修改过;
    需要更总所有文件修改的时间
    必须键入很长的命令行来编译

静态库和共享库

1:库的概念

    函数库是由系统建立的具有一定功能的函数的集合,库中存放函数的名称和对应的目标代码,以及链接过程中需要的重定位信息;
    Linux中标准的C函数库防止在/usr/lib下,以文件形式存放
    用户可以根据自己的需要建立自己的函数库函数
    函数库分为静态库(.a)和共享库(.so)

库函数:
存放在函数库中的函数,库函数具有明确的功能,入口调用参数,和返回数值
库函数的源代码一般都是不可见的,但在对应的头文件中你可以看到它对外的一些接口

2:静态库的创建与使用
a:概念:

静态库就是以一些.o目标文件的集合,以.a结尾

静态库在程序链接的时候使用,连接器会将程序中使用到的一些函数代码从静态库的文件中拷贝出来放到文件中去,一旦链接成功,在执行程序的时候就不需要静态库了

由于每个使用静态库的应用程序都需要拷贝所有函数的代码,所以静态库生成的可执行文件都是相对比较大的

b:创建

    ar rcs lib库文件名字.a 目标文件1 目标文件2 ...目标文件n
    语法:
        r:代表将.o的目标文件添加如静态库中
        c:表示创建静态库  create
        s:表示产生索引    search
    注意:
    静态库文件创建的时候尽量去使用libxxxx.a
    目标文件就是.o文件:

c:使用

在生成可执行文件的时候去链接(生成可执行文件之后,删除静态库文件,并不会对可执行文件产生任何影响):

gcc -o 可执行文件  调用者的目标文件 -Ldir -l库文件名字
或者gcc -o 可执行文件 -ldir 调用这的C源文件 -Ldir -l库文件名字

参数:-Ldir:选项表示将指定的库文件所在的目录加入到库搜索路径中,默认的库路径在usr/lib文件下面
-lname:(前缀lib不要加上)表示库搜索路径下的libname.a或者libname.so文件,这也是为什么库文件使用lib开头的原因之一,如果你的库文件不是以lib开头的(hello.a),那么就不能使用-l选项,而是直接如hello.a,即将原来的-lhello 写成hello.a也是可以进行替换的
-l是链接器选项,必须放在被编译和链接的文件的后面

如:
    src/下有mymath_test.c
    include/下有mymath.h
    staticlib/下有libmymath.a
    gcc -o bin/my_math -Iinclude src/mymath_test.c -Lstaticlib -lmymath
    注意了:
    -l后面的名字是去掉了libmymath去掉了lib之后的名字mymath
    静态库函数的链接是需要去链接头文件的

    gcc -o  bin/mymath2 -ldir obj/mymath_test.o -Lstaticlib -lmymath 

3:动态库的创建与使用(.so文件)

1:概念

共享库也叫做动态链接库,在linux中是以so(share object)为后缀,在windows中主要是以.dll为后缀
共享库在程序的链接的时候并不像静态库那样会拷贝使用函数的代码,而只是**作一些标记**,在程序开始启动的时候(实际是加载程序时候)运行的时候,夹在所需要的函数
可执行文件在运行的时候,还是需要将共享库加载进来,所以需要共享库支持
共享库链接出来的程序是比静态库链接出来的要很多
共享库文件在删除之后就会提示库文件找不到的错误

2:共享库的创建

gcc -shared -fPCI -o lib库文件名字.so 目标文件...;

-shared表示使用共享库
-fpci或者-fPCI表明创建产生独立目标代码,具体取决于平台

3:共享库的使用:

gcc -o 可执行文件 调用这的目标文件 -Ldir -l库文件名字
gcc -o 可执行文件 -ldir 调用者的C源程序 -Ldir -l库文件名字


注意:
    在运行共享库链接生成的可执行文件的时候,很容易出现共享库找不到的问题,这个时候需要配置共享库的路径

运行可执行文件的出错解决方案:
1:将共享库拷贝到/usr/lib下面(root)
2:export LD_LIBRARY_PATH=库文件目录(尽限于当前终端的临时环境变量)

最后谢谢大家的访问:欢迎大家持续访问,有错误的地方希望各位看客能够及时指出,谢谢

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值