Linux C++ 服务器端这条线怎么走?一年半能做出什么?
您好,我現在大三了,請問我想往 Linux C++ 服務器方向發展該怎么走,比如現在在看 Linux 程序設計,還應該在看哪些書,可以完成一些什么項目?謝謝。
有 C++、C 基礎,算法數據結構還不錯。 添加評論? 分享 按投票排序按時間排序
22 個回答
2453贊同 反對,不會顯示你的姓名 陳碩,Linux C++程序員,muduo 網絡庫作者 枯葉未凋零、張可愛、知乎用戶?等人贊同既然你是在校學生,而且編程語言和數據結構的基礎還不錯,我認為應該在《操作系統》和《計算機體系結構》這兩門課上下功夫,然后才去讀編程方面的 APUE、UNP 等書。
下面簡單談談我對學習這兩門課的看法和建議,都是站在服務端程序員的角度,從實用主義(pragmatic)的立場出發而言的。
學習操作系統的目的,不是讓你去發明自己操作系統內核,打敗 Linux;也不是成為內核開發人員;而是理解操作系統為用戶態進程提供了怎樣的運行環境,作為程序員應該如何才能充分利用好這個環境,哪些做法是有益的,哪些是做無用功,哪些則是幫倒忙。
學習計算機體系結構的目的,不是讓你去設計自己的 CPU(新的 ISA 或微架構),打敗 Intel 和 ARM;也不是參與到 CPU 設計團隊,改進現有的微架構;而是明白現代的處理器的能力與特性(例如流水線、多發射、分支預測、亂序執行等等指令級并行手段,內存局部性與 cache,多處理器的內存模型、能見度、重排序等等),在編程的時候通過適當組織代碼和數據來發揮 CPU 的效能,避免 pitfalls。Modern Microprocessors
這兩門課程該如何學?看哪些書?這里我告訴你一個通用的辦法,去美國計算機系排名靠前的大學的課程主頁,找到這兩門課最近幾年的課程大綱、講義、參考書目、閱讀材料、隨堂練習、課后作業、編程實驗、期末項目等,然后你就心里有數了。
學習任何一門課程都要善于抓住主要矛盾、分清主次、突出重點,關鍵是掌握知識框架,學會以后真正有用的知識和技能,而不要把精力平均分配在一些瑣事上。
請允許我再次引用孟巖的觀點:http://blog.csdn.net/myan/article/details/5877305
我(孟巖)主張,在具備基礎之后,學習任何新東西,都要抓住主線,突出重點。對于關鍵理論的學習,要集中精力,速戰速決。而旁枝末節和非本質性的知識內容,完全可以留給實踐去零敲碎打。
原因是這樣的,任何一個高級的知識內容,其中都只有一小部分是有思想創新、有重大影響的,而其它很多東西都是瑣碎的、非本質的。因此,集中學習時必須把握住真正重要那部分,把其它東西留給實踐。對于重點知識,只有集中學習其理論,才能確保體系性、連貫性、正確性,而對于那些旁枝末節,只有邊干邊學能夠讓你了解它們的真實價值是大是小,才能讓你留下更生動的印象。如果你把精力用錯了地方,比如用集中大塊的時間來學習那些本來只需要查查手冊就可以明白的小技巧,而對于真正重要的、思想性東西放在平時零敲碎打,那么肯定是事倍功半,甚至適得其反。
因此我對于市面上絕大部分開發類圖書都不滿——它們基本上都是面向知識體系本身的,而不是面向讀者的。總是把相關的所有知識細節都放在一堆,然后一堆一堆攢起來變成一本書。反映在內容上,就是毫無重點地平鋪直敘,不分輕重地陳述細節,往往在第三章以前就用無聊的細節謀殺了讀者的熱情。
比如說操作系統,應該把精力主要放在進程管理與調度、內存管理、并發編程與同步、高效的IO等等,而不要過于投入到初始化(從 BIOS 加載引導扇區、設置 GDT、進入保護模式)這種一次性任務上。我發現國內講 Linux 內核的書往往把初始化的細節放在前幾章,而國外的書通常放附錄,你可以體會一下。初始化對操作系統本身而言當然是重要的,但是對于在用戶態寫服務程序的人來說,弄清楚為什么要打開 PC 上的 A20 地址線真的有用處嗎?(這不過是個歷史包袱罷了。)
再比方說《計算機網絡》,關鍵之一是理解如何在底層有丟包、重包、亂序的條件下設計出可靠的網絡協議,這不算難。難一點的是這個可靠協議能達到“既能充分利用帶寬,又能做到足夠公平(并發連接大致平均分享帶寬)”。而不是學會手算 CRC32,這更適合放到信息論或別的課程里去講。
注意分清知識的層次。就好比造汽車與開汽車的區別,我認為一個司機的技能主要體現在各種道路條件和天氣狀況下都能安全駕駛(城市道路、高速公路、鄉間公路 X 晴、雨、雪、霧),平安到達目的地。作為一名司機,了解汽車運行的基本原理當然是好事,可以有助于更好地駕駛和排除一些常見故障。但不宜喧賓奪主,只要你不真正從事汽車設計工作,你再怎么研究發動機、傳動、轉向,也不可能比汽車廠的工程師強,畢竟這是人家的全職工作。而且鉆研汽車構造超過一定程度之后,對開好車就沒多大影響了,成了個人興趣愛好。“有的人學著學著成了語言專家,反而忘了自己原本是要解決問題來的。”(語出孟巖?快速掌握一個語言最常用的50%)
對于并發編程來說,掌握 mutex、condition variable 的正確用法,避免誤用(例如防止 busy-waiting 和 data race)、避免性能 pitfalls,是一般服務端程序員應該掌握的知識。而如何實現高效的 mutex 則是 libc 和 kernel 開發者應該關心的事,隨著硬件的發展(CPU 與內存之間互聯方式的改變、核數的增加),最優做法也隨之改變。如果你不能持續跟進這一領域的發展,那么你深入鉆研之后掌握的知識到了幾年之后可能反而成為累贅,當年針對當時硬件的最優特殊做法(好比說定制了自己的 mutex 或 lock-free 數據結構)在幾年后有可能反而會拖低性能。還不如按最清晰的方式寫代碼,利用好語言和庫的現成同步設施,讓編譯器和 libc 的作者去操心“與時俱進”的事。
注意識別過時的知識。比方說《操作系統》講磁盤IO調度往往會講電梯算法,但是現在的磁盤普遍內置了這一功能(NCQ),無需操作系統操心了。如果你在一個比較好的學校,操作系統課程的老師應該能指出這些知識點,避免學生浪費精力;如果你全靠自學,我也沒什么好辦法,盡量用新版的書吧。類似的例子還有《計算機體系結構》中可能會講 RISC CPU 流水線中的 delay slot,現在似乎也都廢棄了。《計算機網絡》中類似的情況也不少,首先是 OSI 七層模型已經被證明是扯淡的,現在國外流行的教材基本都按五層模型來講(Internet protocol suite),如果你的教材還鄭重其事地講 OSI (還描繪成未來的希望),扔了換一本吧。其次,局域網層面,以太網一家獨大(幾乎成了局域網的代名詞),FDDI/Token ring/ATM 基本沒啥公司在用了。就說以太網,現在也用不到 CSMA/CD 機制(因為 10M 的同軸電纜、10M/100M 的 hub 都過時了,交換機也早就普及了),因此碰撞檢測算法要求“以太網的最小幀長大于最大傳播延遲的二倍”這種知識點了解一下就行了。
另外一點是 low level 優化的知識非常容易過時,編碼時要避免過度擬合(overfitting)。比方說目前國內一些教科書(特別是大一第一門編程語言的教程)還在傳授“乘除法比加減法慢、浮點數運算比整數運算慢、位運算最快”這種過時的知識。現代通用 CPU 上的實際情況是整數的加減法和乘法運算幾乎一樣快,整數除法慢很多;浮點數的加減法和乘法運算幾乎和整數一樣快,浮點數除法慢很多。因此用加減法代替乘法(或用位運算代替算術運算)不見得能提速,反而讓代碼難懂。而且現代編譯器可以把除數為小整數的整數除法轉變為乘法來做,無需程序員操心。(目前用浮點數乘法代替浮點數除法似乎還是值得一做的,例如除以10改為乘以0.1,因為浮點運算的特殊性(不滿足結合律和分配率),阻止了編譯器優化。)
類似的 low level 優化過時的例子是早年用匯編語言寫了某流行圖像格式的編解碼器,但隨著 CPU 微架構的發展,其并不比現代 C 語言(可能用上 SIMD)的版本更快,反而因為使用了 32-bit 匯編語言,導致往 64-bit 移植時出現麻煩。如果不能派人持續維護更新這個私有庫,還不如用第三方的庫呢。現在能用匯編語言寫出比 C 語言更快的代碼幾乎只有一種可能:使用 CPU 的面向特定算法的新指令,例如 Intel 的新 CPU (將會)內置了 AES、CRC32、SHA1、SHA256 等算法的指令。不過主流的第三方庫(例如 OpenSSL)肯定會用上這些手段,及時跟進即可,基本無需自己操刀。(再舉一個例子,假如公司早先用匯編語言寫了一個非常高效的大整數運算庫,一直運轉良好,原來寫這個庫的高人也升職或另謀高就了。Intel 在 2013 年發布了新微架構 Haswell,新增了 MULX 指令,可以進一步提高大整數乘法的效率?GMP on Intel Haswell?,那么貴公司是否有人持續跟進這些 CPU 的進化,并及時更新這個大整數運算庫呢?或者直接用開源的 GMP 庫,讓 GMP 的作者去操心這些事情?)
如果你要記住結論,一定要同時記住前提和適用條件。在錯誤的場合使用原本正確的結論的搞笑例子舉不勝舉。
最后一點小建議,服務端開發這幾年已經普及 64-bit 多核硬件平臺,因此在學習操作系統的時候,可以不必太關心單核上特有的做法(在單核時代,內核代碼進入臨界區的辦法之一是關中斷,但到了多核時代,這個做法就行不通了),也不必太花精力在 32-bit 平臺上。特別是 32-bit x86 為了能支持大內存,不得已有很多 work around 的做法(困難在于 32-bit 地址空間不夠將全部物理內存映射入內核),帶來了額外的復雜性,這些做法當時有其積極意義,但現在去深入學似乎不太值得。
關于項目,我出兩個練手題目:
一、多機數據處理。有 10 臺機器,每臺機器上保存著 10 億個 64-bit 整數(不一定剛好 10 億個,可能有上下幾千萬的浮動),一共約 100 億個整數(其實一共也就 80GB 數據,不算大,選這個量級是考慮了 VPS 虛擬機的容量,便于實驗)。編程求出:
1. 這些數的平均數。
2. 這些數的中位數。
3. 出現次數最多的 100 萬個數。
*4. (附加題)對這 100 億個整數排序,結果順序存放到這 10 臺機器上。
*5. (附加健壯性要求)你的程序應該能正確應對輸入數據的各種分布(均勻、正態、Zipf)。
*6. (附加伸縮性要求)你的程序應該能平滑擴展到更多的機器,支持更大的數據量。比如 20 臺機器、一共 200 億個整數,或者 50 臺機器、一共 500 億個整數。
二、N-皇后問題的多機并行求解。利用多臺機器求出 N-皇后問題有多少個解。(注意目前的世界紀錄是 N = 26,A000170 - OEIS?)
1. 8 皇后問題在單機上的運算時間是毫秒級,有 92 個解,編程實現之。
2. 研究 N-皇后問題的并行算法,寫一個單機多線程程序,爭取達到線性加速比(以 CPU 核數計)。再設法將算法擴展到多機并行。
3. 用 10 臺 8 核的機器(一共 80 個 CPU cores),求解 19-皇后和 20-皇后問題,看看分別需要多少運行時間。你的方案能否平滑擴展到更多的機器?
*4. (附加題)如果這 10 臺機器的型號不一,有 8 核也有 16 核,有舊 CPU 也有更快的新 CPU,你該采用何種負載均衡策略,以求縮短求解問題的時間(至少比 plain round-robin 算法要好)?
你可以用 Amazon EC2 或 Google GCE 來驗證你的程序的正確性和性能,這兩家的虛擬機都是按小時(甚至更短)收費,開 10 臺虛擬機做一個下午的實驗也花不了多少錢。
編輯于 2014-09-21?70 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 37贊同 反對,不會顯示你的姓名 知乎用戶,挨踢人士 Chow Anod、楊海坡、知乎用戶?等人贊同 hi,我快畢業了,和你一樣,我之前也對自己是這么定位的。根據你的情況,已經有了良好的計算機基本素質,接下來的工作會好做很多。
你可以先試著看UNIX環境高級編程 (豆瓣)和UNIX網絡編程 (豆瓣),通過這兩本書能讓你對linux 下的服務器編程有一定的了解和認知。讀這兩本書最好有良好的操作系統和計算機網絡基礎,所以再推薦兩本書:TCP/IP詳解 卷1:協議 (豆瓣)和深入理解計算機系統(原書第2版) (豆瓣)。
記得,看書的過程中別只用眼睛,要去實踐。
接著,你可以去使用并看一些小巧而又精彩的開源工具的源代碼,譬如 libevent 或者 memcached。這些都是開源的,而且資料也有很多。看這些東西,能讓你學到很多。
一年半還很長,希望你能夠耐住寂寞,在技術上有所沉淀。 編輯于 2014-01-27?1 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 4贊同 反對,不會顯示你的姓名 羅然,大風吹散夢想 qingliudao、萬盛中路搖滾樂隊、毈錯誤?等人贊同 一年半的時間我不認為你能達到樓上那些人說的地步。總之先定好方向,網絡服務端也有好多路線的,是走webserver還是游戲通信后端,rpc,流媒體還是下載器。任何一個方向不專注3年,談不上有何建樹 發布于 2014-09-18?添加評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 6贊同 反對,不會顯示你的姓名 邰原朗,https://github.com/grizzlybears Raymondp7z9f3、知乎用戶、拙而不群?等人贊同 不停地與崩潰泄漏搏斗,
直到
于萬行代碼中,找出越界/泄漏點,如同探囊取物。 發布于 2014-09-19?添加評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 22贊同 反對,不會顯示你的姓名 沈文,刪你評論只因你太low 楊原、你龍哥哥、Zhen Su?等人贊同 建議:找點項目做 千萬別聽樓上的死啃大部頭。項目做到一定程度 你就知道該看些什么了 發布于 2014-07-27?8 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 58贊同 反對,不會顯示你的姓名 余鋒,阿里云數據庫工程師 linuxsever、知乎用戶、林炳辰?等人贊同 看書容易迷失,從成熟的工程開始如nginx, 看不懂的地方從書中找答案,會學的很快。 發布于 2014-01-27?10 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 10贊同 反對,不會顯示你的姓名 馬達 lakeone huang、當我遇上你、康雨揚?等人贊同 在學校,一定要把基礎打牢:操作系統,數據結構和網絡基礎。項目經驗在以后的工作中會很快跟上,這時候就看誰的基礎好,誰就走的遠。如果基礎不好,別人已經學以至用,你還是補基礎課;差距很明顯。 發布于 2014-01-27?1 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 12贊同 反對,不會顯示你的姓名 Zhu Alejandro,慢悠悠的會寫一點代碼的小樹懶 Chow Anod、tobegod、知乎用戶?等人贊同 從問題來看,還是建議你用Linux和PHP在學校弄個簡單的網絡社區出來吧,先建立知識體系,知道每個東西是干什么的。Linux + C++要么是內核開發,要么分布式系統底層,或者驅動開發。從題主的問題,應該排除了驅動開發。內核開發,以上回答提供了很好的建議,分布式系統開發需要的知識比較廣,對于大三的人來說,從你問問題的方式看,你還不具備這個基礎,所以你還是先從單臺Linux服務器,加簡單php網站開始吧。同時打好shell和python的底子。如果學校有數據庫和分布式的課程,就好好學習理論知識。我想對于在校大學本科生來說,能做好這些就很不錯了。之后就去一個靠譜的公司,踏踏實實地干幾年。 發布于 2014-01-27?4 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 24贊同 反對,不會顯示你的姓名 匿名用戶 黃杰、當我遇上你、唔知?等人贊同 根據工程經驗來看,Linux C/C++這個方向主要強調性能,高并發,穩定性這些因素,重點在后端。如果你對前端內容不是特別敏感(所謂的美),后端是你的強項,大數據,云存儲,云計算都與linux后端有密切 關系。
內容:語言(c/c++),算法(強調性能),linux系統編程及內核原理 (才知道如何調優),網絡。這是基礎。
然后就是具體的方向,例如高并發服務器?大數據?完全根據你自己的定位。
這里有關于linux的視頻以及大數據相關的視頻和項目,可以參照學習。
數據結構與算法剖析 視頻
linux高級程序設計(第3版)視頻
數據結構與算法面試題視頻
開源項目 發布于 2014-05-27?添加評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 16贊同 反對,不會顯示你的姓名 林志剛,軟件研發工程師 知乎用戶、溫豪、respass?等人贊同 看書的話建議你可以這么來:
1. 基礎:計算機網絡(了解網絡傳輸層協議的機制,包括TCP和UDP)
2. Linux開發:Unix網絡編程(了解Linux系統支持傳輸層協議的Socket API)
3. 應用層協議:HTTP權威指南(這是一個使用TCP的應用層協議,通過了解HTTP協議的機制,你可以學習一下應用程序的網絡通信協議的實現以及所面臨的各類問題)
項目的話,建議你可以從實現一個最簡單的QQ程序開始,你可以用Linux的C++開發底層的服務器端程序,在另一臺機子上用java開發客戶端。通過這樣一個項目你可以感受一下網絡的跨平臺跨語言特性。
PS:雖然上面這個項目看起來很簡單,但是你在實現過程中需要解決的問題很多,包括:定義和解析應用層協議包,設計協議的對話規則,設計算法來識別用戶,定義用戶之間傳輸對話數據的架構(基本的架構有兩類:通過服務器中心轉發,以及用戶與用戶之間點對點連接通信,建議先從服務器中心轉發架構做起),離線信息的保存等等。
其實要學會如何通過Linux C來實現數據通信很簡單,基本的API就那么幾個,但關鍵是如何設計自己應用程序的通信協議,并實現可靠的客戶端和服務端程序,什么是可靠?例如你的客戶端突然斷線了怎么處理?服務器端的客戶隊列太長怎么辦?要是用戶發送了不正確的報文給服務器,服務端程序怎么處理?要是連接不上服務器怎么辦?你應該可以發現,要解決這些問題,單是學習Linux網絡編程的幾個API是不夠的,你還需要學習網絡協議,這也就是為什么我建議你去看計算機網絡和HTTP權威這兩本關于網絡協議設計和分析的書了。
當然目前很多底層服務器程序是不需要你從頭開始寫的,一般你只需要改一些原有的服務器程序的代碼,優化一下現有的算法即可。所以在你完成了上述的學習后,你可以去學習Nginx或者Apache的http服務端程序源碼,這對于今后的工作可能也是有幫助的。 發布于 2015-05-13?2 條評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 14贊同 反對,不會顯示你的姓名 yegle,野生程序猿 知乎用戶、大海的禮物、naozai Wu?等人贊同 不是“我想往X方向發展應該看什么書”,而是“我作為一個CS專業的學生應該看什么書”
像APUE,UNP這樣的書,和你未來要做什么方向有什么關系?像算法導論這樣的書,你作為CS畢業生說自己沒通讀過說得過去嗎?
放寬心好好看書,好好學基礎。忘了是哪個知乎問題下的回答,我覺得挺好:計算機科班出身和非科班出身的最大區別是,科班出身的人有充足的時間去看上面的書并且可以和同樣有時間看這些書的人能討論學習。 發布于 2014-09-19?添加評論?感謝? 分享 ?收藏???沒有幫助???舉報???作者保留權利 13贊同 反對,不會顯示你的姓名 Honwhy,將char變量用%d輸出 abc12380x86、Gray D、知乎用戶?等人贊同 TCP/IP詳解
UNIX網絡編程1.2
UNIX環境高級編程
數據結構
算法導論(納信告訴我,CLRS并不是章章都精彩準確的。)
HTTP權威指南
現在很多服務器開始采用腳本語言來寫了,腳本語言有異步非阻塞I/O,事件驅動等等優點,建議學習C++的同時多點了解腳本語言。
總結
以上是生活随笔為你收集整理的Linux C++ 服务器端这条线怎么走?一年半能做出什么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 加密芯片具体是要保护什么
- 下一篇: 安装docker-ce