閱讀860 返回首頁    go 阿裏雲 go 技術社區[雲棲]


UNIX/Linux C 程序員需要掌握的七種武器

我是一名普通的軟件工程師,不是什麼技術大牛。這篇文章所提到的“七種武器”隻是我這些年工作經驗的一點體會和感悟,如果有錯誤的地方,還請大家指正。

(一)C語言

作為一名C程序員,熟練掌握C語言是最基本的一項技能。關於如何學好C語言,以及C語言話題的討論,網上有很多經典的文章,我就不一一列舉了。在這裏,我隻想談一點我個人的體會:剛畢業時,我來到一家比較大的軟件公司工作,而公司的工作模式是每個人隻負責一個小模塊。這樣工作兩年後,我自認為我的C語言水平已經很高了。後來,我來到現在這家公司。由於工作需要,接觸的東西也多了,開源項目也了解一些,才發現自己的C語言能力太一般了:原來宏可以這樣寫,指針可以這樣用…等等。現在我在寫代碼時,常常會想:這個行為是C語言規範定義的嗎?如果是,是C89還是C99?我現在用的編譯器支持嗎?如果不是C語言規範定義的,那麼在程序運行的這個平台,行為是確定的嗎?所以我建議大家平時可以多想想這些問題,查查資料,相信一定會對C語言有更深的理解。

(二)UNIX/Linux係統編程

在UNIX/Linux係統上開發程序,掌握係統編程API是必不可少的技能。而這方麵的經典書籍都是一些大部頭的英文著作,讓人望而生畏。在這裏,我談一點自己的建議:我覺得可以先找一本口碑不錯的中文書先看一下,了解一下都有哪些種類的API。這樣以後用到時,再去精讀經典英文著作裏的相關章節,或是查man手冊。此外,我覺得如果有時間,可以學習一下經典的開源項目,了解這些開源項目是如何使用這些API的。舉個例子,Redis是很多人推薦的一個很不錯的學習C語言的開源項目。我在閱讀代碼時,看到保存數據到文件時會用到fsync函數,我就會去深入地了解一下這個函數的作用。這樣比單純地去看那些著作效果要好。

(三)網絡編程及相關知識

關於網絡方麵,我想從以下三點分享一下我的體會:

a)網絡協議。在日常的工作中,大家接觸和使用最多的無疑是TCP/IP協議族。此外,由於工作領域不同,也可能用到其它的協議。比方說,我主要做電信相關的程序開發,平時可能接觸SCTP協議會更多一些。對於這些協議,我覺得掌握最基本的知識是必須的,其它的邊邊角角知識可以等到用時再查。舉例來說,TCP協議的“三次握手”,“四次揮手”,“TIME-WAIT狀態”這些基本的知識點要弄明白,其它的邊角知識學完老不用忘得也快,還是用時google一下效率更高。

b)Socket編程。Socket編程的經典書籍一點不比講係統編程的書薄,所以可以選一本相對薄點,口碑不錯的精讀一下,這樣基本就掌握的百分之五、六十了。另外有時間還是看一下經典的開源代碼。這裏還拿Redis舉例,Redis裏關於處理網絡連接和通信的代碼量不大,而且基本涵蓋了所有常見的UNIX平台,看完以後一定受益匪淺。

c)協議分析工具。TCPdump、snoop(Solaris平台工具)、wireshark等這些工具不僅能幫助我們抓取數據包,還能分析數據包,這對debug網絡程序有非常大的幫助。所以,我們至少要掌握這些工具最常用的功能。此外,對於開放源代碼的工具,我們更是可以從代碼中學到很多知識。舉例來說,我做短信相關的項目,就從wireshark的分析短信協議的代碼裏學到了很多東西,這使我對短信協議有了更清晰的理解。

(四)腳本編程能力

一提到腳本編程,大家首先想到的可能就是Bash shell腳本編程了。不錯,在Unix/Linux上,Bash shell也許就是用的最廣泛的腳本編程語言。我平時主要用Bash shell做兩個方麵的工作:a)用於編寫監控服務腳本;b)寫一些簡單的單元測試腳本,比如循環發一些命令,等等。但是Bash shell的功能遠遠要比這些強大。我見過一些高手用Bash shell編程語言寫出了很好玩的遊戲,也有人做出了很cool的網絡應用。所以建議大家有興趣可以多了解一下Unix/Linux的這層“殼”。當然,你也可以選擇學習Python、Perl、Ruby等。不過相比這些語言,Bash shell至少你不用自己去安裝,而且它能做的事同樣很強大。

(五)操作係統及CPU體係結構

也許有一天,你會碰到這樣的情景:你的程序在Solaris上會發生core dump,在Linux上卻運行的好好的。經過一番艱苦的debug,最後得到的原因是兩種操作係統對線程的調度策略不一樣,這會使一個對全局變量沒有加鎖就訪問的bug在Linux上很難出現。所以你需要盡可能地去了解你使用的操作係統,這樣無論對寫程序還是debug都會有很大的幫助。比如,你需要了解進程的內存布局,這樣你就知道棧和堆到底在內存的哪段空間,為什麼內存寫越界有時會core dump,有時沒事。

除了操作係統,了解CPU的體係結構也是一門必修課。比方說,SPARC CPU要求字節對齊,而X86 CPU則沒有這個要求。又比如SPARC CPU是大端模式,而X86 CPU是小端模式,這就要求你對像位域這樣的定義要格外小心。你還要了解你使用的CPU的匯編語言,至少能大概看懂。因為有些時候,當你從C代碼中找不出bug的原因時,就需要你“透過現象看本質”,從匯編代碼層麵看看到底發生了什麼。

(六)編譯器和調試器

“工欲善其事,必先利其器”。編譯器負責把源代碼生成可執行文件,而調試器則是在程序出現bug時,用來“降妖除魔”的不二神器。我會以我最熟悉的gcc和gdb為例子,來談一下個人體會。

gcc有很多編譯選項,除了要熟悉像-O,-g這些最基本的選項,我建議大家可以多了解一些其它不常見的選項。因為這些選項很可能幫助我們找到程序的一些bug。舉個例子,在比較新的gcc版本裏,增加了-fstack-protector這個選項,而它可以幫助我們檢查到緩衝區溢出這種bug。此外,你還可能碰到這種情況,一個bug總是發生在程序優化後的版本,而不會出現在沒經過優化的版本。所以,多了解你的編譯器,你就可以更好地了解你的程序是如何生成的。

一個程序員不可能不碰到bug,而這個時候,調試器就是最好的工具。可以說,在遇到bug時調試技巧和手段是否豐富是衡量一個程序員的能力和水平的重要參考。除此以外,gdb另一個重要用途就是分析程序的core dump文件。我個人很喜歡看破案和推理的電視節目。我覺得程序的core dump文件可以比作“犯罪現場”,而gdb就是公安人員用來在現場提取線索的工具。對gdb越熟悉,就越能從core dump文件提取有價值的信息,也就越有助於我們定位到程序bug的“root cause”。

(七)DTrace/SystemTap

DTrace是由Sun的幾位才華橫溢的工程師開發的,最開始隻支持Solaris操作係統,現在FreeBSD和Mac OS X也都支持了。Linux上類似的工具有SystemTap,也有人把DTrace移植到Linux上,不過效果似乎並不好。簡單地說,DTrace可以幾乎不會在對整個係統有任何性能影響下,讓你了解你的程序所發生的一切。這對分析程序的熱點(“Hot spot”),了解程序的執行流程,定位程序bug都有很大的幫助。有些時候,DTrace可能是你唯一的工具。舉例來說,有個程序隻發生在生產環境,而在實驗室環境無法複現(當然,理論上任何bug都可以複現,隻是我們沒有找到複現條件。)。你不可能在你懷疑的代碼打上斷點,然後用gdb去調試。這時你隻能借助於DTrace,通過它去了解程序到底是如何運行的,當時的變量值是什麼。此外,DTrace還可以幫你了解操作係統的kernel,這會滿足很多geek的好奇心。

以上就是我總結的UNIX/Linux C 程序員需要掌握的“七種武器”,同時也很感謝你能耐心地讀完這篇文章。如果這篇小文沒有讓你覺得浪費時間,而是對你有哪怕一點小小的幫助,我的目的也就達到了。如果你有一些好的觀點,也非常歡迎你能分享出來。謝謝!

最後更新:2017-05-24 09:31:40

  上一篇:go  Maven入門指南(二)
  下一篇:go  無人駕駛的分級以及產品化後會帶來的改善