腾讯暑期实习面试问题总结--后台开发方向

  1. 操作系统相关
    1. 进程与线程:
      1. 一个进程至少包含一个线程,多个线程共享进程的内存空间(寄存器、堆栈、上下文);
      2. 进程是资源分配和调度的基本单位,线程是cpu调度的基本单位;
      3. 进程创建fork();线程创建是pthread_create();
      4. 进程摧毁会删除其中所有线程;而线程摧毁不会影响其他线程;
      5. 线程的私有属性:线程id、寄存器、线程控制块TCB、栈空间
      6. 进程的私有属性:进程id、进程控制块PCB
      7. 多线程要注意内存的保护,利用互斥锁、读写锁、信号量、条件变量机制;编写难度较高;
      8. 多线程占用内存比多进程要低;
    2. 进程空间:顺序从低地址到高地址:
      1. 文本段、程序段、TXT段:存放编译过的二进制代码;只读;共享内存;线程安全;
      2. Data段:在程序运行前已被初始化的全局变量;
      3. bss段:在程序运行前未被初始化的全局变量;
      4. 堆:手动分配;malloc、calloc等;
      5. 栈:从上往下自动分配内存;存储代码执行时的临时变量;存储函数执行的入口地址;
    3. 进程间通信、线程间通信:
      1. 进程间通信方式
        1. 管道:半双工通信,一个流动方向;只能用于父子进程/兄弟进程;
        2. 有名管道FIFO:半双工通信,可以用于任意进程间;
        3. 消息队列:独立于读数据和写数据;有不同的消息优先级;
        4. 共享内存:最快,需要信号量同步;
        5. 信号量:有一个可用资源,如果为0阻塞;不为0,则可用资源-1;
        6. socket:不同机器进程间通信;
      2. 线程间通信:
        1. 互斥量:
        2. 读写锁:有读锁和写锁;
        3. 信号量:
        4. 条件变量:满足条件后通过signal函数通知进程
      3. 原子操作:不会被线程调度打断的操作;可以是多个操作步骤;
    4. Linux常用命令
      1. https://blog.csdn.net/csdnxxm/article/details/105227684
    5. Linux目录分析
      1. /bin  :保存常见命令
      2. /boot :保存linux系统启动相关的文件,首先加载
      3. /dev :存放设备文件,外设、usb驱动等
      4. /etc :存放软件配置文件,安装samba过程中,会修改/etc/samba/samba.conf文件;
      5. /home :最常使用,每个用户默认空间在该目录下;
      6. /lib :保存系统的动态链接库;
      7. /media:光盘挂载点;
      8. /mnt:系统挂载点,一般插优盘需要挂载在这里;
      9. /proc :文件系统,保存所有文件信息,注意设备也是文件;如cpu、内存、io端口等;
      10. /root :root用户目录;
      11. /tmp:临时目录;
      12. /usr:系统软件安装目录;
      13. /var:动态文件/数据,如log文件;
    6. 编译过程
      1. 预处理:(1)将宏定义展开;(2)将头文件插入;(3)处理条件预编译指令;(4)删除注释;(5)添加行号;(6)保留#pragma 编译器指令;
      2. 编译:(1)词法分析(2)语法分析(3)语义分析(4)源代码优化
      3. 汇编:转换为汇编语言
      4. 链接:未解决符号重定位
        1. 静态链接:编译时完成;需要的函数被复制到相关位置;利用ar cr libxxx.a  xx.o命令生成;
        2. 动态链接:程序运行时重定位;g++ -fPIC(位置无关) -shared libXXX.so  XXX.o命令生成;
        3. 静态链接执行速度快,但是动态链接占用内存少,更有利于共享内存;
        4. 程序升级问题:静态链接改动就得重新编译,动态链接接口不变就不需要改动;
  2. 网络相关
    1. TCP三次握手
      1. A发送SYN=n的包,进入SYN_SEND状态;
      2. B返回一个SYN+ACK的包,SYN=m,ACK=n+1,进入SYN_RECV状态;
      3. A返回一个ACK包,ACK=m+1,进入established状态;B收到这个ack或者收到数据报文时进入established状态;所以三次握手最后一次可以丢包;
    2. TCP四次挥手
      1. A发送FIN包,进入FIN_Wait_1状态;
      2. B返回ACK包,进入Close_Wait状态;A收到这个ACK包后,进入FIN_WAIT_2状态;
      3. B发送FIN包,进入LAST_ACK状态;
      4. A收到FIN包,发送ACK包,进入TIME_WAIT状态;B收到ack后关闭进入closed状态;A等待2MSL时间后close;2倍的最大报文生存时间;30s,60s等;
    3. TCP字段
      1. 基本20字节,最多能扩展到60字节
      2. 2字节源端口号,2字节目的端口号
      3. 4字节SYN序列号
      4. 4字节ACK序列号
      5. 4位字段总大小offset,6位保留位,syn+ack+fin+org(紧急指针)+psh+rst(重连)标志包类型位;2字节滑动窗口;
      6. 2字节的校验和;2字节的紧急指针;
    4. 网络IO模型
      1. 四种IO模型
        1. 阻塞IO模型:执行recvfrom()函数后,阻塞,直到数据读到用户空间;
        2. 非阻塞IO模型:执行recvfrom()函数后,如无数据,立刻返回状态;循环执行查询操作,直到有数据,阻塞,数据读到用户空间;
        3. 多路IO模型:利用select/poll/epoll等函数阻塞查询有无数据,可以轮循的方式查询到多个链接;查询到后调用read函数阻塞获取数据;
        4. 异步IO模型:执行read函数,通知内核一个回调函数,立刻返回去做其他事务;内核收到数据,将数据拷贝到用户空间后,回调通知用户;  
        5. 注意:前三种为同步IO模型,数据都是用户阻塞从内核空间拷贝;而异步IO是内核完成这件事情;
      2. select函数:fd标识符保存在一个bitmap中,总数受限;fd每次使用完成后需要清零重新赋值;需要完成用户空间到内核空间的fd的拷贝;
      3. poll函数:fd标识符保存在结构体数组中,总数相对select大很多;不需要重新赋值;需要完成用户空间到内核空间的fd的拷贝;
      4. epoll函数:fd保存在结构体数组中,但是内存通过mmap映射到内核空间,相当于内存共享,不需要完成用户空间到内核空间的fd的拷贝;同时只处理活跃的fd,不同于select和poll要全部遍历fd;
    5. TCP拥塞控制
    6. 五层模型--从浏览器输入到获取内容,中间经历了什么?
      1. 域名解析:浏览器缓存、本地缓存、递归查询
      2. 构建HTTP请求包;
      3. 进行TCP连接,三次握手;
      4. 发送HTTP请求包--五层模型,逐层传递;
      5. 服务器返回一个重定向地址;返回1/3;
      6. 服务器返回页面框架,本地浏览器进行渲染;
      7. 继续请求页面中的其他元素;
      8. close连接;
    7. 负载均衡技术:
      1. HTTP重定向技术:负载均衡服务器;用户向该服务器请求时,服务器返回一个其他服务器的IP地址;302状态码;两次请求才能获取内容;--应用层
      2. DNS解析:在DNS服务器上为一个域名配置了多个IP地址;--应用层
      3. 先进行DNS均衡负载,在进行HTTP重定向;
      4. 应用层反向代理服务器:类似于重定向,但是它可以缓存部分常用数据;---应用层
      5. 数据链路层:均衡负载服务器修改mac地址,这样真正的服务器不用通过均衡负载服务器发送数据,而可以直接发送;
  3. 算法相关
    1. 求链表中点:快慢指针
    2. 求无序数组第K大数:快速排序
    3. 二叉树求最长路径:DFS+全局变量,求字树深度;
  4. 数据结构相关
    1. 数组和链表
      1. 都是顺序存储结构
      2. 数组地址空间连续,链表地址空间不连续
      3. 增:数组O(1)扩容O(n)、链表O(1)删:数组O(n)、链表O(1)改:数组O(1)、链表O(n)-O(1)查:数组O(1)、链表O(n)
      4. 数组插入、删除数据较慢;查找数据较快;
    2. 栈和队列
      1. 可以用数组也可以用链表
      2. 栈有一个指针,指向栈顶
      3. 队列两个指针,一个队首,一个队尾
      4. 栈先进后出,队列FIFO
    3. map底层实现:更多的是存储一个映射关系,有的需要排序,用数组实现更好一些;
      1. hashmap将作为一个node节点存储;
      2. 利用hash(key)计算数组存储位置,每个位置处可能是一个链表;
      3. 内存不够时进行扩容,重新计算位置;
    4. hash冲突:
      1. 开放定址法:线性探测、二次探测、随机探测
      2. 再次hash法:不同的hash函数
      3. 链地址法:hashmap
    5. LRU缓存设计:需求put()、get()
      1. 需要删除中间、最末尾元素:链表
      2. 添加元素
      3. 读取元素:用hash定位
  5. c/c++语言相关
    1. 写memcpy()函数:注意地址覆盖
    2. inline函数
      1. 用于函数体较短时,避免复杂的环境变量入栈操作、PC计数器、寄存器等;
      2. 直接将函数体展开到调用函数的位置;
      3. 与宏定义的区别:宏定义编译器不进行检查,inline函数会检查;
    3. static关键字
      1. 修饰变量:只能初始化一次,占用的静态变量区,不是栈,不随函数退出而销毁;
      2. 修饰函数:只能在本文件中使用,其他文件不能引用;
      3. 修饰对象成员:所有对象公用这一个成员,属于类,不属于某个具体的对象;
      4. 修饰成员函数:操作静态成员变量;
    4. const关键字
      1. 修饰一个变量,表明不可修改;
      2. 修饰函数参数:函数中该参数/该参数指向的内容不可修改;
      3. const只修饰后面的变量,注意*要跟后面的连起来;
    5. 多态、虚函数

你可能感兴趣的:(腾讯暑期实习面试问题总结--后台开发方向)