原本是搜pthread的相關資料,看blog發現不少linux程序員都看的一本神書《APUE》,裏面有系統的兩章內容專門講pthread(不過是用c語言作的代碼示例,這個不礙事,仍是歸到原來linux c++分類中了),決定把這本書打印出來,過一下這兩章內容。這個系列後面的日誌會根據APUE書中的內容來。html
這篇日誌說的內容與APUE沒有直接關係,可是倒是由APUE引起的。python
背景是這樣的:linux
(1)對於我這個只在windows下用vs等IDE寫過一些c程序,不知道gcc是幹啥的人來講,在unix下搞c就有困難(這個感受有點兒相似於只學過開自動擋的汽車,一會兒讓你開手動擋了)。c++
(2)上來APUE的第一個demo就不能編譯經過,由於APUE的全部demo代碼中都包含一行include 「apue.h」。翻開/apue/include/apue.h看了一眼:都是一些宏定義和函數聲明,一些函數的具體實現都在/apue/lib/中了。這些東西怎麼整合起來?之前在windows下好像都是用IDE創建一個工程,剩下的都是IDE給作好了。可是如今用的mac,未來在公司要用的是Linux,學會在linux下開發c c++的工程項目是遲早的事情,躲不開。程序員
(3)若是是python這種腳本語言,只要有python解釋器就OK了;可是c語言這種強類型的語言的源代碼是如何變成可執行的二進制文件的?這個問題我也說不清楚。(非計算機科班出身,沒學過編譯原理)shell
上面的三個問題,恐怕也是不少只在win下開發過程序的人遇到的問題,而我就是其中一員。下面記錄下解決上面困難的過程。macos
記錄一下遇到的各類問題,經過查閱資料和推理一點兒點兒摸索着解決了(純本身記錄,非小白可直接忽略,不敢浪費你們時間):ubuntu
(一)gcc -I(搞清楚include "...")windows
原書的demo中 第一行是include "apue.h",但本身意識到「apue.h」不在當前路徑下,應該把apue.h所在的路徑完整寫出來。 因而照貓畫虎的代碼以下:編輯器
#include "../apue.3e/include/apue.h" #include <pthread.h> void * thr_fn1(void *arg) { printf(("thread 1 returning\n")); return ((void *)1); } void * thr_fn2(void *arg) { printf(("thread 2 exiting")); pthread_exit((void *)2); } int main(int argc, char const *argv[]) { int err; pthread_t tid1, tid2; void *tret; err = pthread_create(&tid1, NULL, thr_fn1, NULL); err_exit(err, "can't"); return 0; }
但立刻以爲上述的代碼有問題:若是apue.h的路徑改了,那豈不是全部源代碼中的include 「apue.h」都要跟着改?這樣確定不科學。
因而查閱了一下gcc命令(http://blog.sina.com.cn/s/blog_57295811010008pj.html),知道了-I這個選項,能夠把include "..."包含的文件路徑放在-I後面。因而作了以下修改:
#include "apue.h"
並執行命令:gcc -I../apue.3e/include 11.3.c -pthread
獲得了以下結果:
報錯的內容就是說err_exit()這個函數找不到吧(這個時候不知道ld是什麼意思,linker是啥也不知道)
因而推理一下:多是隻有apue.h頭文件,gcc的過程當中沒有找到實際函數實現吧。
去翻翻發現apue.h中有一句話:
void err_exit(int, const char *, ...) __attribute__((noreturn));
這就是一句函數聲明。
那麼函數實體在哪裏呢?到這裏有點兒瞎,由於原書給的文件很大,那麼多的文件上哪找err_exit呢?
即便找到的err_exit()的函數定義,又怎麼讓包含err_exit()函數定義的這個文件與demo文件合在一塊兒呢?線索斷了。
(二)make命令以及Makefile (在unix下本身完成win下IDE完成的事情)
接着(一),瞎查了半天沒有什麼結果,糾結了一下子。
一個偶然的想法讓我在解決問題的路上去學了下make以及Makefile。
因爲書上的demo畢竟是在ubuntu上運行的,而個人電腦是mac系統,雖然說都是unix,可是會不會是個人系統有問題或者gcc版本這類的問題致使不能編譯經過呢?因而,我就想試試,能不能在APUE提供的源代碼目錄下編譯經過呢?
這時候,我找到了APUE提供的源碼文件夾中的Makefile文件,以下:
ROOT=.. EXTRALIBS=-pthread PLATFORM=$(shell $(ROOT)/systype.sh) include $(ROOT)/Make.defines.$(PLATFORM) BAR = ifeq "$(PLATFORM)" "macos" TLOCK = EXTRALIBS=-pthread else TLOCK = timedlock endif ifeq "$(PLATFORM)" "linux" BAR = barrier EXTRALIBS=-pthread -lrt -lbsd endif ifeq "$(PLATFORM)" "freebsd" BAR = barrier EXTRALIBS=-pthread endif ifeq "$(PLATFORM)" "solaris" BAR = barrier EXTRALIBS=-lpthread -lrt endif PROGS = badexit2 cleanup exitstatus threadid all: $(PROGS) condvar.o maketimeout.o mutex1.o mutex2.o mutex3.o rwlock.o $(TLOCK) $(BAR) $(PROGS): $(LIBAPUE) $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) clean: rm -f $(PROGS) $(TEMPFILES) *.o $(TLOCK) $(BAR) include $(ROOT)/Make.libapue.inc
以前據說過,Makefile貌似是告訴系統去怎麼編譯源代碼這類的。因而,上網搜了以下的資料,對make和Makefile進行了下突擊:
gcc -ansi -I../include -Wall -DMACOS -D_DARWIN_C_SOURCE threadid.c -o threadid -L../lib -lapue -pthread
本身運行的命令照比make執行的命令主要少了紅字的那一塊。原來,是-L -l告訴了gcc,函數err_exit()的具體實如今哪裏的啊。
==================================================
插播:忽然想起來本身買過一本書《程序員的自我修養》,裏面講了編譯、連接什麼的。
因而趕忙讀了讀,搞清楚點兒。也是在那本書中,知道了「連接」是一個很重要的過程,把
不一樣模塊拼在一塊兒組成最後的完整的程序。
插播結束。
==================================================
-l後面接的「apue」應該是庫文件的名字(linux靜態庫文件通常以libXXX.a的形式,XXX就是-l後面跟着的名字),因而天然就想看看這個apue庫文件的樣子
(四)sublime的陷阱 (有些格式的文件,sublime不顯示)
先找了下原書提供的代碼文件中的lib文件夾;果真,找到了err_exit()函數的實現文件:error.c
你們能夠看到,本人用的編輯器是sublime text2。爲何要提一下這個編輯器?後面立刻說,如何被編輯器的設置給坑了。
看看sublime左側邊欄中,lib文件夾下也沒有這樣的文件啊,難倒還有其餘的坑麼?到這裏又有些糾結了
(1)如今源文件所在目錄已經找到了
(2)也知道-L把外部的庫文件路徑告訴gcc,-l告訴gcc應該具體用哪一個庫文件了
因而我在網上搜了一下(如這篇blog,http://www.cnblogs.com/showna/articles/1013399.html),庫文件確實都是lib開頭,.a .dylib結尾的這類啊。難倒庫文件在lib文件夾中丟了?仍是有其餘的說道?。
正在鬱悶的時候,用iTerm命令行進入了lib文件夾下面,忽然展示了驚人的一幕:
喵了個咪的,這個apue庫文件.a、編譯後的目標文件.o都有啊!原來只是sublime的左邊欄中沒有這些.o和.a文件啊。
因而,知道被sublime給坑了。很快上網搜到了緣由,在sublime的Preferences選中中有以下的幾行默認配置:
在sublime默認中,.a .o .lib這些擴展名的文件都不顯示啊!!!
到了這裏,終於把這一系列問題搞清楚了(這個過程大概持續了一白天),總結下緣由:
(1)對編輯器特性不熟悉(不知道有些文件還自動過濾了不顯示),這個只能靠實踐去磨了
(2)對於程序由源代碼到可執行文件的原理不瞭解。之前在windows平臺不少事情都VS作了,用Eclipse寫Java就更省事兒了;如今須要本身寫Makefile去作,就要把每一個環節都搞清楚。這個光靠實踐不行,還得去系統的學學,好比《程序員的自我修養》這本書就是很是好的內容。遂決定讀。