execv动态链接 linux
2012-09-08 11:16:41 jeffreyst 阅读数 2010
  1. 函数原型

int execv(const char *progname, char *const argv[]);   //#include <unistd.h>

 

  

     2. 用法介绍

         execv会停止执行当前的进程,并且以progname应用进程替换被停止执行的进程,进程ID没有改变。

progname: 被执行的应用程序。

argv: 传递给应用程序的参数列表, 注意,这个数组的第一个参数应该是应用程序名字本身,并且最后一个参数应该为NULL,不参将多个参数合并为一个参数放入数组。

 

      3. 返回值

          如果应用程序正常执行完毕,那么execv是永远不会返回的;当execv在调用进程中返回时,那么这个应用程序应该出错了(可能是程序本身没找到,权限不够...), 此时它的返回值应该是-1,具体的错误代码可以通过全局变量errno查看,还可以通过stderr得到具体的错误描述字符串:

 

       4. 示例

  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <unistd.h>  
  4. #include <errno.h>  
  5.   
  6.   
  7. main(void)  
  8. {  
  9.   pid_t pid = fork();  
  10.      
  11.   if( pid == 0 ) // this is the child process  
  12.   {  
  13.      execv("/bin/ls", NULL);  
  14.   
  15.      // the program should not reach here, or it means error occurs during execute the ls command.  
  16.      printf("command ls is not found, error code: %d(%s)", errno, strerror(errno);  
  17.   }  
  18. }  

 

 

  

int execl(const char *path, const char *arg, ...);
int execlp(const char *
file, const char *arg, ...);
int execle(const char *
path, const char *arg,
..., char * const
envp[]);
int execv(const char *
path, char *const argv[]);
int execvp(const char *
file, char *const argv[]);


2018-02-01 14:01:11 weixin_33806509 阅读数 3

1, 编译,使用-shared和-fpic 生成动态链接库
库源码:test.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static void printline(int len)
{

    int i;

    for(i = 0;i<len;i++)
    {
        printf("=");        
    }
    printf("\n");
}

void print(char * s)
{   
    int len = 0;
    int  i = 0;
    if(!s || *s == '\0')
    {
        return ;
    }

    len = strlen(s);
    printline(len);
    printf("%s\n",s);
    printline(len);
}

头文件:test.h

#ifndef __TEST_H__
#define __TEST_H__

void print(char * s);

#endif

编译库文件:

gcc test.c -shared -fpic -o libtest.so

2.编译测试代码

测试代码:main.c

#include "test.h"

int main()
{
    char teststr[] = "hello world";

    print(teststr);

    return 0;

}

编译测试代码

    gcc  main.c -L./ -ltest -o main

3.运行

当运行时,发现找不到库文件
./main: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

这个是linux库文件搜索路径的问题,有两个解决方式

  1. 在/etc/ld.so.conf.d/下编写配置文件,指定库路径,然后使用ldconfig去刷新缓存
  2. 在执行前设置环境变量 LD_LIBRARY_PATH,指定当前的路径,再去执行时,则现在本地去搜索
root@GFD:~/workspace/so_test# export LD_LIBRARY_PATH=./
root@GFD:~/workspace/so_test# ./main
===========
hello world
===========

转载于:https://blog.51cto.com/6306331/2067710

2017-04-29 14:26:00 weixin_34130389 阅读数 23

问题

曾经不止一次遇到过这样的情况:从机器A拷贝一个二进制文件到另一台机器B,两台机器的操作系统版本一样,可是在机器A能正常运行,在机器B却提示错误。最常见的就是提示动态链接库找不到,如:

./test: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

其实就是说,找不到动态链接库libstdc++.so.6

最近又有一次碰到类似的问题,所以顺便把动态链接库的基本原理了解了一遍。

静态链接

静态链接库,在Linux下文件名后缀为.a,如libstdc++.a。在编译链接时直接将目标代码加入可执行程序。

动态链接

动态链接库,在Linux下是.so文件,在编译链接时只需要记录需要链接的号,运行程序时才会进行真正的“链接”,所以称为“动态链接”。如果同一台机器上有多个服务使用同一个动态链接库,则只需要加载一份到内存中共享。因此,动态链接库也称共享库

命名规则

动态链接库与应用程序之间的真正链接是在应用程序运行时,因此很容易出现开发环境和运行环境的动态链接库不兼容或缺失的情况。

Linux通过规定动态链接库的版本命名规则来管理兼容性问题。

Linux规定动态链接库的文件名规则比如如下:

libname.so.x.y.z

  • lib:统一前缀。
  • so:统一后缀。
  • name:库名,如libstdc++.so.6.0.21的name就是stdc++。
  • x主版本号。表示库有重大升级,不同主版本号的库之间是不兼容的。如libstdc++.so.6.0.21的主版本号是6。
  • y次版本号。表示库的增量升级,如增加一些新的接口。在主版本号相同的情况下,高的次版本号向后兼容低的次版本号。如libstdc++.so.6.0.21的次版本号是0。
  • z发布版本号。表示库的优化、bugfix等。相同的主次版本号,不同的发布版本号的库之间完全兼容。如libstdc++.so.6.0.21的发布版本号是21。

另外,Linux下的一个动态链接库会有下面三个名字:

libstdc++.so -> libstdc++.so.6.0.21*
libstdc++.so.6 -> libstdc++.so.6.0.21*
libstdc++.so.6.0.21*
  • libstdc++.so:linker name,程序编译链接时如果依赖了共享库,链接器只认不带任何版本的共享库。如果存在多个同名(上面命名规则中的name)动态链接库,linker name会指向最新的一个。
  • libstdc++.so.6:SO_NAME, 程序运行时会按照这个名称去找真正的库文件。也就是说,ELF可执行文件中保存的动态库名就是SO_NAME。如果存在多个同一主版本号的动态链接库,SO_NAME会指向最新的一个。
  • libstdc++.so.6.0.21:real name,这是动态链接库的真正名称。

相关路径

  • /lib:最关键和基础的动态链接库。
  • /usr/lib:关键的动态链接库。
  • /usr/local/lib:第三方动态链接库。
  • 由/etc/ld.so.conf配置文件指定的目录。

ldconfig

动态链接器不可能在每次查找动态链接库都去遍历所有动态链接库的目录,这样速度太慢了。因此,在系统启动时会通过ldconfig为动态链接库生成SO_NAME/etc/ld.so.cache存放系统动态链接库的路径信息,加速动态链接库的查找。

程序启动查找动态链接库的路径顺序如下:

  1. LD_LIBRARY_PATH指定的路径。
  2. 由路径缓存文件/etc/ld.so.cache指定的路径。
  3. 默认共享库目录,先/usr/lib,然后/lib

注意,安装动态链接库后,需要重启系统或运行ldconfig生成SO_NAME和刷新/etc/ld.so.cache文件。

ldd

通过ldd elf_file可以查看ELF文件依赖哪些动态链接库,如

$ ldd test
linux-vdso.so.1 =>  (0x00007ffc89b46000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6e20ec7000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f6e20bc1000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f6e209ab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6e205e3000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6e211cb000)
  • linux-vdso.so.1是内核提供的一个动态链接库,所以这里只有一个内存地址。
  • /lib64/ld-linux-x86-64.so.2是一个动态链接库的绝对路径。
2015-09-29 20:36:19 shujianhenu 阅读数 476

在程序中总会用到各式各样的库,有两种使用方式:静态链接库和动态链接库,在windows下分别对应.lib文件和.dll文件,使用静态库时需要包含对应的头文件并引用lib文件,使用动态库则需要手动通过函数加载dll中的函数。
linux下使用方法则有所不同,linux下.a文件.so文件分别对应静态和动态链接库。

静态链接库

ar rcs libmylib.a mylib.o 生成.a静态库
gcc -o hello main.c -L. -lmylib 生成可执行文件hello;gcc会在mylib之前自动添加lib,即找文件libmylib.a
./hello 执行

可以发现即使删除libmylib.a文件,hello也可以执行。

动态链接库

gcc -fPIC -shared -o libmylib.so mylib.c 生成.so动态库
gcc -o hello main.c -L. -lmylib 生成可执行文件hello;gcc会在mylib之前自动添加lib,即找文件libmylib.so
./hello 执行
./hello: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory

可以发现此时hello执行出错,gcc编译时优先链接动态库文件,但程序执行时并没有找到动态链接库
在linux下程序搜索动态链接库是按照如下顺序的:

  • ELF可执行文件中动态段中DT_RPATH所指定的路径,编译时gcc加入链接参数“-Wl,-rpath”指定该动态库搜索路径
  • 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
  • 配置文档/etc/ld.so.conf中指定的动态库搜索路径
  • 默认的动态库搜索路径/lib
  • 默认的动态库搜索路径/usr/lib

按照第一种方法解决,

gcc -o hello main.c -L. -lmylib -Wl,-rpath=. 参数-Wl,-rpath=. 指定当前路径为动态库搜索路径
./hello 可执行

按照第二种方法解决,

export LD_LIBRARY_PATH=.
./hello 可执行

使用命令 readelf -d hello可见其搜索路径 Library rpath: [.]

Dynamic section at offset 0x7b0 contains 22 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libmyhello.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [.]
 0x000000000000000c (INIT)               0x400490
 0x000000000000000d (FINI)               0x4006b8
 0x000000006ffffef5 (GNU_HASH)           0x400260

第三种方法,

把当前路径写入/etc/ld.so.conf,并执行ldconfig重新加载

第四种方法,

把libmylib.so文件拷贝到/lib中

第四种方法,

把libmylib.so文件拷贝到/lib中

第五种方法,

把libmylib.so文件拷贝到/usr/lib中

在实际使用中第一和第二种方法最经常被采纳,但是使用变量LD_LIBRARY_PATH时要注意,一旦LD_LIBRARY_PATH变量被设置之后,该变量生效范围内的所有程序执行时都会先查找该变量所指定的搜索目录,这样势必会造成一些浪费。

参考http://www.eefocus.com/book/09-04/716171276059628.html
http://blog.chinaunix.net/uid-23592843-id-223539.html

2011-10-10 22:55:07 calvin_zcx 阅读数 543
————————————————————————————————————

1.什么是库
windows平台和linux平台下都大量存在着库。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
由于windowslinux的本质不同,因此二者库的二进制是不兼容的。
本文仅限于介绍linux下的库。
2.库的种类
linux下的库有两种:静态库和共享库(动态库)。
二者的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
3.库存在的意义
库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。
现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
4.库文件是如何产生的在linux
静态库的后缀是.a,它的产生分两步
Step 1.
由源文件编译生成一堆.o每个.o里都包含这个编译单元的符号表
Step 2.ar命令将很多.o转换成.a,成文静态库
动态库的后缀是.so,它由gcc加特定参数编译产生。
例如:
$ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *.
5.库文件是如何命名的,有没有什么规范

linux下,库文件一般放在/usr/lib /lib下,
静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
动态库的名字一般为libxxxx.so.major.minorxxxx是该lib的名称,major是主版本号, minor是副版本号
6.如何知道一个可执行程序依赖哪些库
ldd
命令可以查看一个可执行程序依赖的共享库,
例如# ldd /bin/lnlibc.so.6
=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
=> /lib/ld- linux.so.2 (0×40000000)
可以看到ln命令依赖于libc库和ld-linux

7.可执行程序在执行的时候如何定位共享库文件
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径
此时就需要系统动态载入器(dynamic linker/loader)
对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目录找到库文件后将其载入内存

8.在新安装一个库之后如何让系统能够找到他
如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下
1.
编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
2.
运行ldconfig,该命令会重建/etc/ld.so.cache文件

我 们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静 态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。 
1步:编辑得到举例的程序--hello.hhello.cmain.c 

hello.h(
见程序1)为该函数库的头文件。
hello.c(
见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"Hello XXX!"
main.c(
见程序3)为测试库文件的主程序,在主程序中调用了公用函数hello 
程序
1: hello.h
#ifndef HELLO_H
#define HELLO_H

void hello(const char *name);

#endif //HELLO_H
程序
2: hello.c
#include 

void hello(const char *name)
{
  printf("Hello %s!/n", name);
}
  
程序
3: main.c
#include "hello.h"

int main()
{
  hello("everyone");
  return 0;
}
2步:将hello.c编译成.o文件; 

无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。 
在系统提示符下键入以下命令得到hello.o文件。
 
# gcc -c hello.c 

(
1:本文不介绍各命令使用和其参数功能,若希望详细了解它们,请参考其他文档。

(
2:首字符"#"是系统提示符,不需要键入,下文相同。

我们运行ls命令看看是否生存了hello.o文件。
 
# ls 
hello.c hello.h hello.o main.c 

(
3:首字符不是"#"为系统运行结果,下文相同。

ls命令结果中,我们看到了hello.o文件,本步操作完成。
 
下面我们先来看看如何创建静态库,以及使用它。
 
3步:由.o文件创建静态库;
 
静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。
 
在系统提示符下键入以下命令将创建静态库文件libmyhello.a
 
# ar cr libmyhello.a hello.o 

我们同样运行ls命令查看结果:
 
# ls 
hello.c hello.h hello.o libmyhello.a main.c 

ls
命令结果中有libmyhello.a
 
4步:在程序中使用静态库;
 
静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。 

在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。 
# gcc -o hello main.c 
-L. -lmyhello 

# ./hello 
Hello everyone! 

我们删除静态库文件试试公用函数hello是否真的连接到目标文件 hello中了。 
# rm libmyhello.a 
rm: remove regular file `libmyhello.a'? y 
# ./hello 
Hello everyone! 

程序照常运行,静态库中的公用函数已经连接到目标文件中了。
 
我们继续看看如何在Linux中创建动态库。我们还是从.o文件开始。
 
5步:由.o文件创建动态库文件;
 
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。用gcc来创建动态库。
 
在系统提示符下键入以下命令得到动态库文件libmyhello.so
 
# gcc -shared -fPCI -o libmyhello.so hello.o 

我们照样使用ls命令看看动态库文件是否生成。
 
# ls 
hello.c hello.h hello.o libmyhello.so main.c 

6步:在程序中使用动态库;
 
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。
 
# gcc -o hello main.c 
-L. -lmyhello 

# ./hello 
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。我们将文件libmyhello.so复制到目录/usr/lib中,再试试。 
# mv libmyhello.so /usr/lib 
# ./hello 
./hello: error while loading shared libraries: /usr/lib/libhello.so: cannot restore segment prot after reloc: Permission denied
由于SELinux引起,

# chcon -t texrel_shlib_t /usr/lib/libhello.so
# ./hello
Hello everyone! 

成功了。这也进一步说明了动态库在程序运行时是需要的。 
我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,来试试看。
 
先删除 .c.h外的 所有文件,恢复成我们刚刚编辑完举例程序状态。
 
# rm -f hello hello.o /usr/lib/libmyhello.so 
# ls 
hello.c hello.h main.c 

在来创建静态库文件libmyhello.a和动态库文件libmyhello.so
 
# gcc -c hello.c 
# ar cr libmyhello.a hello.o 
# gcc -shared -fPCI -o libmyhello.so hello.o 
# ls 
hello.c hello.h hello.o libmyhello.a libmyhello.so main.c 

通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.so都已经生成,并都在当前目录中。然后,我们运行gcc命令来使用函数库myhello生成目标文件hello,并运行程序 hello
 
# gcc -o hello main.c -L. -lmyhello 
# ./hello 
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

从程序hello运行的结果中很容易知道,当静态库和动态库同名时, gcc命令将优先使用动态库。 

基本概念 
库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。
 
例如:libhello.so libhello.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如:libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。
 
ln -s libhello.so.1.0 libhello.so.1 
ln -s libhello.so.1 libhello.so 

1
、使用库 
当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然 而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。 现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a 一个动态库libhello.so,一个头文件hello.h,头文件中提供sayhello()这个函数/* hello.h */ void sayhello(); 另外还有一些说明文档。
 
这一个典型的程序开发包结构 与动态库连接 linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的sayhello()函数
 
/*testlib.c*/ 
#include  
#include  
int main() 

   sayhello(); 
   return 0; 

使用如下命令进行编译
 $gcc -c testlib.c -o testlib.o 
用如下命令连接:
 $gcc testlib.o -lhello -o testlib 
连接时要注意,假设libhello.o libhello.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数 与与静态库连接麻烦一些,主要是参数问题。还是上面的例子:
 
$gcc testlib.o -o testlib -WI,-Bstatic -lhello 
注:这个特别的"-WI-Bstatic"参数,实际上是传给了连接器ld。指示它与静态库连接,如果系统中只有静态库当然就不需要这个参数了。 如果要和多个库相连接,而每个库的连接方式不一样,比如上面的程序既要和libhello进行静态连接,又要和libbye进行动态连接,其命令应为:
 
$gcc testlib.o -o testlib 
-WI,-Bstatic -lhello -WI,-Bdynamic
 -lbye 
  
2、动态库的路径问题 为了让执行程序顺利找到动态库,有三种方法:
 
(1)
把库拷贝到/usr/lib/lib目录下。
 
(2)LD_LIBRARY_PATH环境变量中加上库所在路径。
 
例如动态库libhello.so/home/ting/lib目录下,以bash为例,使用命令: 

$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ting/lib(注:PWD)
(3) 
修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见。 
3、查看库中的符号 
有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种:
 
一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;
 
一种是库中定义的函数,用T表示,这是最常见的;
 
另外一种是所谓的 符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。
 
例如,假设开发者希望知道上文提到的hello库中是否定义了
 printf(): 
$nm libhello.so |grep printf U 
其中printf U表示符号printf被引用,但是并没有在函数内定义,由此可以推断,要正常使用hello库,必须有其它库支持,再使用ldd命令查看hello依赖于哪些库:
 
$ldd hello libc.so.6=>/lib/libc.so.6(0x400la000) /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000) 
从上面的结果可以继续查看printf最终在哪里被定义,有兴趣可以
go on 
4、生成库 

第一步要把源代码编绎成目标代码。 
以下面的代码为例,生成上面用到的hello库:
 
/* hello.c */ 
#include   
void sayhello() 

  printf("hello,world "); 

gcc编绎该文件,在编绎时可以使用任何全法的编绎参数,例如-g加入调试代码等:
 gcc -c hello.c -o hello.o 
(1)
连接成静态库 连接成静态库使用ar命令,其实ararchive的意思
 
$ar cqs libhello.a hello.o 
(2)
连接成动态库 生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:
 
$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o 
另外再建立两个符号连接:
 
$ln -s libhello.so.1.0 libhello.so.1 
$ln -s libhello.so.1 libhello.so 
这样一个libhello的动态连接库就生成了。最重要的是传gcc -shared 参数使其生成是动态库而不是普通执行程序。 -Wl 表示后面的参数也就是-soname,libhello.so.1直接传给连接器ld进行处理。实际上,每一个库都有一个soname,当连接器发现它正在查找的程序库中有这样一个名称,连接器便会将soname嵌入连结中的二进制文件内,而不是它正在运行的实际文件名,在程序执行期间,程序会查找拥有 soname名字的文件,而不是库的文件名,换句话说,soname是库的区分标志。 这样做的目的主要是允许系统中多个版本的库文件共存,习惯上在命名库文件的时候通常与soname相同 libxxxx.so.major.minor 其中,xxxx是库的名字,major是主版本号,minor 是次版本号

linux 动态链接

阅读数 110

没有更多推荐了,返回首页