在粤嵌学了很多知识,我们把常用的公用函数放在一起做成一个函数库,可以供其他程序共同使用,函数库本质上说,是一个可执行代码的二进制形式,可被操作系统载入内存执行。linux下的库分为两种:静态库,后缀名为

.a和动态库后缀名为.so(共享库);

两者的区别是:

静态库和动态库被载入应用程序的时刻不同,调用静态库函数的应用程序在编译时,会把静态库的代码链接到目标代码中(也就是应用程序的代码中),因此程序所占内存比较大,以后运行此目标程序时不再需要静态库;而动态库在程序编译时不会链接到目标代码中,动态库只有在程序执行时,才被载入内存,因此目标程序所占空间小(如下图),但是目标程序每次运行还要依赖这个动态库,所以如果这个动态库不存在了,则程序无法运行。

那么,linux下是如何使用和创建自己的函数库呢?我们以一个sin.c函数计算为例:

#include

int main(void)

{

float value;

value = sin ( 3.14 / 2 );

printf("%f\n",value);

}

我们编译这个函数:

gcc -o sin sin.c

出现以下错误信息:

sin.c: In function 'main':

sin.c:5: warning: incompatible implicit declaration of built-in

function 'sin'

/tmp/cciDlilg.o(.text+0x2c): In function `main':

sin.c: undefined reference to `sin'

collect2: ld returned 1 exit status

‘undefined reference to sin’,说的是没有 sin 的相关定义参考值!这是因为 C 语言里面的 sin

函示是写在 libm.so

这个函式库中,而我们并没有在原始码里面加入相关的说明,所以当然就需要在编译与连结的时候将这个函式库给他连结进执行档里面,所以可以这样做:

gcc -o sin sin.c -L/usr/lib -lm

"-L"是指定libm.so库所在的路径(linux函数库在/uer/lib中),-l是指定库函数的名字,

“m ” :则是 libm.so 这个函式库,其中, lib 与副档名(.a 或 .so)不需要写。

太棒了!终于编译成功了。现在看看如何建立自己的库!所有库的都是由.o文件生成的,我们再看一个简单的例子,先写出以下三个程序:程序hello.c:

#include

void hello(const char *name)

{

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

}

程序hello.h:

#ifdef HELLO_H

#define HELLO_H

void hello(const char *name)

#endif

程序main.c:

#include

int main()

{

hello("you are a good boy!");

return 0;

}

hello.c是我们要做的函数库的源文件,里面包含库函数hello(); hello.h是该库函数的头文件,main.c为测试这个函数库的程序; 如果我们这样编译main.c程序, gcc -o main

main.c 会出现以下错误: main.c:1:18:

error: hello.h: 没有那个文件或目录提示找不到头文件,因为hello.h是我们自己写的头文件,标准c函数库里面没有这个头文件,我们在编译时加一个参数-I.,指明hello.h在当前目录路径下(如果你放在其他路径下,就改为:-I/头文件路径名):

gcc -o main main.c -I.

不要开心太早,这时还会有错误:

/tmp/ccr2NRXk.o: In function `main':

main.c:(.text+0x11): undefined reference to `hello'

collect2: ld returned 1 exit status

这个错误是不是跟上面编译sin函数时出现的“sin.c:

undefined reference to `sin”是不是很像,没错,找不到库函数hello;因为缺省的/uer/lib里面没有这个库函数,这时候我们就要自己做一个函数库!先做一个静态库:1:将hello.c编译成hello.o文件,无论静态库还是动态库都由.o文件生成:

gcc -c hello.c

2:由.o文件来创建静态库:静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。

ar crv libmyhello.a

hello.o这是如果你看到libmyhello.a文件,说明你的静态库已经创建成功了!现在我们看看如何使用这个静态库:在程序main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。

gcc -o main main.c -L. -lmyhello

./main

hello:you are a good boy!

运行成功,由于静态库是在编译的链接到目标程序中的,编译成功后就不依赖静态库,此时你可以删除静态库libmyhello.a,在运行以下程序验证上面的说法!我们再来看看如何创建一个动态库:

1:动态库的命名个静态库一样,也是在动态库名增加前缀lib,但其文件扩展名为

.so。我们用gcc创建一个动态库名为myhello的文件:

gcc -shared -fPCI -o libmyhello.so hello.o

2:现在使用刚创建成功的libmyhello.so:在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。

gcc -o main main.c -L. -lmyhello

./main

./main: 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

# ./main

Hello:you are a good boy!

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

一般情况下,我们为了保持/usr/liub库的原始性,我们不把自己创建的动态库放在目录/usr/lib中,而是在其他路径下自己建立一个目录,然后把我们自己的函数库集中放在里面,这是编译时就要修改环境变量LD_LIBRARY_PATH,指向自己创建的函数库的路径,在linux下可以用export命令来设置和查看这个环境变量;

另外:当静态库和动态库同名时,gcc将优先使用动态库,可以自己验证以下!

linux 动态库建立,浅析linux下静态库和动态库的建立和使用相关推荐

  1. libcurl linux 静态链接库_GCC 程序编译的静态链接和动态链接

    转自:Mr_Bluyee 在链接阶段中,所有对应于源文件的 .o 文件."-l" 选项指定的库文件.无法识别的文件名(包括指定的.o目标文件和.a库文件)按命令行中的顺序传递给链接 ...

  2. linux php添加mysql扩展模块_linux下为php添加扩展库的方法

    本节内容: linux下添加php扩展库 这里以php curl 扩展库编译为例. 本次编译只是单独编译php的扩展库,然后将编译好的php扩展库加到现在运行的php中,不对现在运行的php重新编译, ...

  3. sqlserver mysql 7303_将MySQL库的表转入到MSSQL中的某个库中(Employees下的Employees表 → pubs库下)_2...

    将MySQL库的表转入到MSSQL中的某个库中(Employees下的Employees表 → pubs库下, 此pubs下的表名是employee,不冲突), 方法大致以下几个(另有其他方法待补充) ...

  4. linux添加Mib库,如何在ubuntu下使snmp支持mibs库字符串形式

    ubuntu下使用snmp,我们可以使用mibs库的OID来查询我们想要得到的结果,例如: snmpwalk -v 2c -c public localhost .1.3.6.1.2.1.25.2.2 ...

  5. linux发布动态网站吗,博达网站群多机发布架构,Linux环境Webserver使用Nginx情况下,站点设置成动态发布的时候,前台访问首页报403错误的问题说明...

    一.情况说明: 博达网站群多机发布架构,如果Web端使用nignx,动态发布的站点访问首页会出现403的错误: 而使用默认的Apache则不会出现该问题: 这是由于Nginx自身特性导致的,请求的文件 ...

  6. linux 进程通信比较,浅析Linux进程通信的几种方式及其比较

    摘要:本文通过对Linux下几种主要通信方式进行概述,并结合Linux系统的系统调用对OS中的实现进行简要概述,并对其优缺点进行分析,阐述了在不同通信情况下应该选择何种通信方式进行选择. 关键词:Li ...

  7. linux中pri=100,浅析Linux中PRI和NI的关系

    Linux中: 所有的优先级范围为0-139,一共140个优先级,数值越低优先级越高; 优先级范围100-139称为静态优先级,这个范围里的进程属于非实时进程,调度方式是:SCHED_OTHER,也就 ...

  8. linux+c+时间间隔+ns,浅析 Linux 中的时间编程和实现原理,第 1 部分: Linux 应用层的时间编程...

    http://www.ibm.com/developerworks/cn/linux/1307_liuming_linuxtime1/index.html#ibm-pcon 本文试图完整地描述 Lin ...

  9. Linux多进程拷贝fork,浅析linux中fork函数

    Linux通过clone()系统调用实现fork().vfork()和__clone()库函数创建新的进程,这个调用通过一系列的参数标志来指明父子进程的共享资源,终将各自的参数标志位传递给clone, ...

最新文章

  1. 麻省理工学院的牛人解说数学体系,你到哪个层次了?
  2. 【Android 应用开发】 Android 各种版本简介 ( Support 支持库版本 | Android Studio 版本 | Gradle 版本 | jcenter 库版本 )
  3. 分布式版本控制系统Mercurial(一):Mercurial基本功能介绍
  4. 【答案放在最后,看题看不到答案】2017年下半年软件设计师 上午选择题
  5. 转载大神的一篇文章----【如何选择开源许可证?】
  6. UVA - 11246 - K-Multiple Free set(容斥原理)
  7. mysql常用命令整理
  8. python一直循环怎么写_自学Python,写一个挨打的游戏代码来初识While循环
  9. CSS→代码语法、优先级、选择器、权值、字体文本、颜色、长度值、块状内联元素、盒模型、布局模型→层模型绝对相对定位、div排列、水平居中
  10. RTL8305NB傻瓜式交换机无法工作
  11. 手把手教你学51单片机_第 一、二章
  12. 莫烦python sklearn笔记
  13. 计算机机房空调原理,机房精密空调的工作原理
  14. [37期]二三事。老师说标题长才霸气。长长长…
  15. eval函数python原理_Python 中 eval 函数的神奇用法
  16. 南理ARPG游戏深度学习One
  17. 绿色便携版谷歌浏览器制作流程
  18. 使用VS Code通过Markdown语法快速画流程图时序图等
  19. 如何快速成为Python工程师?
  20. LeetCode刷题总结01--哈希表问题

热门文章

  1. 网页最少要有一个html标签,PHP_网页开发人员必须知道的10个不常用HTML标签, 网页开发人员常常希望能 - phpStudy...
  2. linux的笔画动态加载,关于Android中GestureOverlayView多笔画的问题
  3. 09丨缓存异常:如何解决缓存和数据库的数据不一致问题
  4. SSM实现个人博客-day01
  5. 第一次安装Intellij IDEA过程中遇到的坑
  6. 笔试——查找重复数(杭州某准独角兽)
  7. Visual Studio 2019 + Visual C++——创建Visual C++ Hello World! 程序
  8. Spring Boot——自定义多个拦截器(HandlerInterceptor)配置方法与执行顺序
  9. JAVA——文档注释(javavdoc)通用注释-超链接@see与@link的使用
  10. oracle中触发器的语法,解析Oracle触发器的语法