- 浏览: 223317 次
- 性别:
- 来自: 北京
最新评论
-
qq452739204:
如果构造的报文大于mtu值,是否需要分片之后再发送出去列?
Linux内核构造数据包并发送(二)(dev_queue_xmit方式) -
xingzengmou:
你好,我搞的原理跟你差不多,但播放的时候有papapa的声音, ...
AudioRecord和AudioTrack类的使用 -
wenjiefeng:
楼主,你有录制pcm格式和播放pcm格式的录音器的demo吗, ...
AudioRecord和AudioTrack类的使用 -
lovepeakingA:
...
AudioRecord和AudioTrack类的使用 -
ZaneLee007:
假的,不学无术
Android禁用键盘的所有按键
库的作用
大体上库的存在,有两方面的原因,一是代码的复用,二是声明和实现的分离。将功能相近的使用模块封装成库,使代码的复用、管理和分发变得简单了许多,例如著名的开源图形库ncurses,你可以自行编译,更可以直接使用已经编译好的现成的库文件。另外,由于库是二进制文件,某种意义上讲,将功能的实现部分隐藏了起来,这就为商业代码的保护提供了一种方式。
库文件按照链接方式和时机,可以分为动态库和静态库,下面分别介绍它们在Linux环境中的创建和使用方法。
静态链接库
静态库是指在程序的链接阶段,其中被用到的代码会被直接链接到可执行文件中的库。静态链接的可执行程序包含了其所需的全部库函数:所有库函数都连接到程序中。 这类程序是完整的,其运行不需要外部库的支持。 静态链接程序的优点之一是其安装之前不需要做环境准备工作 。
Linux中,静态库的扩展名通常为.a,它仅仅是一些目标文件(.o)的归档(archive)或者说打包,另外,为了链接时能够快速地定位其中的符号(函数、变量名等),静态库还会包含一个对其中符号的索引。
创建静态库的过程十分简单,除编译所必须的工具之外,要用到的命令只有两个ar和ranlib。ar可以将各个目标文件进行归档,ranlib对ar生成的归档文件(即静态库文件)进行索引。假设现在有这样几个源文件:plus.c, sub.c及相应的头文件,另外还有一个用来调用库文件中函数的主文件main.c,它们的内容分别是:
plus.c,
#include "plus.h" int plus(int a, int b) { return a + b; }
sub.c,
#include "sub.h" int sub(int a, int b) { return a - b; }
main.c,
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "plus.h" int main(int argc, char **argv) { int a = plus(1, 2); printf("%d\n", a); return 0; }
下面将plus.c和sub.c编译,制作成静态库libmath.a,依次执行:
$ cc main.c -L. -lmath -o main
$ ./main
动态链接库
动态库和静态库相似,也是各个目标文件的集合。但相比静态链接的程序,动态链接可执行程序要小得多:这类程序运行时需要外部共享 函数库的支持,因此好像并不完整。除了程序体小之外,动态链接允许程序包指定必须的库,而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库,这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因,当前多数程序采用动态链接技术。
在Linux中的扩展名通常为.so。但在链接时,并不会被链接到可执行文件中,而是在执行时(需要时)由操作系统的动态加载模块动态地加载到内存,并链接到可执行文件地址空间的相应位置。
动态链接库的创建也分为编译和”归档”两个阶段,但不同的是在这两个阶段需要使用一些不同的命令选项。首先,需要将源文件编译成一种成为位置无关码(PIC: Position Independent Code)的目标文件,这种代码可以被加入到内存的任何位置却不需要加载器对其进行重定位,关于这种格式可以参考《链接器与加载器》和《程序员的自我修养–链接装载与库》中较为详尽的描述。接下来需要将这些位置无关码“归档”为.so文件。整个过程只需一个工具即可,即gcc。还是上面的源文件,执行以下命令:
$ cc -c -fpic plus.c sub.c $ cc -shared -o libmath.so *.o |
这样,包含plus.o和sub.o的动态库文件libmath.so就创建完成了。其中cc(gcc的符号链接)命令的-fpic或-fPIC选项使之创建位置无关的目标文件,使用-shared选项可以创建最终的动态库文件。
使用动态库文件有两种方法,一种是让操作系统的动态加载模块(如ld-linux.so.2)在执行时加载动态库。另一种是在代码中使用dl库动态加载库文件。
先介绍下第一种方法。使用这种方法需要在编译可执行文件时指明库名及其路径(对于自己的编写的动态库而言):
|
$ cc main.c -L. -lmath -o main |
这时可执行文件main就被创建了,上面的命令并没有将libmath.so中相应的目标代码链接到main中(你可以对比一下这里的main和静态链接的main的大小),只是在库中查找和确认main.c中用到的符号而已。但通常这个main现在还无法正常执行,这涉及到系统查找动态库的路径问题,系统通常只在某些指定的目录(标准路径)下查找所需的库文件,若在标准路径中无法找到所需的库,则会到环境变量LD_LIBRARY_PATH(如果存在的话)指定的目录下查找,若仍无法找到就会报错。因为libmath.so在main的当前目录中,而当前目录通常并不在标准路径之列。为了使libmath.so能够被找到和加载,你可以把它放到标准路径中,但更好的方法是将其所在目录加入到LD_LIBRARY_PATH变量中。执行下面的命令:
|
$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. # 添加当前目录 $ export LD_LIBRARY_PATH # 将环境变量导出,使其在子shell中可用 $ ./main 3 |
下面介绍使用dl库加载动态库,dl库中函数很少很简练,看main.c代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <dlfcn.h> #include "plus.h" int main(int argc, char **argv) { void * lib_handle = dlopen("./libmath.so", RTLD_LAZY); if(lib_handle) { int (*plus_ptr)(int, int) = dlsym(lib_handle, "plus"); if(plus_ptr) { int a = plus_ptr(1, 2); printf("%d\n", a); } dlclose(lib_handle); } return 0; }
main.c中,首先使用dlopen打开需要的动态库,其中参数RTLD_LAZY指明仅当需要调用该库时才进行加载。dlopen返回一个句柄,dlsym使用该句柄和符号来取得相应函数的地址,这里使用int (*)(int, int)函数指针来接收plus函数的地址。接下来使用得到的函数指针调用相应的函数,最后通过dlclose函数来关闭句柄。编译这个程序需要使用dl动态链接库,因此需要使用gcc的-ldl选项:
$ cc main.c -ldl -o main
$ ./main
so与.a文件的对比
最后附上libmath.a和libmath.so文件的内容,使用objdump的-d选项查看的:
libmath.a,
In archive libmath.a: plus.o: file format elf32-i386 Disassembly of section .text: 00000000 <plus>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 8b 45 0c mov 0xc(%ebp),%eax 6: 8b 55 08 mov 0x8(%ebp),%edx 9: 8d 04 02 lea (%edx,%eax,1),%eax c: 5d pop %ebp d: c3 ret sub.o: file format elf32-i386 Disassembly of section .text: 00000000 <sub>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 8b 45 0c mov 0xc(%ebp),%eax 6: 8b 55 08 mov 0x8(%ebp),%edx 9: 89 d1 mov %edx,%ecx b: 29 c1 sub %eax,%ecx d: 89 c8 mov %ecx,%eax f: 5d pop %ebp 10: c3 ret
libmath.so:
libmath.so: file format elf32-i386 Disassembly of section .init: 00000324 <_init>: 324: 55 push %ebp 325: 89 e5 mov %esp,%ebp 327: 53 push %ebx 328: 83 ec 04 sub $0x4,%esp ...... 0000044c <plus>: 44c: 55 push %ebp 44d: 89 e5 mov %esp,%ebp 44f: 8b 45 0c mov 0xc(%ebp),%eax 452: 8b 55 08 mov 0x8(%ebp),%edx 455: 8d 04 02 lea (%edx,%eax,1),%eax 458: 5d pop %ebp 459: c3 ret 45a: 90 nop 45b: 90 nop 0000045c <sub>: 45c: 55 push %ebp 45d: 89 e5 mov %esp,%ebp 45f: 8b 45 0c mov 0xc(%ebp),%eax 462: 8b 55 08 mov 0x8(%ebp),%edx 465: 89 d1 mov %edx,%ecx 467: 29 c1 sub %eax,%ecx 469: 89 c8 mov %ecx,%eax 46b: 5d pop %ebp 46c: c3 ret 46d: 90 nop 46e: 90 nop 46f: 90 nop ...... Disassembly of section .fini: 000004a8 <_fini>: 4a8: 55 push %ebp 4a9: 89 e5 mov %esp,%ebp 4ab: 53 push %ebx 4ac: 83 ec 04 sub $0x4,%esp 4af: e8 00 00 00 00 call 4b4 <_fini+0xc> 4b4: 5b pop %ebx 4b5: 81 c3 40 1b 00 00 add $0x1b40,%ebx 4bb: e8 d0 fe ff ff call 390 <__do_global_dtors_aux> 4c0: 59 pop %ecx 4c1: 5b pop %ebx 4c2: c9 leave 4c3: c3 ret
可见,相对.a,.so有很多额外的代码段,其中比较重要的是<_init>段和<_fini>段。它们分别进行一些前期和后期处理工作,例如<_init>通常在dlopen返回之前执行一些.so库中的一些初始化工作(C++中就可能是全局构造或者静态对象的构造函数)。
转自:http://www.dutor.net/index.php/2010/07/dynamic-static-library/
发表评论
-
Netfilter 地址转换的实现
2011-03-17 23:04 0作者:九贱内核版本:2 ... -
Linux内核构造数据包并发送(二)(dev_queue_xmit方式)
2011-03-03 12:24 8817linux内核太构造数据包 ... -
Linux内核构造数据包并发送(Netfilter方式)
2011-03-03 12:21 5029一、构造数据包简析 这里并不详细介绍如何在内核中构造数据包,下 ... -
iphdr与tcphdr详解(skb_header_pointer函数分析)
2011-03-01 12:25 4413linux 2.6.26 下获取tcp信息: tcph=sk ... -
unp.h文件内容
2010-11-28 15:33 2101/* Our own header. Tabs are se ... -
inet_pton和inet_ntop函数
2010-11-28 15:03 1875Linux下这2个IP地址转换函数,可以在将IP地址在“点分十 ... -
linux类原版电子书589本
2010-10-27 16:13 4179ftp://202.96.64.144/pub/books/( ... -
Linux下线程同步对象——互斥量
2010-10-09 10:47 1568进程是Linux资源分配的对象,Linux会为进程分配虚 ... -
系统信息相关命令
2010-09-27 15:55 790系统 # uname -a ... -
Linux中实现30分钟无操作自动关机
2010-09-27 15:42 1678这是一个自动关机的小程序。该程序可以守护进程的方式运行, ... -
linux IPC-消息队列
2010-09-27 14:02 2350几乎所有的 Linux 发行版本都包含 ipcs 命 ... -
8)Linux程序设计入门--网络编程(下)
2010-09-26 14:12 1053网络编程(7) 7. TCP/IP协议 你也许听说过T ... -
8)Linux程序设计入门--网络编程 (上)
2010-09-26 14:07 1189Linux系统的一个主要 ... -
7)Linux程序设计入门--线程操作
2010-09-26 13:58 914前言:Linux下线程的创 ... -
6)Linux程序设计入门--消息管理
2010-09-26 13:56 946前言:Linux下的进程通 ... -
5)Linux程序设计入门--信号处理
2010-09-26 13:54 985Linux下的信号事件 前 ... -
4)程序设计入门--时间概念
2010-09-26 13:50 748前言:Linux下的时间概 ... -
3)Linux程序设计入门--文件操作
2010-09-26 13:48 957Linux下文件的操作 前言: 我们在这一节将要讨论 ... -
2)Linux程序设计入门--进程介绍
2010-09-26 11:05 837前言: 这篇文章是用 ... -
1)Linux程序设计入门--基础知识
2010-09-26 11:02 820Linux下C语言编程基础知识 前言: 这篇文章介绍 ...
相关推荐
文中是linux下 C++动态库 实现接口提供类导出的一个例子 注意其中使用函数返回基类指针的用法,因为Linux的动态链接库不能像MFC中那样直接导出类 一、介绍 如何使用dlopen API动态地加载C++函数和类,是Unix C++...
第1章绪论.1 1.1操作系统概述1 1.1.1建立操作系统的目标1 1.1.2操作系统是用户与计算机的接口1 1.1.3操作系统是资源管理器2 1.2UNIX系统的主要特性3 1.3UNIX系统的发展史4 1.4开源软件与UNIX的推广发展6 1.4.1开源...
2.1 Linux环境下的编辑器 14 2.1.1 vim使用简介 14 2.1.2 使用vim建立文件 15 2.1.3 使用vim编辑文本 16 2.1.4 vim的格式设置 18 2.1.5 vim配置文件.vimrc 19 2.1.6 使用其他编辑器 19 2.2 Linux下的...
2.1 Linux环境下的编辑器 14 2.1.1 vim使用简介 14 2.1.2 使用vim建立文件 15 2.1.3 使用vim编辑文本 16 2.1.4 vim的格式设置 18 2.1.5 vim配置文件.vimrc 19 2.1.6 使用其他编辑器 19 2.2 Linux下的...
第三讲 Linux下的网络服务,配置问题和常用工具.................................................................24 一.Linux下的网络服务.....................................................................
2.1 Linux环境下的编辑器 14 2.1.1 vim使用简介 14 2.1.2 使用vim建立文件 15 2.1.3 使用vim编辑文本 16 2.1.4 vim的格式设置 18 2.1.5 vim配置文件.vimrc 19 2.1.6 使用其他编辑器 19 2.2 Linux下的...
第十三章 UNIX域套接字和并发服务器的预创建技术 13.1 UNIX域套接字 13.1.1 UNIX域的地址结构 13.1.2 UNIX(套接字使用的示例 13.1.3 传递文件描述符 13.2 并发服务器的预创建技术 ...
C ++便携式动态加载程序一个小型轻量级的库,用于在C ++中创建和使用动态加载的类。 通用接口可在Windows和Unix / Linux平台上使用。
你可以创建一个dll或动态库以便简化连接。 如果你要支持SSL(HTTPS)及压缩的话,可以安装OpenSSL及Zlib库。 gSOAP是独立开发包,不需要任何第三方的软件支持(除非你要用到OpenSSL及Zlib)。 与平台无关的...
程序也必须使用和库一样的设定.可用的选项的介绍参见 Build options 章节. 如果你希望改变缺省的设置,推荐你通过修改命令行参数的方式来实现.(在Visual Studio 的工程设置项里面). 5 基本使用 为了使用LuaBind, ...
9 广泛的操作系统,Web服务器,数据库和编程语言支持 后台支持Windows,Linux,Unix等各种操作系统;支持IIS,Domino,Websphere,Apache等所有后台WEB服务器类型,支持Db2,Oracle,MySQL,SQL Server等各种常用...
而原始的ALGLIB并没有提供静态或动态库来调用,插值函数的参数是字符串类型(你可以看例子),而不是通用的C++数组。 但我想要一种更简单的方法来调用插值函数,为此,我必须添加一些与 MATLAB 函数类似的新函数,以...
◆覆盖了Windows,UNIX,Linux,BeOS和其它操作系统的动态链接过程。 ◆解释了Java链接模式,以及它是如何应用在网络小应用程序和可扩展Java代码中的。 ◆帮助你编写更优雅、更高效的代码,以及构建能够被更加高效地...
17.5 在多线程环境中使用SWIG生成的模块 603 17.6 用PySequence_Fast将Python序列转为 C数组 604 17.7 用迭代器逐个访问Python序列的元素 608 17.8 从Python可调用的C函数中返回None 611 17.9 用gdb调试动态载入...
目录 历史 前言 I....1. 程序的基本概念 1. 程序和编程语言 2. 自然语言和形式语言 ...3. 在Linux C编程中使用Unicode和UTF-8 B. GNU Free Documentation License Version 1.3, 3 November 2008 参考书目 索引
创建一个角度库 角度编译器 调试 部署 Java 博客/文章/教程 视频课程 图书 Java - Spring/Spring-Boot 博客/文章/教程 视频课程 图书 C#、.NET 穿线 工具 数据结构和算法 博客/文章/教程 分而治之 动态规划 贪心算法...
当然,也适用于Linux/FreeBSD/Unix及微软Windows 2000/2003/2008/XP/NT等多种操作系统,初学者推荐WAMP一键搭建WSTMall所需要环境。 先进的动态模型:WSTMall完全继承thinkphp的CURD机制,无需创建任何对应的模型...
使用cgi创建动态页面 guestbook.cgi脚本程序 定义表单以及处理表单数据 cgi.tcl软件包 接下去的几步 第4章 tcl中的字符串处理 string命令 append命令 format命令 scan命令 binary命令 相关章节 第5章...
UNIX/X11,包括Linux,Sun Solaris,HP-UX,HP Tru64 UNIX,IBM AIX,SGI IRIX等; \? Mac OS X,支持Mac OS X 10.3以上版本; \? 嵌入式Linux,包括支持framebuffer的所有Linux平台。 \Qt还支持嵌入式系统,Qt...