1. 程式人生 > >靜態鏈接和動態鏈接

靜態鏈接和動態鏈接

動態 sta class 實例 -i 操作 tdi -a usr

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 tsub
T: 代表該文件中已經有這個函數的實現代碼
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

    

  

  

靜態鏈接和動態鏈接