添加Linux 内核的同步方式、主机字节序与网络字节序、为什么TCP三次握手、为什么TCP四次挥手、TCP有效状态机

This commit is contained in:
huihut 2018-03-25 18:19:58 +08:00
parent fb47f60a0d
commit b26b8bec2a
3 changed files with 143 additions and 4 deletions

147
README.md
View File

@ -265,6 +265,10 @@ int main() {
1. 默认的继承访问权限。struct是public的class是private的。 1. 默认的继承访问权限。struct是public的class是private的。
2. struct作为数据结构的实现体它默认的数据访问控制是public的而class作为对象的实现体它默认的成员变量访问控制是private的。 2. struct作为数据结构的实现体它默认的数据访问控制是public的而class作为对象的实现体它默认的成员变量访问控制是private的。
### C实现C++类
[C语言实现封装、继承和多态](http://dongxicheng.org/cpp/ooc/)
### explicit (显式)构造函数 ### explicit (显式)构造函数
explicit修饰的构造函数可用来防止隐式转换 explicit修饰的构造函数可用来防止隐式转换
@ -1087,6 +1091,26 @@ typedef struct BiTNode
> 进程线程部分知识点来源于:[进程线程面试题总结](http://blog.csdn.net/wujiafei_njgcxy/article/details/77098977) > 进程线程部分知识点来源于:[进程线程面试题总结](http://blog.csdn.net/wujiafei_njgcxy/article/details/77098977)
### Linux 内核的同步方式
#### 原因
在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。
#### 同步方式
* 原子操作
* 信号量semaphore
* 读写信号量rw_semaphore
* 自旋锁spinlock
* 大内核锁BKLBig Kernel Lock
* 读写锁rwlock
* 大读者锁brlock-Big Reader Lock
* 读-拷贝修改(RCURead-Copy Update)
* 顺序锁seqlock
> 来自[Linux 内核的同步机制,第 1 部分](https://www.ibm.com/developerworks/cn/linux/l-synch/part1/)、[Linux 内核的同步机制,第 2 部分](https://www.ibm.com/developerworks/cn/linux/l-synch/part2/)
### 死锁 ### 死锁
#### 产生条件 #### 产生条件
@ -1110,6 +1134,58 @@ typedef struct BiTNode
* WindowsFCB表 + FAT + 位图 * WindowsFCB表 + FAT + 位图
* Unixinode + 混合索引 + 成组连接 * Unixinode + 混合索引 + 成组连接
### 主机字节序与网络字节序
#### 主机字节序CPU字节序
##### 概念
主机字节序又叫CPU字节序其不是由操作系统决定的而是由CPU指令集架构决定的。主机字节序分为两种
* 大端字节序Big Endian高序字节存储在低位地址低序字节存储在高位地址
* 小端字节序Little Endian高序字节存储在高位地址低序字节存储在低位地址
##### 存储方式
32位整数0x12345678是从起始位置为0x00的地址开始存放
内存地址 | 0x00 | 0x01 | 0x02 | 0x03
---|---|---|---|---
大端|78|56|34|12
小端|12|34|56|78
##### 判断大端小端
可以这样判断自己CPU字节序是大端还是小端
```cpp
#include <iostream>
using namespace std;
int main()
{
int i = 0x12345678;
if (*((char*)&i) == 0x12)
cout << "大端" << endl;
else
cout << "小端" << endl;
return 0;
}
```
##### 各架构处理器的字节序
* Intel、AMDX86架构小端
* ARMARM架构大端小端都支持默认是小端
* IBM、MotorolaPowerPC架构大端
#### 网络字节序
网络字节顺序是TCP/IP中规定好的一种数据表示格式它与具体的CPU类型、操作系统等无关从而可以保重数据在不同主机之间传输时能够被正确解释。
网络字节顺序采用大端Big Endian排列方式。
## 计算机网络 ## 计算机网络
计算机经网络体系结构: 计算机经网络体系结构:
@ -1122,7 +1198,7 @@ typedef struct BiTNode
---|---|--- ---|---|---
物理层 | 通过媒介传输比特确定机械及电气规范比特Bit | RJ45、CLOCK、IEEE802.3(中继器,集线器) 物理层 | 通过媒介传输比特确定机械及电气规范比特Bit | RJ45、CLOCK、IEEE802.3(中继器,集线器)
数据链路层|将比特组装成帧和点到点的传递帧Frame| PPP、FR、HDLC、VLAN、MAC网桥交换机 数据链路层|将比特组装成帧和点到点的传递帧Frame| PPP、FR、HDLC、VLAN、MAC网桥交换机
网络层|负责数据包从源到宿的传递和网际互连包PackeT|IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP路由器 网络层|负责数据包从源到宿的传递和网际互连包Packet|IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP路由器
运输层|提供端到端的可靠报文传递和错误恢复段Segment|TCP、UDP、SPX 运输层|提供端到端的可靠报文传递和错误恢复段Segment|TCP、UDP、SPX
会话层|建立、管理和终止会话会话协议数据单元SPDU|NFS、SQL、NETBIOS、RPC 会话层|建立、管理和终止会话会话协议数据单元SPDU|NFS、SQL、NETBIOS、RPC
表示层|对数据进行翻译、加密和压缩表示协议数据单元PPDU|JPEG、MPEG、ASII 表示层|对数据进行翻译、加密和压缩表示协议数据单元PPDU|JPEG、MPEG、ASII
@ -1294,17 +1370,80 @@ UDP 首部
> TCP/UDP 图片来源于:<https://github.com/JerryC8080/understand-tcp-udp> > TCP/UDP 图片来源于:<https://github.com/JerryC8080/understand-tcp-udp>
#### TCP 与 UDP 的区别
1. TCP面向连接UDP是无连接的
2. TCP提供可靠的服务也就是说通过TCP连接传送的数据无差错不丢失不重复且按序到达UDP尽最大努力交付即不保证可靠交付
3. TCP的逻辑通信信道是全双工的可靠信道UDP则是不可靠信道
5. 每一条TCP连接只能是点到点的UDP支持一对一一对多多对一和多对多的交互通信
6. TCP面向字节流可能出现黏包问题实际上是TCP把数据看成一连串无结构的字节流UDP是面向报文的不会出现黏包问题
7. UDP没有拥塞控制因此网络出现拥塞不会使源主机的发送速率降低对实时应用很有用如IP电话实时视频会议等
8. TCP首部开销20字节UDP的首部开销小只有8个字节
#### TCP传输连接管理 #### TCP传输连接管理
> 因为TCP三次握手建立连接、四次挥手释放连接很重要所以附上《计算机网络第7版-谢希仁》书中对此章的详细描述:<https://github.com/huihut/interview/blob/master/images/TCP-transport-connection-management.png>
##### TCP 三次握手建立连接 ##### TCP 三次握手建立连接
![UDP报文](images/TCP三次握手建立连接.png) ![UDP报文](images/TCP三次握手建立连接.png)
##### TCP 四次握手释放连接 【TCP建立连接全过程解释】
![UDP报文](images/TCP四次握手释放连接.png) 1. 客户端发送SYN给服务器说明客户端请求建立连接
2. 服务端收到客户端发的SYN并回复SYN+ACK给客户端同意建立连接
3. 客户端收到服务端的SYN+ACK后回复ACK给服务端表示客户端收到了服务端发的同意报文
4. 服务端收到客户端的ACK连接已建立可以数据传输。
> 因为TCP三次握手建立连接、四次握手释放连接很重要所以附上《计算机网络第7版-谢希仁》书中对此章的详细描述:<https://github.com/huihut/interview/blob/master/images/TCP-transport-connection-management.png> ##### TCP为什么要进行三次握手
【答案一】因为信道不可靠而TCP想在不可靠信道上建立可靠地传输那么三次通信是理论上的最小值。而UDP则不需建立可靠传输因此UDP不需要三次握手。
> [Google Groups . TCP建立连接为什么是三次握手{技术}{网络通信}](https://groups.google.com/forum/#!msg/pongba/kF6O7-MFxM0/5S7zIJ4yqKUJ)
【答案二】因为双方都需要确认对方收到了自己发送的序列号,确认过程最少要进行三次通信。
> [知乎 . TCP 为什么是三次握手,而不是两次或四次?](https://www.zhihu.com/question/24853633/answer/115173386)
【答案三】为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
> [《计算机网络第7版-谢希仁》](https://github.com/huihut/interview/blob/master/images/TCP-transport-connection-management.png)
##### TCP 四次挥手释放连接
![UDP报文](images/TCP四次挥手释放连接.png)
【TCP释放连接全过程解释】
1. 客户端发送FIN给服务器说明客户端不必发送数据给服务器了请求释放从客户端到服务器的连接
2. 服务器接收到客户端发的FIN并回复ACK给客户端同意释放从客户端到服务器的连接
3. 客户端收到服务端回复的ACK此时从客户端到服务器的连接已释放但服务端到客户端的连接还未释放并且客户端还可以接收数据
4. 服务端继续发送之前没发完的数据给客户端;
5. 服务端发送FIN+ACK给客户端说明服务端发送完了数据请求释放从服务端到客户端的连接就算没收到客户端的回复过段时间也会自动释放
6. 客户端收到服务端的FIN+ACK并回复ACK给客户端同意释放从服务端到客户端的连接
7. 服务端收到客户端的ACK后释放从服务端到客户端的连接。
##### TCP为什么要进行四次挥手
【问题一】TCP为什么要进行四次挥手 / 为什么TCP建立连接需要三次而释放连接则需要四次
【答案一】因为TCP是全双工模式客户端请求关闭连接后客户端向服务端的连接关闭一二次挥手服务端继续传输之前没传完的数据给客户端数据传输服务端向客户端的连接关闭三四次挥手。所以TCP释放连接时服务器的ACK和FIN是分开发送的中间隔着数据传输而TCP建立连接时服务器的ACK和SYN是一起发送的第二次握手所以TCP建立连接需要三次而释放连接则需要四次。
【问题二】为什么TCP连接时可以ACK和SYN一起发送而释放时则ACK和FIN分开发送呢ACK和FIN分开是指第二次和第三次挥手
【答案二】因为客户端请求释放时服务器可能还有数据需要传输给客户端因此服务端要先响应客户端FIN请求服务端发送ACK然后数据传输传输完成后服务端再提出FIN请求服务端发送FIN而连接时则没有中间的数据传输因此连接时可以ACK和SYN一起发送。
【问题三】为什么客户端释放最后需要TIME-WAIT等待2MSL呢
【答案三】
1. 为了保证客户端发送的最后一个ACK报文能够到达服务端。若未成功到达则服务端超时重传FIN+ACK报文段客户端再重传ACK并重新计时。
2. 防止已失效的连接请求报文段出现在本连接中。TIME-WAIT持续2MSL可使本连接持续的时间内所产生的所有报文段都从网络中消失这样可使下次连接中不会出现旧的连接报文段。
#### TCP 有限状态机
![TCP的有限状态机](images/TCP的有限状态机.png)
### 应用层 ### 应用层

View File

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB