庫函數既提升了代碼的利用率,又屏蔽了函數內部實現的細節,給不一樣開發者提供了統一的接口。從實現來看,庫函數能夠分爲動態函數庫和靜態函數庫。同一組函數,能夠根據須要封裝成靜態庫和動態庫。那麼生成靜態庫和動態庫有什麼區別?靜態庫和動態庫對函數的實現上各有些什麼要求?二者對內存各有什麼影響呢?下面就帶着這些問題一塊兒開探討。
靜態庫和動態庫生成方式的區別
爲了簡化,下面以一個只有一個函數的庫的實現來講明。庫函數的代碼demo.c以下:
/*******************************************************************/
int cal(int a, int b)
{
return (a^(a << b)) + (b << a);
}
main.c中的代碼以下:
[root@localhost mylib]# cat main.c
#include<stdio.h>
#include "demo.h"
int main(void)
{
printf("Call cal(7,8) = %08x\n", cal(7,8));
}
[root@localhost mylib]# cat demo.h
int cal(int, int);
若是須要生成動態庫,則須要用到下面的Makefile:
MYLIB := libdemo.so
BIN := test
CFLAG := -Wall -I../ -I./ -DTEST=1
LIBFLAG := -L./ -rpath=/home/xqch/workspace/mylib ./ -ldemo
all: $(MYLIB) $(BIN)
$(BIN): main.o
gcc $(CFLAG) -L/home/xqch/workspace/mylib -ldemo -o $@ $^
$(MYLIB): demo.o
ld -shared -fpic -rpath=/home/xqch/workspace/mylib -o $@ $^
%.o:%.c
gcc $(CFLAG) -c -o $@ $<
.PHONY: ×××tall clean
×××tall:
cp $(MYLIB) /usr/lib
cp $(MYLIB) /lib
clean:
rm -rf *.o $(BIN) $(MYLIB)
而生成靜態庫的過程以下:
[xqch@localhost mylib]$ cat Makefile
MYLIB := libdemo.a
BIN := main
CFLAG := -Wall -I../ -I./ -DTEST
all: $(MYLIB) $(BIN)
$(BIN): main.o
gcc $(CFLAG) -o $@ $^ $(MYLIB)
$(MYLIB): demo.o
ar -rcv $@ $^
%.o:%.c
gcc $(CFLAG) -c -o $@ $<
.PHONY: clean
clean:
rm -rf *.o $(BIN) $(MYLIB)
靜態庫和動態庫生成的二進制代碼的區別
基於上面的兩個Makefile咱們能夠對比下它們的區別:
[xqch@localhost mylib]$ ls -alrt main
-rwxrwxr-x. 1 xqch xqch 7696 Oct 26 21:21 main
dynamic:
[xqch@localhost mylib]$ ls -alrt test
-rwxrwxr-x. 1 xqch xqch 7602 Oct 25 19:32 test
能夠看到靜態庫生成的可執行文件比須要連接動態庫生成的可執行文件大.經過反彙編,咱們能夠看到差別就在於對庫函數的調用方式不一樣:
static:
08048724 <cal>:
8048724: 55 push %ebp
8048725: 89 e5 mov %esp,%ebp
8048727: 53 push %ebx
8048728: 83 ec 04 sub $0x4,%esp
804872b: a1 30 a0 04 08 mov 0x804a030,%eax
8048730: 83 c0 01 add $0x1,%eax
8048733: a3 30 a0 04 08 mov %eax,0x804a030
8048738: a1 3c a0 04 08 mov 0x804a03c,%eax
804873d: 83 c0 01 add $0x1,%eax
8048740: a3 3c a0 04 08 mov %eax,0x804a03c
8048745: a1 38 a0 04 08 mov 0x804a038,%eax
804874a: 83 c0 01 add $0x1,%eax
804874d: a3 38 a0 04 08 mov %eax,0x804a038
8048752: 8b 0d 38 a0 04 08 mov 0x804a038,%ecx
dynamic:
080485a0 <cal@plt>:
80485a0: ff 25 2c a0 04 08 jmp *0x804a02c
80485a6: 68 40 00 00 00 push $0x40
80485ab: e9 60 ff ff ff jmp 8048510 <_init+0x2c>
靜態庫和動態庫對代碼的要求
二者共同點是若是須要對多線程代碼的支持,代碼裏不能出現全局變量和動態變量和靜態變量(函數內部和外部的),由於它們最後都是放在.bss或者.data段,而同進程的不一樣線程間共享同一個數據段,某個線程調用使用那些變量函數後,後面的調用函數看到就是改變的值。多線程
靜態庫和動態庫對內存的影響
靜態程序佔用內存較多,動態程序反之。由於動態程序是在執行時鏈接,添加被調用的動態函數的地址到.got.plt(process link table)中去。
ide