前段時間專心面過騰訊,通過了N輪的技術面,結果仍是掛了,但沒掛在技術面,比較欣慰,回來以後寫一點總結,以供有夢想進入騰訊作後臺服務器開發的同窗參考,本文章爲胡成精心總結,胡成原創,copy和轉載請通知。ps:()以內的文字由做者點評,非面試題文字。mysql
linux和os:linux
netstat tcpdump ipcs ipcrm (若是這四個命令沒據說過或者不能熟練使用,基本上能夠回家,經過的機率較小 ^_^ ,這四個命令的熟練掌握程度基本上能體現面試者實際開發和調試程序的經驗)c++
cpu 內存 硬盤 等等與系統性能調試相關的命令必須熟練掌握,設置修改權限 tcp網絡狀態查看 各進程狀態 抓包相關等相關命令 必須熟練掌握面試
awk sed需掌握算法
共享內存的使用實現原理(必考必問,而後共享內存段被映射進進程空間以後,存在於進程空間的什麼位置?共享內存段最大限制是多少?)sql
c++進程內存空間分佈(注意各部分的內存地址誰高誰低,注意棧從高道低分配,堆從低到高分配)數據庫
ELF是什麼?其大小與程序中全局變量的是否初始化有什麼關係(注意.bss段)編程
使用過哪些進程間通信機制,並詳細說明(重點)設計模式
makefile編寫,雖然比較基礎,可是會被問到緩存
gdb調試相關的經驗,會被問到
如何定位內存泄露?
動態連接和靜態連接的區別
32位系統一個進程最多多少堆內存
多線程和多進程的區別(重點 面試官最最關心的一個問題,必須從cpu調度,上下文切換,數據共享,多核cup利用率,資源佔用,等等各方面回答,而後有一個問題必須會被問到:哪些東西是一個線程私有的?答案中必須包含寄存器,不然悲催)
寫一個c程序辨別系統是64位 or 32位
寫一個c程序辨別系統是大端or小端字節序
信號:列出常見的信號,信號怎麼處理?
i++是否原子操做?並解釋爲何???????
說出你所知道的各種linux系統的各種同步機制(重點),什麼是死鎖?如何避免死鎖(每一個技術面試官必問)
列舉說明linux系統的各種異步機制
exit() _exit()的區別?
如何實現守護進程?
linux的內存管理機制是什麼?
linux的任務調度機制是什麼?
標準庫函數和系統調用的區別?
補充一個坑爹坑爹坑爹坑爹的問題:系統如何將一個信號通知到進程?(這一題哥沒有答出來)
c語言:
宏定義和展開(必須精通)
位操做(必須精通)
指針操做和計算(必須精通)
內存分配(必須精通)
sizeof必考
各種庫函數必須很是熟練的實現
哪些庫函數屬於高危函數,爲何?(strcpy等等)
c++:
一個String類的完整實現必須很快速寫出來(注意:賦值構造,operator=是關鍵)
虛函數的做用和實現原理(必問必考,實現原理必須很熟)
sizeof一個類求大小(注意成員變量,函數,虛函數,繼承等等對大小的影響)
指針和引用的區別(通常都會問到)
多重類構造和析構的順序
stl各容器的實現原理(必考)
extern c 是幹啥的,(必須將編譯器的函數名修飾的機制解答的很透徹)
volatile是幹啥用的,(必須將cpu的寄存器緩存機制回答的很透徹)
static const等等的用法,(能說出越多越好)
數據結構或者算法:
《離散數學》範圍內的一切問題皆由可能被深刻問到(這個最坑爹,最重要,最體現功底,最能加分,特別是各種樹結構的實現和應用)
各種排序:大根堆的實現,快排(如何避免最糟糕的狀態?),bitmap的運用等等
hash, 任何一個技術面試官必問(例如爲何通常hashtable的桶數會取一個素數?如何有效避免hash結果值的碰撞)
網絡編程:
tcp與udp的區別(必問)
udp調用connect有什麼做用?
tcp鏈接中時序圖,狀態圖,必須很是很是熟練
socket服務端的實現,select和epoll的區別(必問)
epoll哪些觸發模式,有啥區別?(必須很是詳盡的解釋水平觸發和邊緣觸發的區別,以及邊緣觸發在編程中要作哪些更多的確認)
大規模鏈接上來,併發模型怎麼設計
tcp結束鏈接怎麼握手,time_wait狀態是什麼,爲何會有time_wait狀態?哪一方會有time_wait狀態,如何避免time_wait狀態佔用資源(必須回答的詳細)
tcp頭多少字節?哪些字段?(必問)
什麼是滑動窗口(必問)
connect會阻塞,怎麼解決?(必考必問,提示:設置非阻塞,返回以後用select檢測狀態)
若是select返回可讀,結果只讀到0字節,什麼狀況?
網絡編程:
tcp與udp的區別(必問)
udp調用connect有什麼做用?
tcp鏈接中時序圖,狀態圖,必須很是很是熟練
socket服務端的實現,select和epoll的區別(必問)
epoll哪些觸發模式,有啥區別?(必須很是詳盡的解釋水平觸發和邊緣觸發的區別,以及邊緣觸發在編程中要作哪些更多的確認)
大規模鏈接上來,併發模型怎麼設計
tcp結束鏈接怎麼握手,time_wait狀態是什麼,爲何會有time_wait狀態?哪一方會有time_wait狀態,如何避免time_wait狀態佔用資源(必須回答的詳細)
tcp頭多少字節?哪些字段?(必問)
什麼是滑動窗口(必問)
connect會阻塞,怎麼解決?(必考必問,提示:設置非阻塞,返回以後用select檢測狀態)
若是select返回可讀,結果只讀到0字節,什麼狀況?
keepalive 是什麼東東?如何使用?
列舉你所知道的tcp選項,並說明其做用。
socket什麼狀況下可讀?
db:
mysql,會考sql語言,服務器數據庫大規模數據怎麼設計,db各類性能指標
最後:補充一個最最重要,最最坑爹,最最有難度的一個題目:一個每秒百萬級訪問量的互聯網服務器,每一個訪問都有數據計算和I/O操做,若是讓你設計,你怎麼設計?
前些時間去了騰訊面試, 惋惜現場沒回答好。
是一些基礎問題,同時也比較深刻的問題。 在此列出來, 歡迎你們討論交流。
提問(不按時間順序):
1, 使用Linux epoll模型,水平觸發模式(Level-Triggered);當socket可寫時,會不停的觸發socket可寫的事件,如何處理?
2, 從socket讀數據時,socket緩存裏的數據,可能超過用戶緩存的長度,如何處理? 例如,socket緩存有8kB的數據,而你的緩存只有2kB空間。
3, 向socket發送數據時, 可能只發送了用戶緩存裏的一半,如何處理?例如,須要向socket發送8kB數據,返回值只有2kB發送成功。
4, C++的虛函數是怎麼實現的?
5, C++的虛函數有什麼做用?
6, 非阻塞connect()如何實現?
7,sizeof()問題
class A
{
char c;
int val;
short sh;
}
class B
{
char c;
int val;
short sh;
void func1(void);
virtual func2(void);
}
sizeof(A), sizeof(B) 分別是多少?
8, 實現字符串比較函數 strcmp(char *src, char * sub)
9, 實現內存拷貝函數 strcpy(void*dst, char * src, size_t len)
10,條件變量的如何使用? 你使用的線程函數是什麼?
11, deamon進程如何實現?
12, HTTP和CGI是什麼?
13, TCP的三次握手, TIME_WAIT和CLOSE_WAIT狀態是什麼?
由於第7題以後的屬於客觀題,不打算在此寫答案。 朋友們若有好的答案也歡迎跟貼。
本人在此寫出本身對前6個問題的回答:
1, 使用linux epoll模型,水平觸發模式(Level-Triggered);當socket可寫時,會不停的觸發socket可寫的事件,如何處理?
第一種最普通的方式:
當須要向socket寫數據時,將該socket加入到epoll模型(epoll_ctl);等待可寫事件。
接收到socket可寫事件後,調用write()或send()發送數據。。。
當數據所有寫完後, 將socket描述符移出epoll模型。
這種方式的缺點是: 即便發送不多的數據,也要將socket加入、移出epoll模型。有必定的操做代價。
第二種方式,(是本人的改進方案, 叫作directly-write)
向socket寫數據時,不將socket加入到epoll模型;而是直接調用send()發送;
只有當或send()返回錯誤碼EAGAIN(系統緩存滿),纔將socket加入到epoll模型,等待可寫事件後,再發送數據。
所有數據發送完畢,再移出epoll模型。
這種方案的優勢: 當用戶數據比較少時,不須要epool的事件處理。
在高壓力的狀況下,性能怎麼樣呢?
對一次性直接寫成功、失敗的次數進行統計。若是成功次數遠大於失敗的次數, 說明性能良好。(若是失敗次數遠大於成功的次數,則關閉這種直接寫的操做,改用第一種方案。同時在日誌裏記錄警告)
在我本身的應用系統中,實驗結果數據證實該方案的性能良好。
事實上,網絡數據可分爲兩種到達/發送狀況:
一是分散的數據包, 例如每間隔40ms左右,發送/接收3-5個 MTU(或更小,這樣就沒超過默認的8K系統緩存)。
二是連續的數據包, 例如每間隔1s左右,連續發送/接收 20個 MTU(或更多)。
回來查了資料,發現如下兩種方式:
第三種方式: 使用Edge-Triggered(邊沿觸發),這樣socket有可寫事件,只會觸發一次。
能夠在應用層作好標記。以免頻繁的調用 epoll_ctl( EPOLL_CTL_ADD, EPOLL_CTL_MOD)。 這種方式是epoll 的 man 手冊裏推薦的方式, 性能最高。但若是處理不當容易出錯,事件驅動中止。
第四種方式: 在epoll_ctl()使用EPOLLONESHOT標誌,當事件觸發之後,socket會被禁止再次觸發。
須要再次調用epoll_ctl(EPOLL_CTL_MOD),纔會接收下一次事件。 這種方式能夠禁止socket可寫事件,應該也會同時禁止可讀事件。會帶來不便,同時並無性能優點,由於epoll_ctl()有必定的操做代價。
2, 從socket讀數據時,socket緩存裏的數據,可能超過用戶緩存的長度,若是處理?
能夠調用realloc(),擴大原有的緩存塊尺寸。
可是臨時申請內存的有必定性能損失。
這種狀況要看接收緩存的方式。
第一種方式: 使用100k的大接收緩存爲例。
若是要等待數據,並進行解析。可能發生緩存不夠的狀況。此時只能擴充緩存,或先處理100k的數據,再接收新的數據。
第二種方式: 使用緩存隊列,分紅8K大小的隊列。
不存在接收緩存不夠的狀況。 除非用戶解析已出錯,使用數據接收、使用脫勾。 這種方式的代價是,可能須要將緩存隊列再次拷貝、拼接成一塊大的緩存,再進行解析。 而在本人的系統中,只須要將socket接收的數據再次原樣分發給客戶, 因此這種方案是最佳方案。
3, 向socket發送數據時, 可能只發送了用戶緩存裏的一半,而後失敗,如何處理?
記錄緩存的偏移量。 下一次socket寫事件時, 再從偏移的位置接着發送。
那個面試官竟然對這個問題問了我兩次, 看來我解釋的不夠清晰。。。。。。 鬱悶。
4, C++的虛函數是怎麼實現的?
使用虛函數表。
回來查下資料: C++對象使用虛表, 若是是基類的實例,對應位置存放的是基類的函數指針;若是是繼承類,對應位置存放的是繼承類的函數指針(若是在繼承類有實現)。因此,當使用基類指針調用對象方法時,也會根據具體的實例,調用到繼承類的方法。
5, C++的虛函數有什麼做用?
虛函數做用是實現多態, 不少人都能理解這一點。但卻不會回答下面這一點。
更重要的,虛函數實際上是實現封裝,使得使用者不須要關心實現的細節。在不少設計模式中都是這樣用法,例如Factory、Bridge、Strategy模式。 前兩天在書上恰好看到這個問題,但在面試的時候卻沒想起來。
我的以爲這個問題能夠很好的區分C++的理解水平。
6, 非阻塞connect()如何實現?
將socket設置成non-blocking,操做方法同非阻塞read()、write();
面試官是在聽到我介紹以後,才問我這個問題。惋惜仍是問我兩遍。
此次面試, 總的來講準備不夠充足, 因此此次機會沒有青睞我! 也有其它一些問題: 1, 對於通常的面試提問, 老是想很簡要的回答完。由於對方可能原本就很清楚,因此本身就想一兩句話說完。 可是有時候這樣行不通。須要適當的回答清晰、完整一些。 2, 對TCP/UDP的問題原本是很熟悉的,但由於長時間沒複習,忘的差很少了。 3, 之前已經對RTSP進行了仔細的學習。 HTTP、SIP屬於同一類協議。而我卻回答不了HTTP的問題。努力學習啊................ 4, 有些問題要問我兩遍,說明個人表達確實不夠清晰。有的問題可能面試官本身並不清晰,因此除了表達清晰以外,徹底有必要適當的回答稍完整些。不然很難讓人滿意。 5, 精神狀態不太好,思惟有些慢了。 由於老是睡的晚。 接下來打算繼續研究 lighttpd源碼, 這樣對我本身的水平提升會有很大幫助。 機會老是青睞有準備的人! 期待下次。