面试经验总结记录

本文是作者的面试经验总结,涵盖了操作系统、计算机网络、数据结构和C++等关键知识点。在操作系统方面,讨论了高并发的本质、线程池的工作原理、线程同步与进程通信方式、内存管理和LRU算法。计算机网络部分涉及UDP可靠传输、IP分片、TCP的可靠传输机制、SSL握手流程等。数据结构部分讲解了排序算法,如选择排序、冒泡排序等。C++部分涉及了函数指针、虚函数实现机制、智能指针等概念。此外,还介绍了HTTP的基本格式、GET和POST的区别以及cookie的作用。

面试经验总结记录

操作系统

1、高并发的本质是什么

​ 充分利用多核CPU,解决IO速度和CPU速度的冲突 ,当碰到IO或者其他情况的阻塞的时候,如果是单线程会导致整个程序阻塞,但多线程可以有其他线程继续利用CPU资源继续工作

2、进程池,线程池,连接池(更偏向于JAVA的问题)

线程池创建的时候需要定义

  • 核心线程数大小(正常工作使用的线程数)
  • 最大线程数(当核心不能满足需求时,扩容能够扩展的最大线程)
  • 线程存活时间(超出核心线程数的线程维持时间)
  • 任务队列(用于存放等待的任务)
  • 拒绝策略(当队列已满,线程数达到最大还有新的任务进来)

3、线程池的扩充和删除

当任务队列已满,线程达到最大时,可以采用扩容策略进行扩容,动态增加核心线程数和最大线程数以满足任务数量的需求

线程池预热,线程池创建完成后,池里是没有线程的,所以需要预热

怎么让线程池的线程阻塞(suspend阻塞,resume唤醒)

4、线程同步的方式

  • 互斥量(只有一个线程能够访问)
  • 信号量(n个线程能够访问)
  • 条件变量

5、进程通信方式

  • 管道(匿名管道,父子进程单向流通,命名管道利用文件系统)
  • 系统IPC(消息队列,信号量,共享内存)
  • socket
  • 信号

6、进程的同步互斥方式

​ 信号量,消息队列,管程(通过只能在管程内部使用的条件变量来提供同步)

7、线程安全

通过加锁对临界区进行保护

8、锁的类型

互斥锁(只允许一个线程访问)

条件锁(条件变量,满足条件则唤醒)

自旋锁(忙等,不释放资源直到条件满足)

原子锁(原子操作,锁内不会被中断)

读写锁(读可重入,写会阻塞)

悲观锁(每次写入数据都假设其他线程会更改数据,因此需要加锁)

悲观锁又包括共享锁(也叫读锁,可以读,不能写)

也包括排它锁(也叫写锁,其他事务无法进入)

乐观锁(直到数据提交才加锁)

公平锁(多个线程通过申请的顺序进入队列排队,排第一位的能够获得锁)缺点:吞吐量低,其余线程都阻塞。

非公平锁(直接获取锁,获取不到才进行排队)缺点:可能会饥饿

9、LRU算法(最近最少使用)

利用固定大小的双向链表,将已存在被访问的数据或新加入数据放在链表头,如果长度超标,删除链表尾的数据

LFU(最近不经常使用)

10、逻辑地址和物理地址的映射

浅析逻辑地址与物理地址映射关系_朱里安-优快云博客_逻辑地址到物理地址的映射

11、汇编角度的函数调用逻辑,push ebp,mov ebp,esp

12、怎么从硬盘中拿到想要的数据,通过段表或页表

13、内存泄露怎么检测,怎么解决

泄露类型:(1)堆泄露,malloc分配的空间没有释放

​ (2)系统资源泄露,socket资源没有释放

检查方案:(1)BoundsChecker

(2)windows平台,利用crt库

(3)Linux平台,利用valgrind

14、用户态调用fopen后发生了什么

15、TLB的作用

作为页表的cache

通过TLB可以直接将虚拟内存映射到物理内存,不需要访问页表

16、浮点数的存储方式,符号位,指数位,小数位

17、用户态进入核心态

(1)系统调用

(2)异常

(3)外设中断

计算机网络

1、用udp实现可靠传输功能

2、IP的分片机制

(1)DF=0,允许分片

(2)MF=1,后续还有分片,MF=0,最后一个分片

(3)片偏移,单位是8字节

3、IP报文格式,TCP报文格式

4、TCP的可靠传输,流量控制,拥塞控制

拥塞控制:慢开始,拥塞避免,快重传,快恢复

5、TCP的timewait有什么用

(1)最后发送的ACK对方可能没有收到,如果对方没有收到会继续重发FIN,这时TimeWait状态会回复ACK并重置等待时间2MSL,

(2)对方发送的数据包可能由于网络原因还没有到达,这时还会继续接受数据包

6、证书的内容

7、为什么要三次握手

(1)通信双方都需要有能力发送信息并且接受回应的过程

(2)如果第二次后认为连接成功,服务器主动发送数据,而第二次握手可能会丢失,客户端就无法正常接受数据,三次握手的话,这种情况会进行第二次的重发

8、read,write的底层实现

9、IO复用,select和epoll的具体功能和实现

select将所有已连接的Socket都放到一个文件描述符的集合中,然后调用select函数将文件描述符拷贝到内核中,通过内核来检查是否有网络事件的发生,检查到后,将Socket标记为可读或可写,然后将整个文件描述符拷贝回用户态,再通过用户态遍历找到可读或可写的socket再处理

select利用固定长度的BitsMap来表示文件描述符集合,默认长度FD_SETSIZE 1024

poll用链表组织文件描述符集合,长度可以更大,但具体思路是一样的

epoll在内核中利用红黑树来跟踪进程的文件描述符,利用事件驱动的机制,在内核维护了一个链表来记录就绪事件,当有事件发生,可以通过回调函数将其加入列表中

epoll中提供ET边缘触发,当被监控的socket中有可读事件触发,服务器会从epoll_wait中苏醒一次,没有read结束也只会苏醒一次,因此必须要一次读完

LT水平触发,服务器会不断从缓冲区中读数据,读完才结束

10、ssl握手流程

clienthello(支持加密套件)

server_key_exchange(协商密钥),server_certificate(签名证书),server_hello_done(加密套件)

client_key_exchange(协商密钥)

change_cipher_spec(接下来用会话密钥加密),finished(hash,握手完成)

数据结构

1、LSM树

提高写性能,牺牲一部分读性能,让写操作顺序化

2、字典树

3、位图

排序算法

都是从小到大

选择排序

排序方案:每次选择最小的数与无序的第一位进行交换,交换的位置变为有序

优化方案:可以一次得到最大和最小两个数,节省一半时间

时间复杂度:O(n^2)

空间复杂度:O(1)

冒泡排序

排序方案:每次比较相邻两个数,如果第二个比第一个小,就交换

时间复杂度:O(n^2)

空间复杂度:O(1)

插入排序

排序方案 :把第一个元素当做有序数列,从第二个元素开始扫描未排序数列,将其插入有序数列中

时间复杂度:O(n^2)

空间复杂度:O(1)

希尔排序

排序方案:对待排序数组根据一定的增量分成多个子序列,对每个子序列进行插入排序,对增量进行递减到增量为1,则直接插入排序,相当于是插入排序的优化方案

时间复杂度:小于O(n^2)

空间复杂度:O(1)

快速排序

排序方案:找到一个数字基准,将比这个基准小的移动到左边,比他大的移动到右边,每轮该基准都能找到自己的最终位置

时间复杂度:O(nlogn)

空间复杂度:O(1)

归并排序
堆排序
C++

1、C++不能重载的符号

  • . 成员访问运算符
  • .* 成员指针访问运算符
  • :: 域运算符
  • sizeof 长度运算符
  • ?: 条件运算符

2、map,unordered_map,set有什么相同点和区别

map基于红黑树,有序,log(n)的查找效率

unordered_map基于hash表,无序,O(1)的查找效率,但不稳定,依赖于hash碰撞

3、回调机制

通过给函数传函数指针,触发事件时调用

4、函数指针 void(*pfun)(int);

5、虚函数实现机制

6、delete this

(1)this对象必须用new分配(而不是用new[],也不是用placement new,也不是局部对象,也不是global对象)

(2)delete this之后,不能访问该对象任何的成员变量和虚函数

(3)delete this之后,不能访问this指针

7、右值引用

延长右值对象的生命周期

8、对齐

9、static和const的作用

10、智能指针

shared_ptr

unique_ptr

weak_ptr

11、四种强制类型转换

const_cast 只能改变const

static_cast 任何具有明确定义的类型转换,不包含const

reinterpret_cast 位模式提供的较低层次的转换

dynamic_cast 类类型的转换,必须有虚函数

Base* base = new Derived;
Derived *der = dynamic_cast<Derived*>(base);

12、new和malloc的区别

  • *最重要的。new进行类类型分配,会调用类的构造函数,利用delete进行释放会调用析构函数,而malloc没有
  • *次重要。new[],delete[]可以进行数组的分配处理,malloc无
  • 申请内存位置。new为自由存储区,具体位置需要看编译器,malloc为堆
  • 返回类型安全性。new返回对象类型指针,类型匹配,malloc返回void*,需要强转
  • 失败返回。new抛出异常,malloc返回NULL
  • 内存大小分配。new不需要指定大小,直接按类型分配,malloc需要自定义分配大小
HTTP
1、具体格式

请求报文

请求行,请求头,请求体

请求行(主要包括GET,POST,HEAD,PUT,DELETE等请求类型,结构为请求类型,url,http类型)

请求头(结构为,key: value,包括cookie,编码类型,主机名称,支持的语言类型,连接保持情况,客户端版本号,接受压缩类型,接收的资源类型)

请求体(包括请求的具体数据,对于GET请求,内容一般直接放在url中,请求体为空,而POST的请求内容都放在请求体中)

响应报文

状态行,响应头,响应体

状态行(结构为http类型,状态码,状态信息,状态码:1xx(信息性)2xx(成功)3xx(重定向)4xx(客户端错误)5xx(服务器错误))(4,5到底有什么区别)

响应头(结构也为 key:value 包括cookie设置)

响应体(包括客户端请求的数据,类型为MIME type,包括text/plain,text/html等等)

2、GET和POST的区别

GET,请求参数全放到url中,这样请求长度就受到了限制

GET一般用于获取信息,可缓存,而POST用于修改数据,不可缓存

POST一般会有更多的请求头,需要说明其请求体部分,某些客户端的实现会让POST先发送头部再发送请求体,这样会导致POST的速度比get慢,但这种发两次包不是必须的

3、cookie的作用

由服务器发送给客户端,用于记录用户身份,下次再建立连接时一起发送cookie,服务器就知道客户端的身份了

弊端:

cookie的数量和长度有限制,存在安全问题,cookie可能会被第三方截获转发

MYSQL

1、索引底层实现是利用BTtree或者Hash或者B+Tree实现

​ BTree是一棵多叉平衡树,B+Tree只有叶子节点存放数据

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值