操作系统与计算机网络
操作系统
进程与线程
- 进程与线程的区别和联系
- 进程是系统资源分配的最小单位,线程是程序执行的最小单位
- 进程使用独立的数据空间,而线程共享进程的数据空间
- 线程调度,线程的几种调度算法
- 时间片轮转算法
- 先来先服务调度
- 优先级调度
- 多级反馈队列调度
- 高响应比优先调度
- 线程切换步骤,线程上下文切换,线程切换的代价
- 进程间通信,IPC,6种进程通信方式的原理与适用场景。
- 进程间数据共享的场景可以使用共享内存
- 进程间数据交换的场景可以使用Unix Socket或消息队列
- 协程,协程更加轻量化,是在用户态调度,切换的代价比线程上下文切换要低很多,Java的第三方协程框架,Kilim、Quasar
Linux常用命令
- AWK:处理文本文件的语言,是一个很强大的文件分析工具
- Top
- netstat
- grep
扩展知识点(待补充)
- 内存分页管理
- Swap机制
- 任务队列
CPU Load
内存屏障
- 指令乱序
- 分支预测
- NUMA
- CPU亲和性
计算机网络
网络模型
网络的4/7层模型
HTTP协议
- HTTP协议规范,Method、Header、Cookies,常见的状态码含义,404 502 503
- HTTPS的交互流程
- HTTP2多路复用、Stream流式交互,流量控制 、服务端推送、头部压缩等新特性
TCP协议
- 三次握手建立连接
- 四次挥手断开连接
- TCP的报文状态标志和链接状态
- Nagel算法和ACK延迟,产生的背景,要解决小包问题,提高数据载荷比,对延迟比较敏感且发送数据频率低的场景可以关闭Nagel算法
- TCP的KeepAlive,是一种长时间没有数据发送的场景下,TCP保持链接可用的机制,TCP KeepAlive开启和设置的方式
- TCP是如何通过滑动窗口机制来实现流量控制的
UDP
非链接、非可靠传输、效率非常高
QUIC协议
QUIC已被标准化为HTTP3协议,QUIC基于UDP协议,但QUIC提供了类似TCP的可靠性保证和流量控制,有效的避免了HTTP2协议的前序包阻塞的问题
能实现零RTT建连,提供FEC前向纠错能力。这是什么鬼一点都看不懂呀
TCP协议特点
TCP是传输层协议,对应OSI网络模型的第四层传输层,特点如下:
- TCP协议是基于链接的,也就是传输数据前需要先建立 好链接,然后再进行传输
- TCP链接一旦建立 ,就可以在链接上进行双向的通信
- TCP的传输是基于字节流而不是报文,将数据按字节大小进行编号 ,接收端通过ACK来确认收到的数据编号 ,通过这种机制,TCP协议能够保证接收数据 的有序性和完整性,因此TCP能够提供可靠性的传输
- TCP还能提供流量控制能力,通过滑动窗口来控制 数据的发送速率,滑动窗口的本质是动态缓冲区,接收端根据自己的处理能力在TCP的Header中动态调整窗口的大小,通过ACK应答包通知给发送端,发送端根据窗口大小调整发送的速度
- 仅仅有流量控制 能力还不够,TCP协议还考虑到网络问题可能会导致大量重传,进而导致网络情况进一步恶化,因此TCP协议还提供了拥塞控制 ,TCP处理拥塞控制 主要用到慢启动,拥塞避免、拥塞发生、快速恢复四个算法
特定场景下,Nagel和ACK延迟机制配合使用可能会出现delay40ms超时后才回复ACK包的问题
三次握手建连
TCP是基于链接的,所以在传输数据前需要先建立链接,TCP在传输上双工传输,不区分Client端与Server端,我们把主动发起建连请求的一端称作Client端,把被动态建立链接的一端称作Server端
- 首先建立 链接前需要Server端先监听端口,因此Server端建立 链接前的初始状态就是LISTEN状态,这时Client端准备建立链接,先发送一个SYN同步包,发送完同步包后,Client端的链接状态就变成了SYN_SENT状态.Server端收到SYN后,同意建立链接,会向Client端回复一个ACK。
- 由于TCP是双工传输,Server端也会同时向Client端发送一个SYN,申请 Server向Client方向建立链接,发送完ACK和SYN后,Server端链接状态就变成了SYN_RCVD.
- Client收到Server的ACK后,Client端的链接状态就变成ESTABLISHED状态,同时Client向Server端发送ACK,回复Server端的SYN请求。
- Server端收到Client端的ACK后,Server端的链接状态也就变成了ESTABLISHED状态,此时建连完成,双方随时可以进行数据传输。
SYN洪水攻击发生的原因,就是Server端收到Client端的SYN请求后,发送了ACK和SYN,但是Client端不进行回复,导致Server端大量的链接处在SYN_RCVD状态,进而影响其他正常请求的建连。可以通过设计tcp_synack_retries=0 加快半链接的回收速度,或者调大tcp_max_syn_backlog来应对少量的SYN洪水攻击 。
四次挥手断连
TCP 链接的关闭通信双方都可以先发起,我们暂且把先发起的一方看作 Client。
- 通信中 Client 和 Server 两端的链接都是 ESTABLISHED 状态,然后 Client 先主动发起了关闭链接请求,Client 向 Server 发送了一个 FIN 包,表示 Client 端已经没有数据要发送了,然后 Client 进入了 FIN_WAIT_1 状态。
- Server 端收到 FIN 后,返回 ACK,然后进入 CLOSE_WAIT 状态。此时 Server 属于半关闭状态,因为此时 Client 向 Server 方向已经不会发送数据了,可是 Server 向 Client 端可能还有数据要发送。
- 当 Server 端数据发送完毕后,Server 端会向 Client 端发送 FIN,表示 Server 端也没有数据要发送了,此时 Server 进入 LAST_ACK 状态,就等待 Client 的应答就可以关闭链接了。
- Client 端收到 Server 端的 FIN 后,回复 ACK,然后进入 TIME_WAIT 状态。TIME_WAIT 状态下需要等待 2 倍的最大报文段生存时间,来保证链接的可靠关闭,之后才会进入 CLOSED 关闭状态。而 Server 端收到 ACK 后直接就进入 CLOSED 状态。
Q:为什么需要等待2倍最大报文段生存时间之后再关闭链接?
- 保证TCP协议的全双工连接能够可靠关闭
- 保证这次连接的重复数据段从网络中消息,防止端口被重用时可能产生的数据混淆
从这个交互流程可以看出,无论是建连还是断链,都是需要在两个方向上进行,只不过建连时,Server 端的 SYN 和 ACK 合并为一次发送,而断链时,两个方向上数据发送停止的时间可能不同,所以不能合并发送 FIN 和 ACK。这就是建连三次握手而断链需要四次的原因。
实际应用中有可能遇到大量 Socket 处在 TIME_WAIT 或者 CLOSE_WAIT 状态的问题。一般开启 tcp_tw_reuse 和 tcp_tw_recycle 能够加快 TIME-WAIT 的 Sockets 回收;而大量 CLOSE_WAIT 可能是被动关闭的一方存在代码 bug,没有正确关闭链接导致的。