程序员面试总结

岗位:后台开发,C/C++、JAVA

网络

  • HTTP1.1和HTTP1.0的区别,参考:http://blog.csdn.net/hguisu/article/details/8608888 
     持久连接–connection,一个tcp连接上可以传送多个请求; 
    host域–使用虚拟主机技术,这样可以区分一台主机上的多个应用; 
    增加了一些请求方法
  • HTTP的头部字段解析:http://www.cnblogs.com/xcsn/p/4308228.html
  • HTTP的状态码含义:1.信息,2.成功,3.重定向,4.客户端错误,5.服务器端错误,参考:http://www.w3school.com.cn/tags/html_ref_httpmessages.asp
  • TCP、UDP和IP报文的格式:http://blog.csdn.net/kernel_jim_wu/article/details/7447377
  • TCP的慢启动、快重传:tcp有一个接收窗口用于流量控制,窗口为1是停等协议,效率低下,如果窗口太大,那么可能会出现网络拥塞。所以拥塞控制依赖于拥塞窗口(cwnd)来进行控制。慢启动有点类似于车辆启动的时候,具体待阐述,参考:http://blog.csdn.net/loverooney/article/details/38323907
  • 多播协议、多播协议的应用场景:一点对多点,节省网络带宽;IP多播广泛应用在网络音频、视频中。依赖IP多播地址,是D类地址。
  • TCP连接三次握手、断开四次挥手的过程:三次握手:客户端发起请求(序列号)-服务器回应ack并给出自己的序列号-客户端回应ack。 断开四次挥手:一端发起断开(FIN),另外一端回应ack;这样一端的写就关闭了;另外一端发起断开请求(FIN),本端回应ack。这样双方都关闭了连接。因为一端关闭了写,但是另外一端可能还有数据要发送,所以两端可能不同时关掉连接,就出现了4次挥手的过程。
  • time_wait状态:tcp 4次挥手的过程中,主动关闭连接的一方,在收到对方的FIN包后会进入time_wait状态(2*MSL的时间),如果在这个时间段内,没有再次收到对面的FIN包,就表示ack已经成功到达。假想,如果没有这个状态,而是直接就是close状态的话,对面没有收到ack,重发FIN包,这边会发送RST包,导致server端收到rst包报错,影响程序进程; 并且假设没有time_wait状态,新的连接请求过来,老的关闭报文就会对新的连接产生干扰。 参考帖子:http://www.firefoxbug.com/index.php/archives/2795/
  • ping的实现:Ping类似于一个回声系统,发送一个请求、对端如果收到回应一个报文就可以判断了。这里采用ICMP(网际控制报文协议)来实现。发送一个ICMP的回送请求报文,对端如果收到,回应一个ICMP的回送请求和回送应答报文。利用的是IP的点对点的协议,并没有端到端,不需要端口这些,使用的是原始套接字(RAW).具体实现可以参考:http://blog.csdn.net/zzucsliang/article/details/41407387
  • traceroute的实现:traceroute是一个寻找到目的地路径的命令。同样是基于ICMP的回送请求报文配合TTL来实现。开始发送一个TTL=1的ICMP回送请求报文,到达一个路由器时,TTL-1=0,此时回应一个ICMP的超时报文,源端收到之后再发送一个TTL=2的报文,以此内推,直到到达目的地,目的端回应一个ICMP的回送应答报文。参考:http://blog.csdn.net/microtong/article/details/3220450
  • close和shutdown:参考:http://blog.liyiwei.cn/socket-%E7%BC%96%E7%A8%8B%E4%B8%ADclose%E5%92%8Cshutdown%E7%9A%84%E5%8C%BA%E5%88%AB/shutdown是优雅的关闭,会让所有数据发送完。·

编程/算法

  • gdb调试相关

    查看变量的二进制值:p /t 变量; 
    bt:列出函数调用栈; 
    info frame:查看当前栈的信息; 
    frame 帧号:切换帧; 
    gdb调试core文件:ulimit -c unlimited,gdb exec coreFile,运行至crash,会打印crash的信息,bt查看栈信息,一般都是段错误:访问了错误的内存段或者没权限,或者根本不存在对应的内存段;

  • 字符串中子字符串的替换:http://blog.csdn.net/songjinghao/article/details/11659051

  • ascii和Unicode、UTF-8的区别:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
  • 动态链接和静态链接:静态库:代码的装载速度快,执行速度也比较快,因为编译时它只会把你需要的那部分链接进去,应用程序相对比较大。但是如果多个应用程序使用的话,会被装载多次,浪费内存。动态链接可以动态的安装和卸载,更加灵活。
  • 如何写一个ORM框架:orm框架的作用是代替你去写sql语句,比如直接将一个对象插入到表中。 框架要有基本的接口(增删改查等接口),输入参数是需要处理的对象等,在接口中,通过反射,获取到我们需要的内容,比如类类型、字段、字段值等,然后拼凑sql语句,去执行sql语句,然后返回结果,释放资源即可。可以参考我的一个开源代码:https://github.com/zy416548283/JDBCSimpleORM/
  • 二叉查找树:定义,查找算法,最大、最小值,添加算法,删除算法,其中会有前驱和后继的相关查找,参考:http://blog.csdn.net/dc_726/article/details/7391869
  • extern C的作用:实现C/C++的混合编程,在C++中,指示编译器用C语言进行编译。参考:http://blog.csdn.net/jiqiren007/article/details/5933599
  • 判断结构体是否相等,可以考虑memcmp函数,逐字节比较。参考:http://www.cnblogs.com/cxz2009/archive/2010/11/11/1875125.html
  • 服务器端经常用到的shell命令:free -m(查看内存使用情况),fdisk -l(查看硬盘分区信息),iostat(查看硬盘的IO性能),uptime(查看服务器的平均负载),vmstat(查看服务器的整体性能),netstat(统计与网络相关的参数)等 参考:http://blog.jobbole.com/15430/http://www.cnblogs.com/linzhenjie/archive/2013/01/14/2859085.html
  • 堆排序:http://blog.csdn.net/morewindows/article/details/6709644/
  • 格雷码的递归编写:注意格雷码除了最高位是相反的以外,后面的都是对称的,可以通过递归很方便的写出n位格雷码,参考:http://fanli7.net/a/ITxinwen/google/2011/1206/150387.html
  • c++的虚函数实现多态的原理:有一个指向虚表的指针,如果子类覆盖了父类的虚函数,虚表里的指针也会覆盖,这样调用的时候就可以调用子类的函数了。参见:http://blog.csdn.net/haoel/article/details/1948051

操作系统

  • 阐述一下系统调用–参考帖子:http://blog.csdn.net/chosen0ne/article/details/7721550 
     要点:通过中断从用户态切换到内核态。中断有两个重要属性–中断号和中断处理程序,中断号表示不同的中断。中断号是一种很稀缺的资源。内核维护一张系统调用表,可以通过系统调用号,明确哪个系统调用,这样就完成了系统调用的函数名称转换。参数传递是通过寄存器完成的。用户态和内核态运行的进程使用的栈不同,栈切换是通过寄存器(栈指针,%esp)来回赋值,并且寄存器传参需要额外的保护和恢复过程。从上面可以看出系统调用很费时间:1. 系统调用通过中断实现,需要完成栈切换;2. 寄存器传参,需要额外的保存和恢复的过程。
  • 进程和线程的区别:进程是分配资源的基本单位(CPU、内存等),有独立的地址空间。线程是进程中的一个实体,共享进程的地址空间,是轻量级的进程,是CPU调度和分配的基本单位,但是各个线程拥有自己的栈空间。 使用多线程编程的好处:(1)单线程遇到阻塞,会卡死,影响交互;(2)发挥多核CPU的计算能力;(3)简化程序结构,使程序便于维护;(4)与进程相比,线程的创建和切换开销更小。 参考:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.htmlhttp://www.nowcoder.com/discuss/1836?type=&order=0&pos=56&page=0
  • linux下面的进程间通信方式:(1)管道:具有亲缘关系的进程通信,命名管道允许无亲缘关系的进程通信,shell命令中的”|”就是一种管道通信,一个命令的输出作为另外一个进程的输入;(2)信号:程序运行过程中可以随时被各种信号打断,从而去处理信号,Linux下面的kill命令就是通过信号的方式和其它进程通信,比如kill -l可以查看信号的分类,kill -9强制杀死对应进程;(3)消息队列:有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点;(4)共享内存:非常快的进程通信方式,和信号量结合起来,达到进程间的同步与互斥;(5)socket:套接字可以让不同主机之间的进程进行通信,肯定还会讲到,很重要。可以参考:http://www.cppblog.com/jerryma/archive/2011/08/03/152348.aspx
  • 线程之间同步的方式:因为线程之间共享内存,所以线程之间需要进行同步。同步的方式有互斥锁、条件变量、读写锁。互斥锁用于保护临界区;条件变量用于发送信号和等待信号;读写锁是在互斥锁的基础上做的改进,又被成为共享-独占,非常适合于读数据的频率远大于写数据的频率的应用。 参考:http://blog.csdn.net/hanchaoman/article/details/5628789
  • 孤儿进程:父进程先退出,子进程被init进程收养;僵尸进程:子进程退出,父进程并没有获取子进程的状态信息,子进程的状态描述符仍然存在系统中;守护进程:Linux的后台服务进程,比如crond等,不受终端控制,在系统启动时启动,在系统关闭时终止。
  • 内存分配策略:malloc,first fit、best fit,分配的时候自然会产生内存碎片,可以在若干次free之后进行碎片合并。http://blog.jqian.net/post/malloc.html
  • 一个malloc的实现:http://blog.codinglabs.org/articles/a-malloc-tutorial.html
  • 使用malloc要注意的事项:1.申请是否成功判断(不成功为null)2.申请成功之后,对内存区域赋初值;3. 使用时注意访问越界;4.使用之后,记得free释放掉;5.free掉之后,指针仍然指向原来的区域,置为NULL,防止再次使用。
  • 交换空间的作用:swap,交换空间可以有两种,交换分区(硬盘分区)和交换文件(没有多的分区情况下,使用文件代替)。交换空间,又叫虚拟内存,是指物理内存不够用的时候,将不常用的数据放到交换空间里,当需要的时候再将交换空间的内容换回物理内存,参考:http://blog.csdn.net/huaishu/article/details/8762957

并发编程

  • select和epoll的区别:select缺点就是epoll的优点。(1) 最大并发数限制;(2)效率不高,线性扫描全部的fd集合;(3)内核和用户空间数据拷贝,采用了内存拷贝。而epoll:(1)没有最大连接数的限制;(2)只管活跃的连接;(3)共享内存http://blog.csdn.net/tianmohust/article/details/6677985 然而select也有相对于epoll的优点:在大部分连接都是活跃的情况下,epoll的维护队列的开销要大一些。
  • 线程池:参考nginx引入线程池提升性能的例子:http://www.infoq.com/cn/articles/thread-pools-boost-performance-9x
  • 阻塞、非阻塞,同步、异步的区别:http://blog.csdn.net/klarclm/article/details/8828486
  • nginx的负载均衡策略:轮询、最少连接优先、ip地址哈希(同一客户端的web请求会到同一个服务器上,可以解决session的问题–一般解决是通过数据库持久化session,然后用分布式的数据库)、基于权重的负载均衡。参考:http://blog.chinaunix.net/uid-301743-id-4801730.html

数据库

  • 关系型数据库:存储的是具有格式化数据结构的数据;
  • mysql的两种主要存储引擎:Myisam和InnoDB(默认)。基本只要你写会用mysql,这个问题是必问的。myisam是不支持事务安全的,但是插入速度非常快,innoDB支持事务安全,但是插入速度相对较低。像12306这种涉及交易的网站,肯定会用到事务的。 具体可以看看视频的讲解:http://www.iqiyi.com/w_19rr0jh7o1.html
  • 事务、事务特点:事务是一个整体,不能分割,比如A向B转账100:A-100,B+100,这两步要一起执行。一起成功、一起失败。所以事务的特点是:ACID–原子性、一致性、隔离性、持久性。简单理解一下,原子性就是指一个事务要么执行,要么不执行;一致性是指事务的运行并不改变数据库中数据的一致性;隔离性是指两个以上的事务不会出现交错执行的状态,比如一个事务的操作结果不会让另外一个事务看到,直到完成;持久性是指事务运行成功以后,吃持久化存储的,不会无缘无故的回滚。
  • 范式:1范式–每一列不可分割;2范式–非主属性完全依赖于主属性;3范式:每一列数据都和主键直接相关,不能传递依赖于主键;
  • 数据库查询优化的常用技巧:(1)索引:优点是读速度快;带来的缺点是体积变大、插入性能变差(需要创建索引);(2)缓存配置(缓存查询语句,缓存查询数据);(3)分库分表,分表又分为垂直和水平拆分; (4)子查询优化。参考:http://blog.csdn.net/zwan0518/article/details/11972853
  • 数据库中高并发出现的悲观锁和乐观锁,悲观锁假设冲突率相当高,直接占有;而乐观锁假设冲突不是很高,读的时候有一个版本号,如果写的时候版本号与读取的版本号不一致,表示已经被人修改过,乐观锁可以用版本号和时间戳来实现。参考:http://www.cnblogs.com/Bob-FD/p/3352216.html
  • where 1=1和where 1=0语句的作用:where 1=1是在表单提交中如果有多个查询条件在拼凑sql语句时如果没有填查询条件时可能会出异常,这个语句规范了sql语句。 where 1=0,这个语句恒为false,表示不返回结果集,节省了内存,可以用于快速建表,比如:create table newtable as select * from oldtable where 1=0; 参考:http://www.cnblogs.com/junyuz/archive/2011/03/10/1979646.html
  • 数据库连接池:客户端调用数据库提供的服务,需要建立到数据库的tcp链接,然而建立链接是很耗时的,所以,我们可以使用一个池子(容器)来保存这些连接,客户端需要连接的时候,从连接池里取出可用连接即可,用完的时候,把连接放回池子就可以了。参考:http://it.deepinmind.com/db/2014/05/04/the-anatomy-of-connection-pooling.html
  • 存储过程:我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。优点是:灵活、可编程、执行速度快(预编译)、减少网络流量等。参考:http://blog.sina.com.cn/s/blog_52d20fbf0100ofd5.html
  • 左连接、右连接、等值连接:left join,会把左表中的数据全部显示出来,如果右表中有相等的也显示出来,没有的话,显示为NULL。右连接同样道理。等值连接是只取相等的。参考:http://blog.csdn.net/wyzxg/article/details/7276979

java/jvm

  • 回调函数:参考http://blog.csdn.net/xiaanming/article/details/8703708 写的很详细,分为同步回调、异步回调。
  • jvm内存回收3大步:回收哪些东西,什么时候回收,怎么回收。

闲聊

  • 你还有什么想问我的么? 如果是技术面的话,一般我会把这个当做结束语,很可能会跪,但也不绝对。面试前要对公司有一定的了解,面试所在部门的业务是什么? 部门的规模多大? 团队的氛围,对新人的培养模式? 待补充。。
  • 你有什么缺点:对于这个问题,有什么缺点可以说,但是要把缺点圆起来,比如说你怎么克服的? 想了一下,自己的缺点是“有时候不懂得合理的分配工作任务,觉得自己干起来效率高一些”,举一个例子,还是把工作模块化划分好,这样效率高一些。
  • 你的最大特点是什么? 身边同学朋友都怎么评价你的。。。根据自己情况来吧,平时也多总结一下自己,多反省一下。

转载自:http://blog.csdn.net/zy416548283/article/details/47136185


你可能感兴趣的:(编程,算法,面试,操作系统,gdb)