標籤:

Linux後台CPP學習之路 & 面經知識點收錄

Linux後台CPP學習之路 & 面經知識點收錄

來自專欄 學習編程

作者:叫小丁不叫小丁丁

鏈接:nowcoder.com/discuss/78

來源:牛客網

一、面經知識點收錄

1】C++

extern "C"的作用:可以把程序編譯成彙編文件,然後從彙編代碼去看它的作用

C/CPP const關鍵字:再了解一下CPP字元串常量以及普通const常量的內存布局,還有與volatile一起使用的效果,然後可以看出C里的const與CPP里的const還是有一定差別的...

C/CPP static關鍵字:了解一下ELF(參見《深入理解計算機系統》第七章:鏈接),然後從符號表的角度去分析static關鍵字的作用,注意:CPP不像python等解釋性語言,它不會執行類定義的代碼,所以類的靜態數據成員必須在類外定義(除了靜態常量),這個時候static的作用跟普通的static語義不同...還有,static函數在單例模式中有一個應用(參見《Effective CPP》條款4:確定對象被使用前已先被初始化)

C/CPP volatile關鍵字:在底層代碼中用得多(之前調試linux文件系統的時候,想要獲得一個file\_struct對象指針,然後這個指針總是被優化掉,不清楚是不是跟volatile有關...)

C/CPP restrict關鍵字:在函數庫介面中用得多

C/CPP內存分配管理:CPP中的new只是對malloc進行了一層封裝,malloc的具體實現可以看glibc的malloc源碼,然後調用system call,最終會接觸操作系統的內存管理模塊,所以最終還是需要了解操作系統的堆管理(簡單堆管理參閱《深入理解計算機系統》第九章:虛擬存儲器,linux中內存管理具體實現可以閱讀linux源碼),需要特別了解內存池的實現(可以閱讀sgi stl源碼)還有夥伴系統與slab...

CPP反射:工廠模式以及CPP17了解一下

CPP異常機制:網上有很多講CPP異常機制的博客

CPP智能指針:可以按照介面要求自己實現一下四個簡單的智能指針,其中share\_ptr里的析構器其實是一個仿函數,然後可以自己想辦法去實現一下function,any之類的模板類

CPP四種類型轉換:

cplusplus.com/doc/tutor

CPP string實現原理:其實實現與vector差不多,具體實現參閱sgi stl源碼

CPP map、set實現原理:封裝了一顆紅黑樹,紅黑樹重要的就是旋轉,還有平衡度(根據黑高證明),具體實現參閱sgi stl源碼

CPP函數重載、覆蓋、隱藏:重載可以從彙編代碼去看(根據參數類型去重命名函數名),覆蓋可以去從虛函數表去分析,隱藏可以從作用域去理解

CPP編譯時多態與運行時多態:類的多態(運行時多態)一定要看看《深度探索CPP對象模型》這本書,stack overflow上有一個帖子深度討論了類的多態、虛繼承這些,講到了構造析構過程中vptr的變化,然後可以自己去適當理解為什麼虛函數的具體調用依賴於構造析構的當前進度(鏈接:https://stackoverflow.com/questions/6258559/what-is-the-vtt-for-a-class)。注意,函數模板不能局部特例化,不然就是模板重載,不得不多說一句,函數模板實例化後的函數與普通函數不在同一命名空間中(不是CPP語言支持的namespace,是編譯器所用的命名空間),所以能夠出現具有相同名字相同參數類型的函數,實際上,從彙編代碼去看,其實最終的名字還是不同的

CPP為什麼構造函數不能設置為虛函數:vptr還沒有被設置,會出現先有雞還是先有蛋的矛盾

new/delete和 malloc/free的區別:《Effective CPP》定製new和delete(條款49~52)了解一下

如何實現只能動態分配類對象,不能靜態分配:只是要求不能在棧上分配,必須在堆上分配

動態鏈接庫與靜態鏈接庫的區別

【2】 設計模式

單例模式(static函數可以實現)

策略模式(舉例:share\_ptr的析構器)

簡單工廠、工廠方法、抽象工廠模式

裝飾模式(閉包:CPP lambda、Python decorator了解一下)

代理模式(舉例:iterator有點代理模式的意思)

原型模式(舉例:實現boost庫中的any時需要用到的clone方法)

模板方法模式(《Effective CPP》條款35:考慮virtual函數以外的其他選擇 有介紹,但是舉的例子感覺不是很好,感覺最大的突出點是事前和事後,之後看了《大話設計模式》對模板方法的介紹,感覺它的最大特點應該是實現最大化代碼復用)

適配器模式(舉例:STL中的容器適配器)

迭代器模式(舉例:iterator)

【3】資料庫

資料庫基本操作:可能還會要求通過sql語句對資料庫進行調優

資料庫索引:索引數據結構的實現,如何設置索引、以及複合索引內部的順序(比如說,假設有一個複合主鍵包含A、B兩列,索引AB與索引BA對資料庫的影響)

資料庫事務:底層如何實現事務

資料庫引擎

資料庫存儲過程

資料庫的第一二三範式

delete、truncate、drop的區別及應用場所

【4】計算機網路

HTTP狀態碼

流量控制

擁塞控制:高延遲擁塞控制會降低tcp傳輸效率,這個時候需要自己實現擁塞控制或者避免擁塞控制,所以需要封裝udp或者ip數據報(如果需要重寫擁塞控制演算法,可以了解一下BBR演算法)

TCP連接的建立與終止:從tcp三次握手可以引入Ddos攻擊

TIME\_WAIT:作用以及如何避免

Ddos攻擊原理:listen隊列

長肥管道

7/5層模型協議、設備

簡單ftp伺服器socket編程:注意盡量使用一個請求一個線程/進程模型

【5】演算法

一定要把《劍指offer》刷到滾瓜爛熟,裡面的演算法最好能全部手寫出來,一般面試的手撕演算法幾乎都來源於這本書

大數據處理:大數據top 100啊之類的問題很常見

大整數計算:轉為字元串計算或者很強的可以自己用位運算實現一下...

如何設計好的散列函數

動態規劃:了解一下動態規劃基本概念以及有哪些常見演算法

貪心演算法:了解一下貪心演算法基本概念以及有哪些常見演算法

排序演算法:快速排序、堆排序、歸併排序、插值排序、冒泡排序、選擇排序、計數排序(了解一下)、基數排序(了解一下),除了兩個需要了解的,其他六個都需要快速寫出來,而且知道它們的平均、最壞時間、空間複雜度

搜索演算法:折半查找(一定要能快速寫出來,還有其變種),二叉樹查找,hash查找

數據結構-堆

數據結構-鏈表:數據結構-跳錶、演算法:二叉搜索樹轉為雙向鏈表、鏈表迴環、反轉、複雜鏈表的複製...

數據結構-樹:數據結構-AVL樹、紅黑樹、B 樹,演算法:二叉樹的前中後序遍歷,還有《劍指offer》上的樹演算法

數據結構-圖:dfs、bfs、dijkstra、floyd、prim、kruskal都要能夠寫出來

字元串演算法:kmp、boyer-moore都要能夠寫出來、正則演算法了解一下

手撕演算法:手撕演算法的代碼量一般都不是很大,所以應該去權衡一下什麼演算法更容易被考到什麼不容易被考到。除了《劍指offer》,還有很多跟程序魯棒性和性能有關的手撕代碼題:strcpy,實現單例模式...,還有一些題來源於leetcode,但是幾乎都是easy或者medium程度的題

【6】操作系統/Linux 內核

中斷:介紹中斷的作用,要是再能從硬體、彙編級別去介紹一下中斷會發生什麼就更棒了

信號:幾乎所有講操作系統的書都有介紹信號,linux信號參閱《Unix環境高級編程》第10章:信號,以及《深入理解linux內核》第11章:信號,需要了解可靠信號與不可靠信號的區別,還需要特別了解SIGCHLD、SIGCLD信號

進程與線程:輕量級進程、系統級線程、用戶級線程、進程,這些可以讀linux內核源碼以及一些資料很容易理解,協程(Python中yield的效果以及它的具體實現(C源碼)了解一下),可以去網上找找CPP的協程庫去讀一讀

linux常見的調度演算法:知道這些演算法的思想就行,讀個linux源碼就更棒

linux文件系統:《深入理解linux內核》第12章:虛擬文件系統 以及 第18章:Ext2和Ext3文件系統 以及 第16章:訪問文件,可以讓你深入了解linux文件系統

linux IPC:System V、Posix IPC熟悉一下,可以參閱《Unix環境高級編程 進程間通信》,以及清楚它們的作用與優缺點,當然還是推薦去閱讀一下IPC的linux內核源碼

如何實現linux的高並發,線程池的思想:github上有好多好多線程庫,抓一個下來自己讀一讀,代碼量不是很大,很推薦自己動手寫一寫

死鎖產生的四個必要條件及如何預防

編寫linux的並發測試程序:生產者消費者並發程序要求能夠寫得出來

驚群效應:舉例子講一下驚群現象,然後去了解一下如何避免。內核中存在兩個驚群的例子,accept驚群與epoll驚群,linux內核經過改進避免了一些驚群,可以從內核源碼去解釋一下它是怎麼做的

fork、vfork、clone的區別:這個真的只能讀源碼才能深入了解了,注意,phtread線程庫就是使用的clone

殭屍進程:清楚一下概念以及它的危害,然後知道如何去避免殭屍進程

select、poll、epoll的區別:從內核源碼去分析,select與poll實現差不多,讀了一個源碼差不多很快就能讀懂第二個,epoll設計很獨特也很有意思,趕快去讀一讀

linux內核夥伴系統、slab緩存(實現原理、與普通內存分配的區別以及優勢):簡單介紹參閱《深入理解linux內核》第8章:內存管理,深入了解就去讀linux內核源碼...

---

二、學習方法

收到好幾條私信評論,問我學習方法,知道自己很菜,雖然有時候會盲目自信,但是跟一些大牛比起來還是會深深感到自卑...沒了解學習過一個領域,看到別人在這方面有見解,然後就會覺得別人特別牛,可是一旦了解,就會發現並沒有想像中的那麼厲害,所以說我真的很菜的(並沒有裝逼,是真心話)...

適合一個人的學習方法,不一定適合另一個人,所以在這發表的見解,大家取其精華去其糟粕...

有好幾個非cs專業的同學問我學習方法,那麼先貼一個鏈接:study.163.com/curricula,這裡有cs專業大一到大四開的所有課程,可能這裡有些課程質量不是很好,但是還是可以了解一下具體開過哪些課,然後自己去找教程去認真學習。這些課程中開的數據結構課感覺還不錯,可以去認真看看...

看到好幾個同學說,問別人學習方法都是推薦了一大堆書,哪看的完...其實很多東西只有看書才能看得明白的也能看得更透徹,我幾乎都是看書看源碼,遇到一些很難的就google或者找視頻看...因為如果所有東西都看別人講(google看博客或者看視頻),就可能遇到一個知識點不同的人不同的看法,然後自己就弄弄不明白還會被帶歪然後就心情爆炸...所以我還是會推薦大家看書或者看源碼,但是會講重點哪些地方應該看哪些地方簡單了解一下,這樣對大家的時間還是能省一點的...

大家一定要有明確的目標,知道自己該學些什麼又有哪些東西學了對主線沒有幫助的,目的明確一點真的很重要,我明知我是linux後台CPP,以前還花了很長時間去學習windows下的編程,雖然學習了一點東西,但是對我的發展並沒有多大幫助而且真的很浪費時間,因為我把它當成主線來認真學習了...就算是這樣,以後還是接觸linux,windows用得少了也很快就會忘記,所以希望大家能好好權衡...

我很強調動手以及發散思維,發散思維比如說學到一個東西能很快聯想到之前學過的另一個東西,以及遇到新的東西希望能夠從更底層去猜測它的實現,要是等以後再接觸到它的實現的時候,可以將具體實現與之前自己的猜測進行比較...動手是真的巨重要,我討厭伸手黨,也討厭紙上談兵,遇到問題我會盡量去用代碼或者實現源碼去解決問題,有時候跟蹤程序的具體過程可能還要反彙編,有時候遇到很難很難的調試問題,比如說之前調試linux文件系統,我真的花了巨長巨長的時間,這個時候需要很強的耐心還有明確的目的,因為有時候調試著調試著突然忘記了自己想要幹嗎...

我從很早開始使用linux作為自己的日常工作環境,為了學習《Unix環境高級編程》,我幾乎嘗試了所有linux發行版還有其他unix系統(這些作為虛擬機部署),部署其實也是一件很有趣的事,也能讓你更加深入的了解類unix系統...推薦大家使用linux作為自己的學習環境,而且還能剋制自己玩大部分遊戲...

ok,開始吧...

【1】CPP語言

在學習CPP之前,我只有C基礎。

我是啃《CPP Primer》這本書,當時是第五版,那個時候最新的還是CPP11標準,也推薦大家看這本書,因為CPP14、17都還是太新,用的很少,而且大多公司也才從CPP98過渡到CPP11。這本書我讀了很多遍,重點是STL與類,模板編程與OO幾乎都佔了CPP的半壁江山。

關於CPP面向對象,讀《CPP Primer》這本書關於類的講解還有《深度探索CPP對象模型》,然後這部分內容就差不多了。

把細節列出來吧:

拷貝控制(默認構造、值構造、拷貝構造、移動構造、拷貝複製、移動複製、析構)這些需要很熟練很熟練的了解,這其中初值列與隱含的析構列很重要,對象模型(簡單繼承、含有虛函數的繼承、含有虛基類的繼承)它們的內存布局需要很清楚的知道,還有看上面那個stack overflow的帖子...命名返回值優化順便了解一下(見《深度探索CPP對象模型》),然後就能理解為什麼有時候類實例的創建沒有按照正確流程...

模板編程首先我推薦一定要把SGI STL庫源碼閱讀一遍,就算源碼沒有看過,STL還是得會熟練的使用,重點在set/map、string/vector,要是能自己寫一寫就最好了,很喜歡侯捷先生的兩句話:「源碼之下,了無秘密」,「天下大事,必作於細」。內存分配器、幾個容器、幾個容器適配器、幾個范型演算法,代碼量大約在1~2w行左右,然後可以自己再實現更多的東西,例如可以再實現一些boost庫中的東西、四個智能指針、any、tuple之類的,然後能真正讓你體會到模板元編程的樂趣...

模板編程幾個重要細節列出來:函數模板--顯式實例化、特例化,類模板--顯式實例化、全特化、局部特例化,模板容易出現的問題見《Effective CPP》條款43:學習處理模板化基類內的名稱以及條款46:需要類型轉換時請為模板定義非成員函數,可能會幫到你。還有一個很容易出現的問題應該就是關於模板的鏈接錯誤了(提示沒有找到指定的函數),其實就是沒有模板實例化,具體問題去google...CPP11還有很多特性,右值呀、lambda呀、function呀,RTTI呀...右值可以從彙編角度去看;lambda也可以從彙編角度去看,lambda其實就是個閉包,在CPP中lambda沒有一個具體的類型,將一個捕獲列表與一個函數捆綁在了一起,所以從彙編去看的話,返回一個lambda其實就是返回捕獲列表中捕獲的數據;function運用了類型擦除,具體實現可以google,其實boost庫中的any也用了類型擦除,RTTI的話其實讀完《深度探索CPP對象模型》,從虛函數表中應該已經知道了它的原理;還有一些高級部分:類型萃取呀、tuple呀這些...,類型萃取讀完SGI STL源碼之後應該已經能夠深刻的理解了,tuple的話就是用了模板遞歸這些嘛

一些模板元編程...書籍推薦:《CPP Primer》、《深度探索CPP對象模型》、《STL源碼剖析》、《CPP標準程序庫》(參閱)、《Boost程序庫完全開發指南》(簡單讀一讀)、《Effective CPP》(想要更好的學習CPP強烈推薦)、《More Effective Modern CPP》(讓你更好的了解CPP11,但是這本書目前還沒有中文版,但是感興趣的同學可以啃一啃...)

【2】設計模式

推薦閱讀《大話設計模式》,提醒一下,設計模式面試考得不多,但是想要了解的話還是去看一看...其中好幾個設計模式可以聯繫已學過的東西加深印象,學習設計模式最好最快的辦法就是理解它的UML圖...

【3】資料庫

我的資料庫不是很好,快速、基本地學習資料庫推薦閱讀《Sql必知必會》(很薄的一本書)

【4】計算機網路

《Tcp/ip詳解》(卷一)了解一下,看上面收錄的面試知識點,著重去學習重要的那些。詳細介紹tcp可以閱讀《計算機網路》(謝希仁)(對也就是大多學校發的那本教材)第7章:運輸層,其中的tcp可靠傳輸相關的一定要認真認真讀!!,列出細節吧:滑動窗口、擁塞控制、還有狀態圖、還有TIME\_WAIT(重中之重),socket編程可以閱讀《Unix網路編程 套接字聯網API》,其中跟SCTP相關的可以忽略掉,其實再省略一點的話只讀第一二部分就行了...

【5】演算法

上面收錄的面試知識點基本已經全部講了,也就是面試的時候所有數據結構與演算法都可能會考到。我演算法還是有點薄弱,因為花了太多的時間去學習專業課然後沒有太多的時間去刷題,但是強烈建議大家多去刷刷題,ACM盡量參加,含金量特別特別高。leetcode、牛客演算法都該做做,尤其是牛客上關於《劍指offer》的專題一定要全部刷到滾瓜爛熟...剛刷演算法可能會很困難,但是堅持去做,做完去看看題解還是會很有進步的。上面我還給了網易雲課堂的鏈接,裡面有開數據結構的課,學習基礎可以去看看...推薦書籍《Algorithms 4th Edition》(英文版,所以可能有點難讀,英語不是很好的話就參閱),《演算法導論》

【6】操作系統

還是上面給的網易雲課堂鏈接,裡面有一門操作系統的課,簡單學習的話可以去看看。

【7】linux內核

先簡單讀一遍《Linux內核設計與實現》,偶爾可對照一下linux內核源碼。但是呢,這本書其中感覺有很多錯誤,不是很嚴謹,所以不推薦作為深入學習linux內核的書籍,只是作為簡單的入門。

深入學習linux內核的話,可以認真讀linux內核源碼然後對照《深入理解linux內核》這本書,當然,重點還是讀源碼...讀了《Linux內核設計與實現》之後已經有了基礎了,然後其實已經可以有能力自己讀懂源碼了...

可能會覺得還是有困難,講一下我的linux入門之路吧...我先讀了一遍《Linux內核設計與實現》,當時對照著源碼讀的,當然啦,書上不可能所有東西都講,只是挑一些特別重要的講,其他的還是需要自己去看去理解...讀完這本書之後,大致的內存管理、進程式控制制之類的還是了解了,我真正入門是在讀多路復用select、poll、epoll源碼的時候,這三個函數源碼真的很簡單,讀懂之後能很有效地增強自信心,然後就覺得很有趣,然後就開始了真正的linux學習之路。之後慢慢地linux文件系統、內存管理、IPC之類的都能看懂,不懂google,看博客,然後繼續讀...linux內核源碼其實並沒有特別難學習,難的是不知道怎麼入門...

這裡有奧特曼的epoll源碼總結:https://www.nowcoder.com/discuss/26226,之後要是有時間我再把我對do_fork、select、poll、epoll、ipc、文件系統、內存管理、大多數系統調用、進程調度呀之類的源碼總結貼出來...

【8】彙編

對了,走CPP後台這條路,就是需要與底層進行接觸,所以了解彙編是必不可少的。儘早學會彙編,對以後學習任何高級語言、操作系統都會很有幫助。推薦閱讀《彙編語言》(王爽),《X86彙編語言 從實模式到保護模式》,《彙編語言程序設計》(簡單閱讀一下,了解AT&T彙編格式)

帖子內容沒用md把格式做好,所以將就讀一讀吧...雖然很菜,但是還是希望上面的總結能夠幫助到大家...有什麼學習相關的問題可以私信我或者給我評論....

跟我交流nowcoder.com/discuss/78

更多好文章nowcoder.com/discuss?


推薦閱讀:

面試官問你:你有什麼想問的,你這麼回答會給你加分
奇葩而有效的反向面試——王猛見桓溫
「面試達人」面試官問「你的缺點是什麼?」來看最優解法!
面試中的CV --- classification to detection
HR在公司的地位如何?HR的職責、價值是什麼?

TAG:Linux | CC | 面試 |