1、最本质区别
是否被编译进程序内部
静态(函数)库
一般扩展名为(linux下是.a) (windows下是.lib),这类的函数库通常扩展名为libxxx.a或xxx.lib
静态库命名格式:lib + "库名称”+ .a(后缀) 例:libadd.a就是一个叫add的静态库
这类库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译成的文件会比较大,这类函数库最大的优点就是编译成功的可执行文件可以独立运行,而不再需要向外部要求读取函数库的内容;但是从升级难易度来看明显没有优势,如果函数库更新,需要重新编译。
动态函数库
动态函数库的扩展名一般为(linux下是.so)(windows下是.dll),这类函数库通常名为libxxx.so或xxx.dll
动态库命名格式:lib + "库名称”+ .so(后缀) 例:libadd.so就是一个叫add的动态库
与静态函数库被整个捕捉到程序中不同,动态函数库在编译的时候,在程序里只有一个“指向”的位置而已,也就是说当可执行文件需要使用到函数库的机制时,程序才会去读取函数库来使用;也就是说可执行文件无法单独运行。这样从产品功能升级角度方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件。
假如有程序1,程序2,和Lib.o三个文件,程序1和程序2在执行时都需要用到Lib.o文件,当运行程序1时,系统首先加载程序1,当发现需要Lib.o文件时,也同样加载到内存,再去加载程序2当发现也同样需要用到Lib.o文件时,则不需要重新加载Lib.o,只需要将程序2和Lib.o文件链接起来即可,内存中始终只存在一份Lib.o文件,而且12代码段共享数据段不共享。
动态链接优点
①毋庸置疑的就是节省内存;
②减少物理页面的换入换出;
③在升级某个模块时,理论上只需要将对应旧的目标文件覆盖掉即可。新版本的目标文件会被自动装载到内存中并且链接起来;
④程序在运行时可以动态的选择加载各种程序模块,实现程序的扩展。
动态库
lib.c
#include <stdio.h>
#include "lib.h"
static int a = 0;
void set(int v)
{
a = v;
printf("a = %d\n", a);
}
void get()
{
printf("b = %d\n", a);
}
lib.h
void set(int v);
void get();
编译生成动态库文件
gcc -fPIC -shared -o lib.so lib.c
两个进程一个写一个读
program1.c
#include "lib.h"
#include <time.h>
#include <unistd.h>
void main()
{
int cnt = 0;
while(1){
set(cnt++);
usleep(1000000);
}
return;
}
program2.c
#include "lib.h"
#include <time.h>
#include <unistd.h>
void main()
{
while(1){
get();
usleep(500000);
}
return;
}
gcc -o program1 program1.c ./lib.so
gcc -o program2 program2.c ./lib.so
./program1 &./program2
两个进程读写看来数据是不共享的
当我们两个线程公用一个动态函数库的时候
touch thread2.c
#include "lib.h"
#include <time.h>
#include <pthread.h>
#include <unistd.h>
void* thread1(void* data)
{
int cnt = 0;
while(1){
printf("thread1 set...\n");
set(cnt++);
usleep(1000000);
}
return NULL;
}
void* thread2(void* data)
{
while(1){
printf("thread2 get...\n");
get();
usleep(500000);
}
}
void main()
{
pthread_t thread_id;
pthread_create(&thread_id, NULL, &thread1, NULL);
pthread_create(&thread_id, NULL, &thread2, NULL);
while(1){
usleep(10000000);
}
return;
}
gcc thread2.c -o thread2 -lpthread ./lib.c
./thread2
不同线程数据段共享