静态链接和动态链接

1.实例代码

//add.c#include"tmath.h"

int tadd(int x,int y)
{
    return x+y;
}

int tsub(int x,int y)
{
    return x-y;
}
//mul.c
#include"tmath.h"

int tmul(int x, int y)
{
    return x*y;
}

int tdiv(int x,int y)
{
    return x/y;
}
//main.c
#include<stdio.h>
#include"tmath.h"

int main(void)
{

    int a = 8;
    int b = 2;

    printf("%d + %d = %d\n",a,b,tadd(a,b));
    printf("%d - %d = %d\n",a,b,tsub(a,b));
    printf("%d * %d = %d\n",a,b,tmul(a,b));
    printf("%d / %d = %d\n",a,b,tdiv(a,b));

    return 0;
}

 

nm 二进制文件 ./a.out     main.o

            [email protected]:~/unixc/day02$ nm add.o
            0000000000000000 T tadd
            0000000000000014 T tsub
            [email protected]:~/unixc/day02$ nm mul.o
            0000000000000013 T tdiv
            0000000000000000 T tmul
            [email protected]:~/unixc/day02$ nm main.o
            0000000000000000 T main
                             U printf
                             U tadd
                             U tdiv
                             U tmul
                             U tsubT: 代表该文件中已经有这个函数的实现代码U: 代表该文件中使用了这个函数,但是没有这个函数代码的实现有的函数在编译的时候发生了链接,这个链接称为静态链接有的函数在代码加载到内存执行的时候,才发生链接,这个链接成为动态链接,也可以称为延迟绑定。printf()在a.out中认为U

2.程序已经为目标文件的时候,需要和运行时文件链接,什么是运行时文件

gcc *.o -v        查看链接的整个过程
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o
-L/usr/lib/gcc/x86_64-linux-gnu/5
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib -L/lib/x86_64-linux-gnu
-L/lib/../lib
-L/usr/lib/x86_64-linux-gnu
-L/usr/lib/../lib
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../..
add.o main.o mul.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o

crt1.o   crti.o crtend.o ...
程序的入口是_start
而C程序的入口是main函数
C程序是函数构成,main函数和其他函数一样,理清一个程序就需要清理函数之间的调用和被调用的关系
特定的操作系统有特定的框架和_start入口

2. 静态库的制作和使用

  1.生成obj文件

  gcc -c add.c mul.c

  [email protected]:~/unixc/day02$ gcc -c add.c mul.c
  [email protected]:~/unixc/day02$ ls
  add.c  add.o  mul.c  mul.o

  2.生成静态库文件

  ar -r libtmath.a add.o mul.o        //libtmath.a   库名为tmath,在前面加个lib,以.a为后缀

  [email protected]:~/unixc/day02$ ar -r libtmath.a *.o
  ar: creating libtmath.a
  [email protected]:~/unixc/day02$ ls
  add.c  add.o  libtmath.a  mul.c  mul.o

  3.将目标文件和库文件链接成可执行文件

  gcc main.c -L. -ltmath

  -L  指示库文件所在的文件路徑

  -l  指示库文件
  -I  指定头文件的位置,Include

  [email protected]:~/unixc/day02$ gcc  main.c -L. -lpmath
  [email protected]:~/unixc/day02$ ls
  add.c  add.o  a.out  libpmath.a  main.c  mul.c  mul.o  .h
  [email protected]:~/unixc/day02$ a.out
  8 + 2 = 10
  8 - 2 = 6
  8 * 2 = 16
  8 / 2 = 4

3.动态库的制定和使用

  1.gcc -fPIC -c *.c                        
                //这样生成的是动态链接的目标文件,和静态链接的目标文件不一样

  2.gcc -shared -o libptmath.so *.o    //库名为ptmath

  3.gcc main.c -Lsrc -lptmath -Isrc

    在这一步之前先要把动态库文件加入到搜索路徑

  4.如何查看可执行文件依赖哪些动态库文件?
          ldd 可执行程序
       [email protected]:~/unixc$ ldd a.out
       linux-vdso.so.1 =>  (0x00007ffeb9fc1000)
       libptmath.so => not found
       libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f61ada8c000)
            /lib64/ld-linux-x86-64.so.2 (0x000055611599d000)

    [email protected]:~/unixc$ echo $LD_LIBRARY_PATH
    [email protected]:~/unixc$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:src
    [email protected]:~/unixc$ echo $LD_LIBRARY_PATH
    :src
    [email protected]:~/unixc$ a.out
    8 + 2 = 10
    8 - 2 = 6
    8 * 2 = 16
    8 / 2 = 4

    [email protected]:~/unixc$ ldd a.out
       linux-vdso.so.1 =>  (0x00007fffcb7fe000)
       libptmath.so => src/libptmath.so (0x00007f9657d02000)
       libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9657920000)
       /lib64/ld-linux-x86-64.so.2 (0x000055628211d000

    另外一种方法是sudo mv libptmath.so /lib

    

  

  

时间: 2024-12-30 02:59:27

静态链接和动态链接的相关文章

linux 静态链接和动态链接

链接 一个可执行目标文件的生成需要经过预编译(g++ -E).编译(g++ -S).汇编(g++ -c).链接四个步骤.链接是将多个可重定位目标文件合并到一个目标文件的过程.链接由链接器完成,链接器重要完成两个任务: 1.符号(符号表由汇编器构造)解析.也就是将符号引用和符号定义关联起来.其中符号定义和符号引用可能不在同一个目标文件中.而且链接器对多重定义的全局符号的解析有一定的规则:不允许有多个同名强符号(函数和初始化了的全局变量).如果有一个强符号和多个弱符号同名选择强符号.如果有多个弱符号

静态链接与动态链接的区别(转载)

1.转载:http://www.cnblogs.com/kex1n/archive/2011/09/06/2168435.html 动态链接库.静态库.import库区别 动态链接库(Dynamic Linked Library):Windows为应用程序提供了丰富的函数调用,这些函数调用都包含在动态链接库中.其中有3个最重要的DLL,Kernel32.dll,它包含用于管理内存.进程和线程的各个函数: User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数:GD

CodeBlocks静态链接与动态链接设置

静态库和动态库的区别 1.静态库 之所以称之为"静态库",是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中.因此对应的链接方式称为静态链接. 从本质上来说,一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,静态库与汇编生成的目标文件(.o/.obj)一起链接为可执行文件. 静态库(后缀为.a/.lib)和.o文件格式相似.即很多目标文件经过压缩打包后形成的一个文件 静态库特点总结: 1. 静态库对函数库的链接是放在编译时期完成的 2.

C的日记-静态链接和动态链接

[静态链接和动态链接]    静态链接:源程序编译之后,如果想要执行,先对目标文件进行链接,链接完成后如果执行了,就把链接好的都装载进内存    缺点:        <1>如果一个目标文件被重复使用,每次都会把目标文件载入内存,造成浪费:        <2>如果相对某个目标文件进行更新,需要先把这个目标文件重新编译+链接,然后重新载入内存.    动态链接:在程序开始运行后(装载到内存)才开始把目标文件依次加载到内存然后编译成可执行文件    优点:        <1&

程序的静态链接,动态链接和装载

一.程序编译链接的整体流程 通常我们使用gcc来生成可执行程序,命令为:gcc hello.c,默认生成可执行文件a.out 其实编译(包括链接)的命令:gcc hello.c 可分解为如下4个大的步骤: 预处理(Preprocessing) 编译(Compilation) 汇编(Assembly) 链接(Linking) gcc compilation 1.       预处理(Preproceessing) 预处理的过程主要处理包括以下过程: 将所有的#define删除,并且展开所有的宏定义

学习总结:静态链接和动态链接

链接可分为静态链接和动态链接 静态链接:对函数库的链接是放在编译时期完成的是静态链接 生成静态链接库的步骤: (1)先将源文件编译成 .o 文件: (源文件可从上一篇查看) g++ -c printA.cpp g++ -c printB.cpp 生成的文件为 printA.o printB.o ,-c 的编译选项,表示只执行到编译,输出目标文件. 无论是静态库文件还是动态库文件,都是由 .o 文件创建的 (2)由 .o 文件创建静态库(.a 文件),执行命令: ar cr libmyprint.

静态和动态链接

引言即使是最简单的HelloWorld的程序,它也要依赖于别人已经写好的成熟的软件库,这就是引出了一个问题,我们写的代码怎么和别人写的库集成在一起,也就是链接所要解决的问题. 首先看HelloWorld这个例子:[cpp] view plain copy  1. // main.c    2.   1 #include <stdio.h>    3.   2    4.   3 int main(int argc, char** argv)    5.   4 {    6.   5     

[CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口

1 平台 1.1 硬件 Table 1. 硬件(lscpu) Architecture: i686(Intel 80386) Byte Order: Little Endian 1.2 操作系统 Table 2. 操作系统类型 操作系统(cat /proc/version) 位数(uname -a) Linux version 3.2.0-4-686-pae i686(32bit) 1.3 编译器 Table 3. 编译器信息 编译器(gcc -v) gcc (Debian 4.7.2-5) 4

动态链接详解

动态链接 动态链接的诞生: 动态链接产生最主要的原因就是静态链接空间浪费过于巨大,更重要的是现阶段各种软件都是模块化开发,不同模块都是由不同厂商开发的,一旦一个模块发生改变,整个软件就需要重新编译(静态链接的情况下). 动态链接主要思想: 把链接这个过程推迟到了运行时再运行,这就是动态链接(Dynamic Linking)的基本思想. 动态链接的好处: 1.动态链接将共享对象放置在内存中,不仅仅节省内存,它还可以减少物理页面的换进换出,也可以提高CPU缓存的命中率,因为不同进程间的数据与指令都集