已通过
自我介绍
问项目
问基础知识
虚拟内存是什么有什么用?(因为我在项目提到了内存缺页算法LRU)
函数调用是怎么实现的?(因为我项目有编译器,就回答了一下栈结构,函数参数返回值压栈弹栈之类的,细节忘了)
堆、栈、寄存器哪些是线程独有的,哪些事线程共享的?(不会,想了一会儿回答寄存器肯定是独有的因为涉及到CPU环境切换,堆栈不确定,又想了一下回答了堆栈也是独有的,他说好的没关系,应该是答错了。。)
两个线程都执行a++100次,a的结果是多少?(犹豫了半天还是说了200,感觉不能这么简单吧)
答案应该是2~200(https://blog.csdn.net/speargod/article/details/96651069)
tcp四次挥手为什么比三次握手多一次?(服务器要把没传完的数据传完才能再发起FIN请求)
网络拥塞、拥塞控制、流量控制相关知识。
打开一个网页的过程?(主要回答了域名解析的过程)
https和http的区别?(加了个SSL实现加密传输)
SSL是怎么实现加密传输的?(大概说了一下,先用非对称加密交换通信秘钥,然后用通信秘钥进行对称加密通信)
http的错误码?(不怎么了解,看我皱了下眉头就说没关系不问了)
数据库里的事务是什么?
用户输入密码怎么保证安全?(没搞懂他想问的是什么。。)
讨论:用户在PC登陆微信时,可以用手机扫码登陆,这是怎么实现的,想聊什么聊什么。
算法题
大鱼吃小鱼问题
一个数字序列,每个元素都代表一条鱼,正数表示鱼向右游,负数表示向左游,数字的绝对值代表鱼的体积,如果两条鱼相撞则大鱼会吃掉小鱼,如果相撞的两条鱼大小相等则都会死亡。鱼游的速度都相同,问最后剩下哪些鱼?
写了个n^2的暴力算法,应该还可以优化。。最后简单说了一下优化的思路,细节没想清楚也不确定对不对,面试官就说差不多了,没有让继续写下去。
优化思路: 开一个数组记录鱼的存活状态,初始值是全true。 从左往右遍历的时候记录一个值表示往右游的鱼的最大值,遇到一个往右游的就更新一下最大值,遇到一个往左游的就比较大小。 如果往左游的小那就被吃掉,反之认为左边所有往右游的鱼都会被这条往左游的鱼吃掉(因为最大的都比它小),则将最大值置为0继续往右遍历,一直遍历到结尾。 然后从右往左反方向遍历一遍,做同样的操作。
面试官是真的好,很和善,会引导你回答问题。
堆、栈、寄存器哪些是线程独有的,哪些事线程共享的?
堆:是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe的。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
寄存器这里不太确定,因为寄存器数量是有限的,所以每个线程在执行时应该用的都是这些寄存器,所以从这个角度来说好像是共享的。但是每个线程执行时寄存器的内容是不能被别的线程访问的,所以应该又是独有的。。。总的来说寄存器应该是独有的吧。。。
函数调用是怎么实现的?

栈帧,也就是stack frame,其本质就是一种栈,只是这种栈专门用于保存函数调用过程中的各种信息(参数,返回地址,本地变量等)。栈帧有栈顶和栈底之分,其中栈顶的地址最低,栈底的地址最高,SP(栈指针)就是一直指向栈顶的。在x86-32bit中,我们用 %ebp 指向栈底,也就是基址指针;用 %esp 指向栈顶,也就是栈指针。下面是一个栈帧的示意图:

一般来说,我们将 %ebp 到 %esp 之间区域当做栈帧(也有人认为该从函数参数开始,不过这不影响分析)。并不是整个栈空间只有一个栈帧,每调用一个函数,就会生成一个新的栈帧。在函数调用过程中,我们将调用函数的函数称为“调用者(caller)”,将被调用的函数称为“被调用者(callee)”。在这个过程中,1)“调用者”需要知道在哪里获取“被调用者”返回的值;2)“被调用者”需要知道传入的参数在哪里,3)返回的地址在哪里。同时,我们需要保证在“被调用者”返回后,%ebp, %esp 等寄存器的值应该和调用前一致。因此,我们需要使用栈来保存这些数据。