静态库,动态库用UNIX 的术语来说,或者叫做归档文件(archive 常以.a 结尾)和共享对象(share object 常以lib 开头.so 结尾)更为准确。静态库,动态库可能是WINDOWS 下的术语,但两者的概念是一样的。下面统一说静态库和动态库。

静态库,就是一大堆object (CC ,CC 在LINUX 下其实是软件链接到GCC 的,编译后默认为.o 结尾的)的集合。静态库就是用ar 等工具集合在一起。在编译的时候,连接器就会将这部分代码嵌入到目标代码里。

动态库,也是一大堆object 的集合(编译成动态或静态,只是编译选项的不同)。不同的时,在编译的时候,连接器并没有将这部分代码嵌入到目标代码里,而在运行时的时候,才加载代码。

由此,一般情况下用静态库一般都比动态库大。

一、静态库编写

以简单起见,写个非常简单例子。

//hello.h

#ifndef _HELLO_H

#define _HELLO_H

void sayhello(const char* msg);

void saygoodbye(const char* msg);

#endif

//hello.c

#include "hello.h"

#include <unistd.h>

#include <string.h>

#include <stdio.h>

void sayhello(const char* msg)

{

char wel[] = "welcome to invoke sayhello function/n";

char hellomsg[BUFSIZ] = "hello, ";

write(STDOUT_FILENO, wel, strlen(wel)+1);

strcat(hellomsg, msg);

strcat(hellomsg, "/n");

write(STDOUT_FILENO, hellomsg, strlen(hellomsg)+1);

}

void saygoodbye(const char* msg)

{

char wel[] = "welcome to invoke saygoodbye function/n";

char goodbyemsg[BUFSIZ] = "goodbye, ";

write(STDOUT_FILENO, wel, strlen(wel)+1);

strcat(goodbyemsg, msg);

strcat(goodbyemsg, "/n");

write(STDOUT_FILENO, goodbyemsg, strlen(goodbyemsg)+1);

}

先编译

[heidong@bogon hellolib]$ gcc -Wall -c hello.c

上面命令将产生hello.o 的obj 文件。(PS 一下:注意到bogon 了吗?你可以猜测我的网络环境)。-Wall 表示打开所有的编译警告。-c 表示只编译不连接。

再创建静态库

[heidong@bogon hellolib]$ ar -cru libhello.a hello.o

一般库文件是以lib 开头的,链接的时候不必指定lib 前缀。-cru 表示创建并替换为最新的。具体各个参数参看ar 的man 页。为了方便,抄袭一些来,鲁迅说拿来主义。

Option Name Example

-d Delete ar -d <archive> <objects>

-r Replace ar -r <archive> <objects>

-t Table list ar -t <archive>

-x Extract ar -x <archive> <objects>

-v Verbose ar -v

-c Create ar -c <archive>

-ru Update object ar -ru <archive> <objects>

至此,文件如下

[heidong@bogon hellolib]$ ls

hello.c hello.h hello.o libhello.a

测试

//statictest.c

#include "hello.h"

int main(int argc, char**argv)

{

char msg[] = "heidong";

sayhello(msg);

saygoodbye(msg);

return 0;

}

编译

[heidong@bogon hellolib]$ gcc -o statictest.o statictest.c -L. -lhello

-L. 表示将当前目录添加到库查找目录里。系统标准的库目录是/usr/lib, /lib, /usr/local/lib 等等。-lhello 表示连接libhello 这个静态库。

测试

[heidong@bogon hellolib]$ ./statictest.o

welcome to invoke sayhello function

hello, heidong

welcome to invoke saygoodbye function

goodbye, heidong

工作了。

二、动态库

代码依然是用上面的,但是编译的选项却不同。

编译

[heidong@bogon hellolib]$ gcc -c hello.c -fPIC

[heidong@bogon hellolib]$ gcc -shared hello.o -o libhello.so

[heidong@bogon hellolib]$ gcc -o statictest.o statictest.c -L. -lhello

-fPIC 表示位置独立的。具体是什么的缩写不知道。第一行生成 hello.o ,第二行将生成动态库libhello.so 。第三行的意思我上面所说的一样。

测试

[heidong@bogon hellolib]$ ./statictest.o

./statictest.o: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

咦,出错,原因就是找不到 libhello.so 这个动态库。有两个解决办法。第一,最简单的就是将库文件复制到系统库目录。需要根用户权限。第二种办法,添加 LD_LIBRARY_PATH 环境变量为所在库的目录。

再次测试

[heidong@bogon hellolib]$ export LD_LIBRARY_PATH=./

[heidong@bogon hellolib]$ ./statictest.o

welcome to invoke sayhello function

hello, heidong

welcome to invoke saygoodbye function

goodbye, heidong

Ok 啦。

可以用ldd 查看依赖于哪些库。

[heidong@bogon hellolib]$ ldd statictest.o

linux-gate.so.1 => (0x00ddf000)

libhello.so => ./libhello.so (0x00e98000)

libc.so.6 => /lib/libc.so.6 (0x00b2a000)

/lib/ld-linux.so.2 (0x00232000)

可见,除了我们的库外,还有额外三个。 libc.so.6 为标准C 的库, lib/ld-linux.so.2为动态连接/加载的库。至于第一个,不太清楚,网上说是“linux-gate.so.1 文件目前在文件系统中根本就不被支持  它只是一个虚拟的DSO (译者注virtual DSO :dynamically shared object ),一个在每个进程的存储空间(process’ memory )指定的地址点被内核暴露出来的共享对象”

三、运行时加载动态库

就是在程序运行的过程中动态地加载动态库(和WINDOWS 下的LoadLibrary 一样)。四个关键的函数:

#include <dlfcn.h>

void *dlopen( const char *filename, int flag );

const char *dlerror( void );

void *dlsym( void *handle, char *symbol );

int dlclose( void *handle );

例子:

#include <unistd.h>

#include <stdio.h>

#include <dlfcn.h>

#include <stdlib.h>

int main(int argc, char**argv)

{

void (*sayhello)(const char*);

void (*saygoodbye)(const char*);

void* handle = NULL;

char* err;

handle = dlopen("libhello.so", RTLD_LAZY);

if(handle == NULL){

fprintf(stderr, "%s/n", dlerror());

exit(-1);

}

sayhello = dlsym(handle, "sayhello");

err = dlerror();

if(err != NULL){

fprintf(stderr, "%s/n", err);

}else{

sayhello("heidong");

}

saygoodbye = dlsym(handle, "saygoodbye");

err = dlerror();

if(err != NULL){

fprintf(stderr, "%s/n", err);

}else{

saygoodbye("heidong");

}

saygoodbye = dlsym(handle, "sssssssaygoodbye");

err = dlerror();

if(err != NULL){

fprintf(stderr, "%s/n", err);

}else{

saygoodbye("heidong");

}

dlclose(handle);

return 0;

}

编译+测试

[heidong@bogon hellolib]$ gcc -Wall -ldl dynamicload.c -o dynamicload.out

[heidong@bogon hellolib]$ ./dynamicload.out

welcome to invoke sayhello function

hello, heidong

welcome to invoke saygoodbye function

goodbye, heidong

./libhello.so: undefined symbol: sssssssaygoodbye

[heidong@bogon hellolib]$

最后一个没有,所以出错。

四、一些常用工具

4.1 file, 测试文件类型:

[heidong@bogon hellolib]$ file libhello.so

libhello.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped

[heidong@bogon hellolib]$ file statictest.o

statictest.o: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

[heidong@bogon hellolib]$

4.2 size 测试可执行文件的代码。

[heidong@bogon hellolib]$ size statictest.o

text data bss dec hex filename

1167 264 8 1439 59f statictest.o

text 为代码段,data 为已经初始化的变量,bbs 为未初始为的变量。Dec 和hex 分别为前三个之和的十进制和十六进制表示。

4.3 nm 查看有哪些导出函数。

[heidong@bogon hellolib]$ nm libhello.so | grep " T "

00000784 T _fini

00000308 T _init

000005cb T saygoodbye

0000046c T sayhello

4.4 objdump 类似windows 下的dumpbin 。

[heidong@bogon hellolib]$ objdump -d libhello.so

libhello.so: file format elf32-i386

Disassembly of section .init:

00000308 <_init>:

308: 55 push %ebp

309: 89 e5 mov %esp,%ebp

30b: 83 ec 08 sub $0x8,%esp

UNIX环境下用C语言写静态库与动态库的更多相关文章

  1. 在windows下用C语言写socket通讯实例

    原文:在windows下用C语言写socket通讯实例 From:Microsoft Dev Center #undef UNICODE #define WIN32_LEAN_AND_MEAN #in ...

  2. 在 win10 环境下,设置自己写的 程序 开机自动 启动的方法

    原文:在 win10 环境下,设置自己写的 程序 开机自动 启动的方法 1.是登录自己用户时才能开机启 C:\Users\username\AppData\Roaming\Microsoft\Wind ...

  3. C语言静态库与动态库(Windows下测试)

    转载于:https://zhidao.baidu.com/question/1946953913764139388.html,原文为Linux上测试,本文为在Windows上编译测试 我们通常把一些公 ...

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

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

  5. Windows下静态库、动态库的创建和调用过程

    静态库和动态库的使用包括两个方面,1是使用已有的库(调用过程),2是编写一个库供别人使用(创建过程).这里不讲述过多的原理,只说明如何编写,以及不正确编写时会遇见的问题. //注:本文先从简单到复杂, ...

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

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

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

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

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

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

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

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

随机推荐

  1. [每天一道A+B]签到检测程序

    签到检测程序,解析github提供的api内的json,解决了服务器和本地时间不同步的问题(时差+8H),实现按日期更新当前签到表.下一步是从api获取organization的信息,求出未签到的成员 ...

  2. Hbase源码分析:Hbase UI中Requests Per Second的具体含义

    Hbase源码分析:Hbase UI中Requests Per Second的具体含义 让运维加监控,被问到Requests Per Second(见下图)的具体含义是什么?我一时竟回答不上来,虽然大 ...

  3. Qt之HTTP上传/下载

    简述 在前面章节中我们讲述了关于Qt显示网络图片的内容,比较简单,因为图片一般都比较小,下载到本地速度比较快,所以基本不需要什么特殊处理,本节我们主要针对HTTP实现上传/下载进行详细的讲解与分享,包 ...

  4. UVa 839 (递归方式读取二叉树) Not so Mobile

    题意: 递归的方式输入一个树状天平(一个天平下面挂的不一定是砝码还可能是一个子天平),判断这个天平是否能满足平衡条件,即W1 * D1 == W2 * D2. 递归的方式处理输入数据感觉很巧妙,我虽然 ...

  5. 4630 no pain no game 树状数组

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4630 题意:给你N个数,然后给你M个询问,每个询问包含一个l 一个r,问你lr 这个区间中任意两个数最 ...

  6. 安卓WebView中接口隐患与手机挂马利用(远程命令执行)

    安卓应用存在安全漏洞,浏览网站打开链接即可中招.目前有白帽子提交漏洞表明目前安卓平台上的应用普遍存在一个安全漏洞,用户打开一个链接就可导致远程安装恶意应用甚至完全控制用户手机,目前微信,手机QQ,QV ...

  7. [转载]hao123军事频道首页JQ焦点图

    适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗. *本作品由[站长素材]收集整理,转载请注明出处! 下载地址

  8. WEBUS2.0 In Action - [源代码] - C#代码搜索器

    最近由于工作的需要, 要分析大量C#代码, 在数万个cs文件中搜索特定关键词. 这是一项非常耗时的工作, 用Notepad++要运行接近半个小时. 于是我利用WEBUS2.0 SDK创建了一个代码搜索 ...

  9. POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)

    题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...

  10. kthread_stop引起的OOP

    1 使用kthread_create创建线程:     struct task_struct *kthread_create(int (*threadfn)(void *data), void *da ...