一、linux和os:
netstat :顯示網絡狀态
tcpdump:主要是截獲通過本機網絡接口的資料,用以分析。能夠截獲目前所有通過本機網卡的資料包。它擁有靈活的過濾機制,可以確定得到想要的資料。
ipcs:檢查系統上共享記憶體的配置設定
ipcrm:手動解除系統上共享記憶體的配置設定
(如果這四個指令沒聽說過或者不能熟練使用,基本上可以回家,通過的機率較小 ^_^ ,這四個指令的熟練掌握程度基本上能展現面試者實際開發和調試程式的經驗)
cpu 記憶體 硬碟 等等與系統性能調試相關的指令必須熟練掌握,設定修改權限 tcp網絡狀态檢視 各程序狀态 抓包相關等相關指令 必須熟練掌握
awk sed需掌握
1. 共享記憶體的使用實作原理
(必考必問,然後共享記憶體段被映射進程序空間之後,存在于程序空間的什麼位置?共享記憶體段最大限制是多少?)
共享記憶體定義:共享記憶體是最快的可用IPC(程序間通信)形式。它允許多個不相關的程序去通路同一部分邏輯記憶體。共享記憶體是由IPC為一個程序建立的一個特殊的位址範圍,它将出現在程序的位址空間中。其他程序可以把同一段共享記憶體段“連接配接到”它們自己的位址空間裡去。所有程序都可以通路共享記憶體中的位址。如果一個程序向這段共享記憶體寫了資料,所做的改動會立刻被有通路同一段共享記憶體的其他程序看到。是以共享記憶體對于資料的傳輸是非常高效的。
共享記憶體的原理:共享記憶體是最有用的程序間通信方式之一,也是最快的IPC形式。兩個不同程序A、B共享記憶體的意思是,同一塊實體記憶體被映射到程序A、B各自的程序位址空間。程序A可以即時看到程序B對共享記憶體中資料的更新,反之亦然。
2. c++程序記憶體空間分布(注意各部分的記憶體位址誰高誰低,注意棧從高到低配置設定,堆從低到高配置設定)
3. 使用過哪些程序間通訊機制,并詳細說明(重點)
4. makefile編寫,雖然比較基礎,但是會被問到
5. gdb調試相關的經驗,會被問到
6. 如何定位記憶體洩露?
記憶體洩漏是指堆記憶體的洩漏。堆記憶體是指程式從堆中配置設定的、大小任意的(記憶體塊的大小可以在程式運作期決定)、使用完後必須顯示釋放的記憶體。應用程式一般使用malloc、realloc、new等函數從堆中配置設定到一塊記憶體,使用完後,程式必須負責相應的調用free或delete釋放該記憶體塊。否則,這塊記憶體就不能被再次使用,我們就說這塊記憶體洩漏了。
C++程式缺乏相應的手段來檢測記憶體資訊,隻能使用top指令觀察程序的動态記憶體總額。而且程式退出時,我們無法獲知任何記憶體洩漏資訊
使用Linux指令回收記憶體,可以使用ps、kill兩個指令檢測記憶體使用情況和進行回收。在使用超級使用者權限時使用指令“ps”,它會列出所有正在運作的程式名稱和對應的程序号(PID)。kill指令的工作原理是向Linux作業系統的核心送出一個系統操作信号和程式的程序号(PID)
7. 動态連結和靜态連結的差別
動态連結是指在生成可執行檔案時不将所有程式用到的函數連結到一個檔案,因為有許多函數在作業系統帶的dll檔案中,當程式運作時直接從作業系統中找。 而靜态連結就是把所有用到的函數全部連結到exe檔案中。
動态連結是隻建立一個引用的接口,而真正的代碼和資料存放在另外的可執行子產品中,在運作時再裝入;而靜态連結是把所有的代碼和資料都複制到本子產品中,運作時就不再需要庫了。
8. 32位系統一個程序最多有多少堆記憶體
9. 多線程和多程序的差別
重點 面試官最最關心的一個問題,必須從cpu排程,上下文切換,資料共享,多核cup使用率,資源占用,等等各方面回答,然後有一個問題必須會被問到:哪些東西是一個線程私有的?答案中必須包含寄存器,否則悲催
10. 說出你所知道的linux系統的各類同步機制(重點)
11. 什麼是死鎖?如何避免死鎖(每個技術面試官必問)
12. 死鎖的條件
(互斥條件(Mutual exclusion):
1、資源不能被共享,隻能由一個程序使用。
2、請求與保持條件(Hold and wait):已經得到資源的程序可以再次申請新的資源。
3、非剝奪條件(No pre-emption):已經配置設定的資源不能從相應的程序中被強制地剝奪。
4、循環等待條件(Circular wait):系統中若幹程序組成環路,該環路中每個程序都在等待相鄰程序正占用的資源。
13. 處理死鎖的政策:
忽略該問題。例如鴕鳥算法,該算法可以應用在極少發生死鎖的的情況下。為什麼叫鴕鳥算法呢,因為傳說中鴕鳥看到危險就把頭埋在地底下,可能鴕鳥覺得看不到危險也就沒危險了吧。跟掩耳盜鈴有點像。
檢測死鎖并且恢複。
仔細地對資源進行動态配置設定,以避免死鎖。
通過破除死鎖四個必要條件之一,來防止死鎖産生。)
14. 列舉說明linux系統的各類異步機制
15. exit()與_exit()的差別?
_exit終止調用程序,但不關閉檔案,不清除輸出緩存,也不調用出口函數。exit函數将終止調用程序。在退出程式之前,所有檔案關閉,緩沖輸出内容将重新整理定義,并調用所有已重新整理的“出口函數”(由atexit定義)。
‘exit()’與‘_exit()’有不少差別在使用‘fork()’,特别是‘vfork()’時變得很突出。
‘exit()’與‘_exit()’的基本差別在于前一個調用實施與調用庫裡使用者狀态結構(user-mode constructs)有關的清除工作(clean-up),而且調用使用者自定義的清除程式
16. linux的記憶體管理機制是什麼?
Linux虛拟記憶體的實作需要6種機制的支援:位址映射機制、記憶體配置設定回收機制、緩存和重新整理機制、請求頁機制、交換機制和記憶體共享機制
記憶體管理程式通過映射機制把使用者程式的邏輯位址映射到實體位址。當使用者程式運作時,如果發現程式中要用的虛位址沒有對應的實體記憶體,就發出了請求頁要求。如果有空閑的記憶體可供配置設定,就請求配置設定記憶體(于是用到了記憶體的配置設定和回收),并把正在使用的實體頁記錄在緩存中(使用了緩存機制)。如果沒有足夠的記憶體可供配置設定,那麼就調用交換機制;騰出一部分記憶體。另外,在位址映射中要通過TLB(翻譯後援存儲器)來尋找實體頁;交換機制中也要用到交換緩存,并且把實體頁内容交換到交換檔案中,也要修改頁表來映射檔案位址。
17. linux的任務排程機制是什麼?
18. 标準庫函數和系統調用的差別?
19. 系統如何将一個信号通知到程序
二、c語言:
宏定義和展開(必須精通)
位操作(必須精通)
指針操作和計算(必須精通)
記憶體配置設定(必須精通)
sizeof必考
各類庫函數必須非常熟練的實作
哪些庫函數屬于高危函數,為什麼?(strcpy等等)
三、c++:
1. 一個String類的完整實作必須很快速寫出來(注意:指派構造,operator=是關鍵)
2. 虛函數的作用和實作原理(必問必考,實作原理必須很熟)
有虛函數的類内部有一個稱為“虛表”的指針(有多少個虛函數就有多少個指針),這個就是用來指向這個類虛函數。也就是用它來确定調用該那個函數。
實際上在編譯的時候,編譯器會自動加入“虛表”。虛表的使用方法是這樣的:如果派生類在自己的定義中沒有修改基類的虛函數,就指向基類的虛函數;如果派生類改寫了基類的虛函數(就是自己重新定義),這時虛表則将原來指向基類的虛函數的位址替換為指向自身虛函數的指針。那些被virtual關鍵字修飾的成員函數,就是虛函數。虛函數的作用,用專業術語來解釋就是實作多态性(Polymorphism),多态性是将接口與實作進行分離;用形象的語言來解釋就是實作以共同的方法,但因個體差異而采用不同的政策。
每個類都有自己的vtbl,vtbl的作用就是儲存自己類中虛函數的位址,我們可以把vtbl形象地看成一個數組,這個數組的每個元素存放的就是虛函數的位址,
虛函數的效率低,其原因就是,在調用虛函數之前,還調用了獲得虛函數位址的代碼。
3. sizeof一個類求大小(注意成員變量,函數,虛函數,繼承等等對大小的影響)
4. 指針和引用的差別(一般都會問到)
指針指向一塊記憶體,它的内容是所指記憶體的位址;而引用是某塊記憶體的别名。
相同點: 都是位址的概念;
差別:
指針是一個實體,而引用僅是個别名;
引用使用時無需解引用(*),指針需要解引用;
引用隻能在定義時被初始化一次,之後不可變;指針可變;
引用沒有 const,指針有 const;
引用不能為空,指針可以為空;
“sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或對象的位址)的大小;
指針和引用的自增(++)運算意義不一樣;
從記憶體配置設定上看:程式為指針變量配置設定記憶體區域,而引用不需要配置設定記憶體區域。
5. 多重類構造和析構的順序
先調用基類的構造函數,在調用派生類的構造函數
先構造的後析構,後構造的先析構
6. stl各容器的實作原理(必考)
STL共有六大元件
1、容器。2、算法。3、疊代器。4、仿函數。6、擴充卡。
序列式容器:
vector-數組,元素不夠時再重新配置設定記憶體,拷貝原來數組的元素到新配置設定的數組中。
list-單連結清單。
deque-配置設定中央控制器map(并非map容器),map記錄着一系列的固定長度的數組的位址.記住這個map僅僅儲存的是數組的位址,真正的資料在數組中存放着.deque先從map中央的位置(因為雙向隊列,前後都可以插入元素)找到一個數組位址,向該數組中放入資料,數組不夠時繼續在map中找空閑的數組來存資料。當map也不夠時重新配置設定記憶體當作新的map,把原來map中的内容copy的新map中。是以使用deque的複雜度要大于vector,盡量使用vector。
stack-基于deque。
queue-基于deque。
heap-完全二叉樹,使用最大堆排序,以數組(vector)的形式存放。
priority_queue-基于heap。
slist-雙向連結清單。
關聯式容器:
set,map,multiset,multimap-基于紅黑樹(RB-tree),一種加上了額外平衡條件的二叉搜尋樹。
hash table-散清單。将待存資料的key經過映射函數變成一個數組(一般是vector)的索引,例如:資料的key%數組的大小=數組的索引(一般文本通過算法也可以轉換為數字),然後将資料當作此索引的數組元素。有些資料的key經過算法的轉換可能是同一個數組的索引值(碰撞問題,可以用線性探測,二次探測來解決),STL是用開鍊的方法來解決的,每一個數組的元素維護一個list,他把相同索引值的資料存入一個list,這樣當list比較短時執行删除,插入,搜尋等算法比較快。
hash_map,hash_set,hash_multiset,hash_multimap-基于hash table。
7. extern c 是幹啥的,(必須将編譯器的函數名修飾的機制解答的很透徹)
8. volatile是幹啥用的,(必須将cpu的寄存器緩存機制回答的很透徹)
volatile的本意是“易變的” 因為通路寄存器要比通路記憶體單元快的多,是以編譯器一般都會作減少存取記憶體的優化,但有可能會讀髒資料。當要求使用volatile聲明變量值的時候,系統總是重新從它所在的記憶體讀取資料,即使它前面的指令剛剛從該處讀取過資料。精确地說就是,遇到這個關鍵字聲明的變量,編譯器對通路該變量的代碼就不再進行優化,進而可以提供對特殊位址的穩定通路;如果不使用volatile,則編譯器将對所聲明的語句進行優化。(簡潔的說就是:volatile關鍵詞影響編譯器編譯的結果,用volatile聲明的變量表示該變量随時可能發生變化,與該變量有關的運算,不要進行編譯優化,以免出錯)
volatile的本質:
編譯器的優化
在本次線程内, 當讀取一個變量時,為提高存取速度,編譯器優化時有時會先把變量讀取到一個寄存器中;以後,再取變量值時,就直接從寄存器中取值;當變量值在本線程裡改變時,會同時把變量的新值copy到該寄存器中,以便保持一緻。
當變量在因别的線程等而改變了值,該寄存器的值不會相應改變,進而造成應用程式讀取的值和實際的變量值不一緻。
當該寄存器在因别的線程等而改變了值,原變量的值不會改變,進而造成應用程式讀取的值和實際的變量值不一緻。
volatile應該解釋為“直接存取原始記憶體位址”比較合适,“易變的”這種解釋簡直有點誤導人。
9. static const等等的用法,(能說出越多越好)
四、資料結構或者算法:
各類樹結構的實作和應用
各類排序:大根堆的實作,快排(如何避免最糟糕的狀态?),bitmap的運用等等
hash, 任何一個技術面試官必問(例如為什麼一般hashtable的桶數會取一個素數?如何有效避免hash結果值的碰撞)
五、網絡程式設計:
1. tcp與udp的差別(必問)
基于連接配接與無連接配接
對系統資源的要求(TCP較多,UDP少)
UDP程式結構較簡單
流模式與資料報模式
TCP保證資料正确性,UDP可能丢包,TCP保證資料順序,UDP不保證
TCP—傳輸控制協定,提供的是面向連接配接、可靠的位元組流服務。當客戶和伺服器彼此交換資料前,必須先在雙方之間建立一個TCP連接配接,之後才能傳輸資料。TCP提供逾時重發,丢棄重複資料,檢驗資料,流量控制等功能,保證資料能從一端傳到另一端。
UDP—使用者資料報協定,是一個簡單的面向資料報的運輸層協定。UDP不提供可靠性,它隻是把應用程式傳給IP層的資料報發送出去,但是并不能保證它們能到達目的地。由于UDP在傳輸資料報前不用在客戶和伺服器之間建立一個連接配接,且沒有逾時重發等機制,故而傳輸速度很快
2. socket服務端的實作,select和epoll的差別(必問)
select的本質是采用32個整數的32位,即32*32= 1024來辨別,fd值為1-1024。當fd的值超過1024限制時,就必須修改FD_SETSIZE的大小。這個時候就可以辨別32*max值範圍的fd。
對于單程序多線程,每個線程處理多個fd的情況,select是不适合的。
1.所有的線程均是從1-32*max進行掃描,每個線程處理的均是一段fd值,這樣做有點浪費
2.1024上限問題,一個處理多個使用者的程序,fd值遠遠大于1024
是以這個時候應該采用poll,
poll傳遞的是數組頭指針和該數組的長度,隻要數組的長度不是很長,性能還是很不錯的,因為poll一次在核心中申請4K(一個頁的大小來存放fd),盡量控制在4K以内
epoll還是poll的一種優化,傳回後不需要對所有的fd進行周遊,在核心中維持了fd的清單。select和poll是将這個核心清單維持在使用者态,然後傳遞到核心中。但是隻有在2.6的核心才支援。
epoll更适合于處理大量的fd ,且活躍fd不是很多的情況,畢竟fd較多還是一個串行的操作
epoll哪些觸發模式,有啥差別?(必須非常詳盡的解釋水準觸發和邊緣觸發的差別,以及邊緣觸發在程式設計中要做哪些更多的确認)
epoll可以同時支援水準觸發和邊緣觸發(Edge Triggered,隻告訴程序哪些檔案描述符剛剛變為就緒狀态,它隻說一遍,如果我們沒有采取行動,那麼它将不會再次告知,這種方式稱為邊緣觸發),理論上邊緣觸發的性能要更高一些,但是代碼實作相當複雜。
epoll同樣隻告知那些就緒的檔案描述符,而且當我們調用epoll_wait()獲得就緒檔案描述符時,傳回的不是實際的描述符,而是一個代表就緒描述符數量的值,你隻需要去epoll指定的一個數組中依次取得相應數量的檔案描述符即可,這裡也使用了記憶體映射(mmap)技術,這樣便徹底省掉了這些檔案描述符在系統調用時複制的開銷。
另一個本質的改進在于epoll采用基于事件的就緒通知方式。在select/poll中,程序隻有在調用一定的方法後,核心才對所有監視的檔案描述符進行掃描,而epoll事先通過epoll_ctl()來注冊一個檔案描述符,一旦基于某個檔案描述符就緒時,核心會采用類似callback的回調機制,迅速激活這個檔案描述符,當程序調用epoll_wait()時便得到通知。
3. 大規模連接配接上來,并發模型怎麼設計
4. tcp結束連接配接怎麼握手,time_wait狀态是什麼,為什麼會有time_wait狀态?哪一方會有time_wait狀态,如何避免time_wait狀态占用資源(必須回答的詳細)
5. tcp頭多少位元組?哪些字段?(必問)
頭20位元組,選項12位元組
6. connect會阻塞,怎麼解決?(必考必問)
最通常的方法最有效的是加定時器;也可以采用非阻塞模式。
設定非阻塞,傳回之後用select檢測狀态)
如果select傳回可讀,結果隻讀到0位元組,什麼情況?
某個套接字集合中沒有準備好,可能會select記憶體用FD_CLR清該位為0;
今天的内容就分享到這裡,需要linux背景伺服器開發學習資料的可以背景私信“資料”,免費分享