Linux C編程初探

之前一直都是在Windows下享受IDE帶來的各種便利苗沧,但對(duì)于程序到底是怎么從源代碼變成可執(zhí)行文件的刊棕,一直不甚明了。聽了舒大師的Linux入門課后待逞,研究一下在Linux下如何進(jìn)行C語言程序開發(fā)甥角。
主要從三個(gè)方面來展開:

  • GCC的基本使用
  • 靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)的編譯和鏈接
  • Makefile的編寫

1. 任務(wù)概述

為了涵蓋前面提出的三個(gè)主題,設(shè)置了如下的任務(wù):
在4個(gè)c文件中分別實(shí)現(xiàn)4個(gè)函數(shù)识樱,將其中兩個(gè)文件編譯為靜態(tài)鏈接庫(kù)嗤无,另兩個(gè)文件編譯為動(dòng)態(tài)鏈接庫(kù),最后在主程序中分別調(diào)用這4個(gè)函數(shù)進(jìn)行輸出怜庸。
文件目錄定義:

./bin    //生成的可執(zhí)行文件
./inc    //頭文件
  func.h
./lib    //生成的庫(kù)文件
./obj    //中間目標(biāo)文件
./src    //源文件
  func_d1.c
  func_d2.c
  func_s1.c
  func_s2.c
  main.c
Makefile

2. GCC基本使用

不考慮庫(kù)文件和makefile的使用当犯,直接用GCC進(jìn)行編譯。
生成中間目標(biāo)文件

$ gcc -c src/func_d1.c
$ gcc -c src/func_d2.c
$ gcc -c src/func_s1.c
$ gcc -c src/func_s2.c
$ gcc -c src/main.c -I inc

鏈接文件

$ gcc -o main func_d1.o func_d2.o func_s1.o func_s2.o main.o

結(jié)果測(cè)試

$ ./main

結(jié)果輸出

hello world!
Using the static library.
Input number is: 1.
Using the dynamic library.
Input string is: hello.

當(dāng)然割疾,這里還并沒有static library和dynamic library什么事嚎卫,只是單純地輸出一些字符串而已。

3. 靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)

先刪除之前生成的可執(zhí)行文件杈曲,重新采用庫(kù)文件的方式來實(shí)現(xiàn)驰凛。

$ rm main

3.1 靜態(tài)鏈接庫(kù)

func_s1.cfunc_s2.c這兩個(gè)文件編譯為靜態(tài)鏈接庫(kù),生成libfunc_s.a担扑。

$ ar rc libfunc_s.a func_s1.o func_s2.o

3.2 動(dòng)態(tài)鏈接庫(kù)

func_d1.cfunc_d2.c這兩個(gè)文件編譯為動(dòng)態(tài)鏈接庫(kù)恰响,生成libfunc_d.so
其中涌献,需要以-fpic方式胚宦,重新編譯func_d1.ofunc_d2.o,使其適應(yīng)共享庫(kù)的調(diào)用方式燕垃。

$ gcc -c -fpic src/func_d1.c src/func_d2.c
$ gcc -shared func_d1.o func_d2.o -o libfunc_d.so

3.3 程序調(diào)用

同時(shí)調(diào)用這兩個(gè)庫(kù)文件枢劝,生成最終的可執(zhí)行文件。

gcc src/main.c -I inc -L . -lfunc_s -Wl,-rpath lib -lfunc_d -o main

執(zhí)行生成的main文件卜壕,結(jié)果與剛才相同您旁,但此時(shí)才是真正地分別通過靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)的方式來實(shí)現(xiàn)函數(shù)調(diào)用的。

4. Makefile編寫

通過編寫Makefile文件轴捎,可以實(shí)現(xiàn)程序的自動(dòng)化編譯和鏈接鹤盒,并且對(duì)于大型的程序蚕脏,能夠?qū)⑽募M織得更加合理和有序。
Makefile文件如下所示:

SHELL = /bin/bash
CC = gcc
AR = ar rc
RM = rm -rf
MV = mv
MK = mkdir -p

INC_DIR = ./inc/
SRC_DIR = ./src/
OBJ_DIR = ./obj/
LIB_DIR = ./lib/
BIN_DIR = ./bin/

BIN_FILE = $(BIN_DIR)main
INC = $(INC_DIR)func.h
SRC_M = $(SRC_DIR)main.c
SRC_S = $(SRC_DIR)func_s1.c $(SRC_DIR)func_s2.c
SRC_D = $(SRC_DIR)func_d1.c $(SRC_DIR)func_d2.c
OBJ_M = main.o
OBJ_S = func_s1.o func_s2.o
OBJ_D = func_d1.o func_d2.o
LIB_S = $(LIB_DIR)libfunc_s.a
LIB_D = $(LIB_DIR)libfunc_d.so

all: init $(LIB_S) $(LIB_D) $(BIN_FILE)

init:
    $(MK) $(OBJ_DIR)
    $(MK) $(LIB_DIR)
    $(MK) $(BIN_DIR)

$(LIB_S): $(OBJ_S)
    $(AR) $(LIB_S) $(OBJ_S)
    $(MV) $(OBJ_S) $(OBJ_DIR)

$(OBJ_S): $(SRC_S)
    $(CC) -c $(SRC_S)
    
$(LIB_D): $(OBJ_D)
    $(CC) -shared $(OBJ_D) -o $(LIB_D)
    $(MV) $(OBJ_D) $(OBJ_DIR)

$(OBJ_D): $(SRC_D)
    $(CC) -c -fpic $(SRC_D)

$(BIN_FILE): $(OBJ_M)
    $(CC) $(OBJ_M) $(LIB_S) $(LIB_D) -o $(BIN_FILE)
    $(MV) $(OBJ_M) $(OBJ_DIR)
    
$(OBJ_M): $(SRC_M)
    $(CC) -c $(SRC_M) -I $(INC_DIR) -o $(OBJ_M)

clean:
    $(RM) $(OBJ_DIR) $(LIB_DIR) $(BIN_DIR)
    $(RM) *.o

其中:

  • 執(zhí)行make clean命令清除之前的編譯結(jié)果侦锯。
  • 執(zhí)行make命令進(jìn)行整個(gè)程序的編譯鏈接驼鞭。

結(jié)果測(cè)試

$ bin/main

最終輸出結(jié)果也和預(yù)想的一致。
至此尺碰,已經(jīng)打通了在Linux下進(jìn)行C語言程序開發(fā)的必要路徑挣棕。

5. 附程序源文件

main.c

#include <stdio.h>
#include "func.h"

void main(void)
{
    printf("hello world!\n");
    func_s1();
    func_s2(1);
    func_d1();
    func_d2("hello");
    
    return;
}

func.h

void func_s1(void);
void func_s2(int a);
void func_d1(void);
void func_d2(char *s);

func_s1.c

#include <stdio.h>

void func_s1(void)
{
    printf("Using the static library.\n");
    return;
}

func_s2.c

#include <stdio.h>

void func_s2(int a)
{
    printf("Input number is: %d.\n", a);
    return;
}

func_d1.c

#include <stdio.h>

void func_d1(void)
{
    printf("Using the dynamic library.\n");
    return;
}

func_d2.c

#include <stdio.h>

void func_d2(char *s)
{
    printf("Input string is: %s.\n", s);
    return;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市亲桥,隨后出現(xiàn)的幾起案子洛心,更是在濱河造成了極大的恐慌,老刑警劉巖题篷,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件皂甘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡悼凑,警方通過查閱死者的電腦和手機(jī)偿枕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來户辫,“玉大人渐夸,你說我怎么就攤上這事∮婊叮” “怎么了墓塌?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)奥额。 經(jīng)常有香客問我苫幢,道長(zhǎng),這世上最難降的妖魔是什么垫挨? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任韩肝,我火速辦了婚禮,結(jié)果婚禮上九榔,老公的妹妹穿的比我還像新娘哀峻。我一直安慰自己,他們只是感情好哲泊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布剩蟀。 她就那樣靜靜地躺著,像睡著了一般切威。 火紅的嫁衣襯著肌膚如雪育特。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天先朦,我揣著相機(jī)與錄音缰冤,去河邊找鬼槽袄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛锋谐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播截酷,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼涮拗,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了迂苛?” 一聲冷哼從身側(cè)響起三热,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎三幻,沒想到半個(gè)月后就漾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡念搬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年抑堡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朗徊。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡首妖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爷恳,到底是詐尸還是另有隱情有缆,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布温亲,位于F島的核電站棚壁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏栈虚。R本人自食惡果不足惜袖外,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望魂务。 院中可真熱鬧在刺,春花似錦、人聲如沸头镊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽相艇。三九已至颖杏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坛芽,已是汗流浹背留储。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工翼抠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人获讳。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓阴颖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親丐膝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子量愧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容