关于Linux静态库和动态库的分析

关于Linux静态库和动态库的分析

1.什么是库

在windows平台和linux平台下都大量存在着库。

本质上来说库是一种可运行代码的二进制形式。能够被操作系统加载内存运行。

因为windows和linux的本质不同,因此二者库的二进制是不兼容的。

本文仅限于介绍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.minor,xxxx是该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文件。

步:编辑得到举例的程序--hello.h、hello.c和main.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 <stdio.h>

void hello(const char *name)

{

printf("Hello %s!\n", name);

}


#include "hello.h"

int main()

{

hello("everyone");

return 0;

}


步:将hello.c编译成.o文件;

不管静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。

在系统提示符下键入下面命令得到hello.o文件。

# gcc -c hello.c

我们执行ls命令看看是否生存了hello.o文件。

# ls

hello.c hello.h hello.o main.c

在ls命令结果中,我们看到了hello.o文件。本步操作完毕。

以下我们先来看看怎样创建静态库,以及使用它。


步:由.o文件创建静态库。

静态库文件名称的命名规范是以lib为前缀。紧接着跟静态库名。扩展名为.a。比如:我们将创建的静态库名为myhello,则静态库文件名称就是libmyhello.a。

在创建和使用静态库时,须要注意这点。创建静态库用ar命令。

在系统提示符下键入下面命令将创建静态库文件libmyhello.a。

# ar cr libmyhello.a hello.o

我们相同执行ls命令查看结果:# ls    ls命令结果中有libmyhello.a。

hello.c hello.h hello.o libmyhello.a main.c


步:在程序中使用静态库。

静态库制作完了,怎样使用它内部的函数呢?仅仅须要在使用到这些公用函数的源程序中包括这些公用函数的原型声明。然后在用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文件開始。


步:由.o文件创建动态库文件。

动态库文件名称命名规范和静态库文件名称命名规范类似。也是在动态库名添加前缀lib,但其文件扩展名为.so。

比如:我们将创建的动态库名为myhello,则动态库文件名称就是libmyhello.so。

用gcc来创建动态库。

在系统提示符下键入下面命令得到动态库文件libmyhello.so。

# gcc -shared -fPIC -o libmyhello.so hello.o

我们照样使用ls命令看看动态库文件是否生成。# ls

hello.c hello.h hello.o libmyhello.so main.c


步:在程序中使用动态库;

在程序中使用动态库和使用静态库全然一样,也是在使用到这些公用函数的源程序中包括这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先执行gcc命令生成目标文件,再执行它看看结果。

# gcc -o hello main.c -L. –lmyhello

$gcc–o app main.c /home/test/program/ibmyLib.so

$gcc -o app2 main.c $PWD/libmyhelloso.so

# ./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!

#

成功了。这也进一步说明了动态库在程序执行时是须要的。

关于Linux静态库和动态库的分析的更多相关文章

  1. Linux下Gcc生成和使用静态库和动态库详解(转)

    一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...

  2. 在Linux下如何使用GCC编译程序、简单生成 静态库及动态库

      最近在编写的一个Apache  kafka 的C/C++客户端,,在看他写的 example中,他的编译是用librdkafka++.a和librdkafka.a    静态库编译的,,,而我们这 ...

  3. Linux下Gcc生成和使用静态库和动态库详解

    参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...

  4. [转]Linux下用gcc/g++生成静态库和动态库(Z)

    Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10|  分类: linux |  标签:链接库  linux  g++  gcc  |举报|字号 订阅     ...

  5. Linux 静态库和动态库 使用说明

        Linux下程序运行中,有两种库,静态库和动态库.     静态库:名字一般为libxxx.a,编译时会整合到可执行程序中,优点是运行时不需要外部函数库支持,缺点是编译后程序较大,一旦静态库改 ...

  6. 在Linux中创建静态库和动态库

    我们通常把一些公用函数制作成函数库,供其它程序使用. 函数库分为静态库和动态库两种. 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库. 动态库在程序编译时并不会被连接到目标代码中 ...

  7. 详细讲解 关于Linux静态库和动态库的分析

    基本概念 库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀. 例如:libhello.so libhello.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: ...

  8. linux下的共享库(动态库)和静态库

    1.什么是库在windows平台和linux平台下都大量存在着库.本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.由于windows和linux的本质不同,因此二者库的二进制是不 ...

  9. linux中C的静态库和动态库分析

    从开始学C语言写第一个"hello world"历程到现在,我依然困惑于到底这个程序完整的执行流程是什么样的.不过,现在我正在尝试一点一点的揭开它的面纱.现在,我尝试分析linux ...

  10. Linux学习笔记7——linux中的静态库和动态库

    一.静态库的编译 静态库的编译过程如下: 1.编译成目标文件 这里有一个可选项-static,调用格式:gcc -c -static 代码文件名.c 2.归档成静态库 A.归档的工具是ar工具,使用a ...

随机推荐

  1. 使用 Polyfill 而不再是 bable 来实践js新特性

    现状 我们想要用ES6 语法来写 JavaScript.然而由于我们需要兼容老版本的浏览器,那些浏览器不支持 ES6,我们需要解决这个问题. 有一个标准的做法是:写 ES6 代码 → 将所有代码编译成 ...

  2. 【BZOJ3456】城市规划

    题目 转送门 思路&算法 我们设点数为\(n\)的简单图的数量为\(f_n\), 点数为\(n\)的简单连通图有\(g_i\)个 于是我们知道,从\(n\)个点中选\(2\)个点有\(n \c ...

  3. 从0开始学习BFC

    为什么需要BFC? <style> .red { background: red; } .blue { background: #1890ff; } .green { background ...

  4. EasyUI DataGrid组织事件冒泡

    在事件内部需要阻止的地方添加如下代码 ]; 解释: arguments.callee是获得我自定义的事件处理方法OnSelected的方法体. .caller是获得调用OnSelected的上层方法( ...

  5. SQLServer2008 去除换行符

    declare @str varchar(8000)set @str='SQL语句' select replace(@str,char(10),'')

  6. linux 清空文件的几种方案

    之前要清理文件,都是简单粗暴的rm -rf log文件,最近,发现在某些环境下,是不能删除文件本省的,又必须要清理文件的内容信息,经过亲自实验,目测以下的几种方案是可行的,方案如下: 1.采用vi命令 ...

  7. 用JSP实现动态交互

    一.什么是JSP? 1.在HTML中嵌入Java脚本代码 2.由应用服务器中的JSP引擎来编译和执行嵌入的Java脚本代码 3.然后将生成的整个页面信息返回给客户端   二.为什么需要基于B/S技术的 ...

  8. 利用VMware14安装虚拟机(Win7&CentOS6.4)

    安装Win7 https://blog.csdn.net/Yangchenju/article/details/80694597 安装CentOS6.4 https://blog.csdn.net/u ...

  9. 计算laws的matlab代码

    很简单的代码:不过花了codeforge上的10个点,自己写也早写出来了; 代码如下: 文件:calLaws.m function [y,h_v,h_h]=calLaws(x,id,LocalEner ...

  10. The remote certificate is invalid according to the validation procedure 远程证书验证无效

    The remote certificate is invalid according to the validation procedure   根据验证过程中远程证书无效 I'm calling ...