前段时间专心面过腾讯,通过了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源码, 这样对我本身的水平提升会有很大帮助。 机会老是青睐有准备的人! 期待下次。