chinaunix:腾讯面试题

腾讯电商面试回来,发现我太菜了,缺乏技术深度。

笔试题感觉不难,但是做了之后总是发觉少点什么东西,深度!这是这场面试总结出来的。

凭记忆分享下笔试,面试题。大家一起解决,然后分享下该看什么书,可以解决这些“深度”问题。

1.内存池算法。
我就把前段时间看到的tcmalloc实现大概写了一遍。

Q:malloc怎么实现的?
A:通过brk,sbrk实现的。
Q:sbrk,brk怎么实现的?sbrk,brk怎么由内核态切换到系统(用户?)态的?

2.怎么定位内存泄露?
我写的是:
1.使用valgrind --这个东西从来没用过
2.mtrace
3.封装malloc,free函数的宏
5./proc/$pid/下的内存相关的文件,监控里面的vss(RSS?忘记是哪个了)的变化。确定是那个进程或线程的vss增加,然后走读进程或者线程的代码。

3.tcp为什么要第三次握手,time_wait是做什么的?
我写的是:
第三次握手是client对server的ack回应。time_wait是为了解决2msl的,什么什么幻影镜像。

4.strace什么什么cgi。 (cgi不会,所以只记得strace)

Q:strace怎么实现的?
A:ptrace
Q:ptrace怎么实现的?

5.ip如何在A,B地址间路由?

6.tcp/ip有几种状态,现场划出所有的状态转换图。
哪里记得这么多,都是netstat看到不懂的状态,然后翻书看状态转换图的。

7.有一张表,表结构如下
序列字段(主键,序列号),
后面的字段记不清了。
当这张表达到1000万数据量时,怎么优化,提高存储性能。

8.虚函数是怎么实现的?
虚函数的n年前研究过啊,当时还记得特意做实验破坏虚函数表来着。面试时就什么都不会了。

9.stl map是怎么实现的,时间复杂度是多少? --这道题,难道要通读<<stl源码剖析>>

10.还有一道服务器负载的题,不会,所以也没记住。

电商的面试官都这么牛,这还是俺第一次遇到这么有广度,有深度的面试,不过也特打击我了。请问各位大侠,该看什么书,才可以搞定这些问题。
其他部门也面试过了,问的问题都相对简单,就电商的特有难度,特有广度。

再补充一个:
11.release和debug版本程序有什么区别,debug信息存储在哪里(提示elf文件)?



1.内存池算法。

基本思想大家都懂:

一个大内存池, 若干不同block_size的小内存池, 以及被分配出去的block.

内存管理基本两个套路:
1, block头部预留内存用于记录元信息以及索引(freelist), 优点就是用户不用记录这个block当初申请的是多大的, 另外减少了一些归还block时的计算开销.
2, block无预留内存, 归还过程与分配过程一致, 需要用户提交block_size, 并且freelist需要外部分配内存对block进行管理.

Q:malloc怎么实现的?

1, 小内存分配有缓存, 但由于基于page的内存管理, 所以小块内存可能造成页内内存浪费, 即碎片, 另外程序占用内存提升即便释放也不会回降, 这是由于malloc内部缓存引起的, 需要与内存泄漏进行区分.
2, 大内存申请会用mmap可能造成缺页引起IO造成程序阻塞, 所以面临大内存频繁申请的需求应该考虑缓存内存块并重用.

具体malloc如何实现, 曾经也了解过, 但没有刻意的记忆, 既然特别清晰的认识我就不瞎说了, 只能说点上面工作中的经验.

2.怎么定位内存泄露?

1, 首先跑测试, 确认是内存泄漏, 以及泄漏的节奏如何, 是阶梯状泄漏还是陡坡状? 什么测试情景下泄漏, 明确涉及到的模块范围, 是否是大压力造成的任务堆积的误判? 反复压力, 如果内存只升不降, 基本可定位为内存泄漏.
2, 抱着测试结论, 先valgrind跑memcheck, 一般带--trace-original=yes --leak-check=full --log-file=xxx --verbose, 由于挂valgrind会导致程序跑慢, 相应压力下内存堆积也会严重一些, 属正常现象.
3, 使用valgrind排查内存问题, 最好保证程序支持优雅退出(释放所有资源), 并且必须先停测试压力, 待进程稳定后才关闭valgrind.
4, 查看valgrind输出报告, 先确认summary中没有error, 并通过多次valgrind执行, 比较summary中内存泄漏是否与执行时间有关, 并逐条check各警告, 结合测试结论与valgrind输出定位问题.

3.tcp为什么要第三次握手,time_wait是做什么的?
3次握手是为了初始化syn序列号,
1, synA
2, synB + ack A
3, ack B

time_wait是本端主动FIN的情况下发生的, 搞开发这个必须知道, 并且也应该知道linger直接RST可以避免这个问题, 这个状态简单说就是对端发FIN后, 本端处于的一个状态, 这个状态下的端口是没法重用的. 这也是我们的监听套接字为什么reuseaddr再bind的理由.

不过time_wait这个选项持续的时间会对短连接客户端程序不利, 因为端口可能无法重用造成无法继续新建连接, 所以一般线上机内核都要优化一些TCP参数.

4.strace

估计是strace让你跟php-cgi吧, 毕竟是作电商的.

5.ip如何在A,B地址间路由?

路由器配置有路由表, 查看目标ip属于哪个网段, 能找到对应的网段则看是否能arp到目标机, 不能就就往这个网段的默认网关丢.

路由当然就是基于ip&mask看看是否匹配某网段, 下面还会有一级一级的路由划分子网与聚合.

6.tcp/ip有几种状态,现场划出所有的状态转换图。

不就是上面说的3路握手,4路挥手吗.

7.有一张表,表结构如下
序列字段(主键,序列号),
后面的字段记不清了。

在线扩容啊, 称原先的mysql是A, 先开上9个mysql进程, 把最近一次库A备份导入, 然后全部设置slave of A同步A的binlog, 然后客户端(dbproxy)就可以切向这9+A共10个库了, 请求按哈希散列, 现在不同主键的操作会落在不同进程上, 可以把slave of都关掉了, 实际上即便不关闭slave of, 客户端在A上的操作对于其他9个进程来说也是不关心的, slave过去也没关系.

然后可以把共10个进程里无关数据(哈希不同)进行小批量多次删除(晚上操作), 最后给每个mysql进程上若干只读slave, 切一下dbproxy配置就可以了.

8.虚函数是怎么实现的?
多态, 取代了c语言的type+switch, 对象里有一个指针(我们通常认为在头部, 与继承结构古有关), 指针指向一个函数数组,里面记录的是派生类的函数地址, 调用基类指针时就可以根据这个函数数组就能调用的正确的实现.

9.stl map是怎么实现的,时间复杂度是多少?

红黑树啊, lg(n)啊, 树太深了一样慢的要死, STL又没提供哈希表,

10.还有一道服务器负载的题,不会,所以也没记住。

原文地址:https://www.cnblogs.com/code-style/p/3332518.html