2.22.2016

Linux 函式庫 (Library)

這一次自己要記錄的是Linux下一個簡單的Library (函式庫)概念....

函式庫的概念很簡單,當我們在寫程式時,會呼叫到許多函式 (Function),但這些函式是怎麼運作的,我們並不想讓他人知道。譬如說,有一些系統廠在Release SDK的時後,一些驅動程式的程式碼,並不會完整的Release出來,就會以函式庫的方式來做Release。

函式庫分為兩種型態,一種是靜態函式庫,附檔名為*.a (archives),相當於Windows下的*.lib (Libraries)

另一種則是動態函式庫 (或稱為共享函式庫),附檔名為*.so (shared object),相當於Windows下的*.dll (Dynamic-Link Libraries)

靜態函式庫的缺點是,當我們在同一個時間執行很多的程序,他們都使用靜態函式庫中的相同函式,就會造成相同函數的程式碼重複佔用記憶體的狀況。事實上,在每個程式檔案中,也都複製了相同的函數程式碼。如此,同時浪費了許多記憶體和磁碟空間。

但,當一個程式引用動態函式庫的函數時,連結後的程序碼,並不會含蓋所呼叫的函數程式碼。直到程序被載入到記憶體執行時,才會去解決動態函式庫的函數和呼叫問題,就是在執行階段才將需要的部份載入記憶體。

所以,系統只需要準備一份動態函式庫,一次提供給眾多的應用程序,並且只佔用一份磁碟空間。

好,自己寫一個很簡單的範例,來記錄Linux下如何產生一個函式庫檔案:

需求非常簡單,我要寫2支函式─hello()和world(),在主程式 (main())中呼叫這兩支函數時,會直接秀出「Hello!! World!! 」,所以總共會有6個檔案,除了Makefile之外,其餘的檔案都非長地精簡:

Makefile:
#
#    File Name: Makefile
#
#    CopyLeft (C) 2016; All rights reserved.
#
#    Author: Pablo Picasso G. (PabloPicasso.G@gmail.com)
#
#    Version: 0.0.1.build022216
#
#    Date: 2016 / 02 / 22
#
#    Description: 
#    1. This make file will include six files (*.c and *.h), 
#       and it'll show "Hello!! World!! "
#    2. 
#

GCC := gcc
CFLAGS := -c -g -DDEBUG
OBJS := main.o hello.o world.o
EXEC := main
RM := rm -rf
LIBS := libmain.a
AR := ar -crv

.PHONY: all
all: $(EXEC)

$(EXEC): main.o libmain.a
    @-$(GCC) -o $(EXEC) main.o -L./ -lmain

$(LIBS): hello.o world.o
    @-$(AR) $(LIBS) hello.o world.o

$(OBJS): %.o: %.c
    @-$(GCC) $(CFLAGS) $< -o $@

.PHONY: clean cleanall install print tar dist TAGS check test
clean:
    @-$(RM) *.o

cleanall: clean
    @-$(RM) $(LIBS) $(EXEC)

install:

print:

tar:

dist:

TAGS:

check: 

test:

hello.h:
#ifndef _HELLO_H_
#define _HELLO_H_

#include <stdio.h>

void hello();

#endif

hello.c:
#include "hello.h"

void 
hello()
{
    printf("Hello!! \n");

    return;
}

world.h:
#ifndef _WORLD_H_
#define _WORLD_H_

#include <stdio.h>

void world();

#endif

world.c:
#include "world.h"

void 
world()
{
    printf("World!! \n");

    return;
}

main.c:
#include "hello.h"
#include "world.h"

int 
main()
{
    hello();
    world();

    return 0;
}

執行Makefile之后,就會產生main執行檔;也不難看出要產生函式庫檔案,就是透過ar -crv指令把hello.o和world.o壓成libmain.a檔案。

沒有留言:

張貼留言