├── .gitignore ├── Computer Network.md ├── Database.md ├── Design Pattern.md ├── Git-ComdLine-REST.md ├── LICENSE ├── Operating Systems.md ├── Python Handbook.md ├── README.md └── _v_images ├── 1588679646408-22276075-76c2-42b2-8b20-84e3401fdbf7.png ├── 1588681690229-615d93e2-9429-42cc-812e-fa8cb7eb49a4.png ├── 1588687137859-38493900-8c93-43ef-bbe7-c67c14e9ba75.png ├── 1588689300339-c33a3d0d-7544-4754-8695-b08fc843183d.png ├── 1588746617916-a21ed08c-42df-40c0-bc79-6701209c2f55.png ├── 1588760917772-e4e10a15-0c43-456e-88f2-279fdd3e2d12.png ├── 1588761010089-ced9b3a9-3232-4729-943a-67c133909d7c.png ├── 1588762859910-c08b6230-8358-42e8-aa48-5835af2d2940.png ├── 1588776261625-d6b2f2b2-85c7-4752-ba71-ac38f9ca639c.png ├── 1588776769193-d3a6ae4a-83d5-4fbf-b187-339039a22f25.png ├── 1588778531181-f78a0447-263d-40cf-bbfd-dfc565997dcd.png ├── 1588820461937-2a508c21-4203-4629-bcc1-ca0750f9fe84.png ├── 1588839044031-1dcdb9c4-a7c0-43b0-af86-4fb919336801.png ├── 1588841461626-35402966-4817-4f7c-bc64-7fa4dbfc6a84.png ├── 1588846767979-ce72003e-375a-4eea-8d13-eed6b726aa3b.png ├── 1588848682603-c5da8658-bbda-4c63-9c3f-f9bc80a93299.png ├── 1588850989407-80696883-cc5d-472b-a4de-0d5f5edd4cc4.png ├── 1588858153516-9c6b4ce0-aa41-42c4-b4c5-ae14e7faae51.png ├── 1588859146567-662ae183-11ae-475d-8d8d-a8549f3d4026.png ├── 1588860191434-2b5ff1d1-06e8-4036-8f95-0adfe7e383c1.png ├── 1588861529453-aa147daa-653f-4559-b2ee-fdb0a370bf11.png ├── 1588862264475-f62b4542-a18a-410e-b841-96049a3f2b44.png ├── 1588863690354-5649da92-3741-4812-9f63-b5b7d0960238.png ├── 1615897397.gif ├── 20191129101827556_21212.png ├── 20191129112652915_15481.png ├── 20191129145400104_2106.png ├── 20191129153624025_28293.png ├── 20191129155345024_11142.png ├── 20191129161026032_32431.png ├── 20191129195451183_16713.png ├── 20191201081919108_30577.png ├── 20191201085151639_2895.png ├── 20191202090217863_1873.png ├── 20191202162008435_14938.png ├── 20191207081711185_20242.png ├── 20191228182659294_7488.jpg ├── 20191228182911371_900.png ├── 20191228183019711_10018.png ├── 20191229101924303_17994.png ├── 20191229111930083_22798.png ├── 20191229112508482_31766.png ├── 20191229113357178_17374.png ├── 20191229144622659_9248.png ├── 20200516165618.png ├── 20200516165630.png ├── 202205271711368.png ├── 202205271711882.png ├── 202205271711967.png ├── 202205271712003.png ├── 202205271712893.png ├── 202205281423439.png ├── 202205281424550.gif ├── image-20221212004219997.png ├── image-20221212004254912.png ├── image-20221212012139142.png ├── image-20221216124728525.png ├── image-20221216124900832.png ├── image-20221216125001462.png └── image-20221216125538480.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | */.DS_Store 3 | .idea/ 4 | -------------------------------------------------------------------------------- /Computer Network.md: -------------------------------------------------------------------------------- 1 | # 计算机网络 2 | 3 | 4 | * 传输层:TCP和UDP 5 | * [什么是三次握手?](#什么是三次握手-three-way-handshake) 6 | * [什么是四次挥手?](#什么是四次挥手) 7 | * [TCP如何实现流量控制?](#TCP如何实现流量控制) 8 | * [TCP的拥塞控制是怎么实现的?](#TCP的拥塞控制是怎么实现的) 9 | * [TCP如何最大利用带宽?](#TCP如何最大利用带宽) 10 | * [TCP与UDP的区别](#TCP与UDP的区别) 11 | * [TCP如何保证传输的可靠性](#TCP如何保证传输的可靠性) 12 | * [~~什么是TCP粘包?~~](#什么是TCP粘包) 13 | * 应用层:HTTP和HTTPS 14 | * [HTTP和HTTPS有什么区别?](#HTTP和HTTPS有什么区别) 15 | * [GET与POST的区别?](#GET与POST的区别) 16 | * [Session与Cookie的区别?](#Session与Cookie的区别) 17 | * [从输入网址到获得页面的过程 (越详细越好)?](#从输入网址到获得页面的过程-越详细越好) 18 | * [HTTP请求有哪些常见状态码?](#HTTP请求有哪些常见状态码) 19 | * [什么是RIP (距离矢量路由协议)?](#什么是RIP-Routing-Information-Protocol-距离矢量路由协议-算法是什么) 20 | * [计算机网络体系结构](#计算机网络体系结构) 21 | * 网络层协议 22 | * [IP地址的分类?](#IP地址的分类) 23 | * [什么叫划分子网?](#什么叫划分子网) 24 | * [什么是ARP协议?](#什么是ARP协议-Address-Resolution-Protocol) 25 | * [什么是NAT (网络地址转换)?](#什么是NAT-Network-Address-Translation-网络地址转换) 26 | * [参考](#参考) 27 | 28 | 29 | ------ 30 | 31 | ### 什么是三次握手 (three-way handshake)? 32 | 33 | ![image-20221212004219997](_v_images/image-20221212004219997.png) 34 | 35 | - 第一次握手:Client将SYN置1,随机产生一个初始序列号seq发送给Server,进入SYN_SENT状态; 36 | - 第二次握手:Server收到Client的SYN=1之后,知道客户端请求建立连接,将自己的SYN置1,ACK置1,产生一个acknowledge number=sequence number+1,并随机产生一个自己的初始序列号,发送给客户端;进入SYN_RCVD状态; 37 | - 第三次握手:客户端检查acknowledge number是否为序列号+1,ACK是否为1,检查正确之后将自己的ACK置为1,产生一个acknowledge number=服务器发的序列号+1,发送给服务器;进入ESTABLISHED状态;服务器检查ACK为1和acknowledge number为序列号+1之后,也进入ESTABLISHED状态;完成三次握手,连接建立。 38 | 39 | ##### TCP建立连接可以两次握手吗?为什么? 40 |
41 | 展开 42 | 43 | 不可以。有两个原因: 44 | 45 | 首先,可能会出现**已失效的连接请求报文段又传到了服务器端**。 46 | 47 | > client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用 “三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采用 “三次握手” 的办法可以防止上述现象发生。例如刚才那种情况,client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。 48 | 49 | 其次,两次握手无法保证Client正确接收第二次握手的报文(Server无法确认Client是否收到),也无法保证Client和Server之间成功互换初始序列号。 50 | 51 | 还有就是两次握手会给SYN flood攻击提供机会。 52 | 扩展阅读: 什么是SYN攻击?https://zhuanlan.zhihu.com/p/360479307 53 |
54 | 55 | ##### 可以采用四次握手吗?为什么? 56 |
57 | 展开 58 | 59 | 可以。但是会降低传输的效率。 60 | 61 | 四次握手是指:第二次握手:Server只发送ACK和acknowledge number;而Server的SYN和初始序列号在第三次握手时发送;原来协议中的第三次握手变为第四次握手。出于优化目的,四次握手中的二、三可以合并。 62 |
63 | 64 | ##### 第三次握手中,如果客户端的ACK未送达服务器,会怎样? 65 | 66 |
67 | 展开 68 | 69 | Server端: 70 | 由于Server没有收到ACK确认,因此会重发之前的SYN+ACK(默认重发五次,之后自动关闭连接进入CLOSED状态),Client收到后会重新传ACK给Server。 71 | 72 | Client端,两种情况: 73 | 1. 在Server进行超时重发的过程中,如果Client向服务器发送数据,数据头部的ACK是为1的,所以服务器收到数据之后会读取 ACK number,进入 establish 状态 74 | 2. 在Server进入CLOSED状态之后,如果Client向服务器发送数据,服务器会以RST包应答。 75 |
76 | 77 | ##### 如果已经建立了连接,但客户端出现了故障怎么办? 78 |
79 | 展开 80 | 81 | 服务器每收到一次客户端的请求后都会重新复位一个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。 82 |
83 | 84 | ##### 初始序列号是什么? 85 |
86 | 展开 87 | 88 | TCP连接的一方A,随机选择一个32位的序列号(Sequence Number)作为发送数据的初始序列号(Initial Sequence Number,ISN),比如为1000,以该序列号为原点,对要传送的数据进行编号:1001、1002...三次握手时,把这个初始序列号传送给另一方B,以便在传输数据时,B可以确认什么样的数据编号是合法的;同时在进行数据传输时,A还可以确认B收到的每一个字节,如果A收到了B的确认编号(acknowledge number)是2001,就说明编号为1001-2000的数据已经被B成功接受。 89 |
90 | 91 | ### 什么是四次挥手? 92 | 93 | ![image-20221212004254912](_v_images/image-20221212004254912.png) 94 | 95 | - 第一次挥手:Client将FIN置为1,发送一个序列号seq给Server;进入FIN_WAIT_1状态; 96 | - 第二次挥手:Server收到FIN之后,发送一个ACK=1,acknowledge number=收到的序列号+1;进入CLOSE_WAIT状态。此时客户端已经没有要发送的数据了,但仍可以接受服务器发来的数据。 97 | - 第三次挥手:Server将FIN置1,发送一个序列号给Client;进入LAST_ACK状态; 98 | - 第四次挥手:Client收到服务器的FIN后,进入TIME_WAIT状态;接着将ACK置1,发送一个acknowledge number=序列号+1给服务器;服务器收到后,确认acknowledge number后,变为CLOSED状态,不再向客户端发送数据。客户端等待2*MSL(报文段最长寿命)时间后,也进入CLOSED状态。完成四次挥手。 99 | 100 | ##### 为什么不能把服务器发送的ACK和FIN合并起来,变成三次挥手(CLOSE_WAIT状态意义是什么)? 101 | 102 |
103 | 展开 104 | 105 | 因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复ACK,表示接收到了断开连接的请求。等到数据发完之后再发FIN,断开服务器到客户端的数据传送。 106 |
107 | 108 | ##### 如果第二次挥手时服务器的ACK没有送达客户端,会怎样? 109 | 110 |
111 | 展开 112 | 113 | 客户端没有收到ACK确认,会重新发送FIN请求。 114 |
115 | 116 | ##### 客户端TIME_WAIT状态的意义是什么? 117 | 118 |
119 | 展开 120 | 121 | 第四次挥手时,客户端发送给服务器的ACK有可能丢失,TIME_WAIT状态就是用来重发可能丢失的ACK报文。如果Server没有收到ACK,就会重发FIN,如果Client在2*MSL的时间内收到了FIN,就会重新发送ACK并再次等待2MSL,防止Server没有收到ACK而不断重发FIN。 122 | 123 | MSL(Maximum Segment Lifetime),指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。 124 |
125 | 126 | ### TCP如何实现流量控制? 127 | 128 | ![滑动窗口](_v_images/20191129145400104_2106.png) 129 | 130 | 使用滑动窗口协议实现流量控制。防止发送方发送速率太快,接收方缓存区不够导致溢出。接收方会维护一个接收窗口 receiver window(窗口大小单位是字节),接受窗口的大小是根据自己的资源情况动态调整的,在返回ACK时将接受窗口大小放在TCP报文中的窗口字段告知发送方。发送窗口的大小不能超过接受窗口的大小,只有当发送方发送并收到确认之后,才能将发送窗口右移。 131 | 132 | 发送窗口的上限为接受窗口和拥塞窗口中的较小值。接受窗口表明了接收方的接收能力,拥塞窗口表明了网络的传送能力。 133 | 134 | ![滑动窗口](_v_images/1615897397.gif) 135 | 136 | ##### 什么是零窗口(接收窗口为0时会怎样)? 137 | 138 |
139 | 展开 140 | 141 | 如果接收方没有能力接收数据,就会将接收窗口设置为0,这时发送方必须暂停发送数据,但是会启动一个持续计时器(persistence timer),到期后发送一个大小为1字节的探测数据包,以查看接收窗口状态。如果接收方能够接收数据,就会在返回的报文中更新接收窗口大小,恢复数据传送。 142 |
143 | 144 | ### TCP的拥塞控制是怎么实现的? 145 | 146 | ![拥塞控制](_v_images/image-20221216125001462.png) 147 | 148 | 拥塞控制主要由四个算法组成:**慢启动(Slow Start)、拥塞避免(Congestion voidance)、快重传 (Fast Retransmit)、快恢复(Fast Recovery)** 149 | 150 | 1. 慢启动:刚开始发送数据时,先把拥塞窗口(congestion window)设置为一个最大报文段MSS的数值,每收到一个新的确认报文之后,就把拥塞窗口加1个MSS。这样每经过一个传输轮次(或者说是每经过一个往返时间RTT),拥塞窗口的大小就会加倍 151 | 152 | ![慢启动](_v_images/image-20221216124728525.png) 153 | 154 | 2. 拥塞避免:当拥塞窗口的大小达到慢开始门限(slow start threshold)时,开始执行拥塞避免算法,拥塞窗口大小不再指数增加,而是线性增加,即每经过一个传输轮次只增加1MSS. 155 | > 无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢开始门限ssthresh设置为出现拥塞时的发送方窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。**(这是不使用快重传的情况)** 156 | 157 | 3. 快重传:快重传要求接收方在收到一个失序的报文段后就立即发出**重复确认**(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。 158 | 159 | ![快重传](_v_images/image-20221216124900832.png) 160 | 161 | 4. 快恢复:当发送方连续收到三个重复确认时,就把慢开始门限减半,然后执行拥塞避免算法。不执行慢开始算法的原因:因为如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方认为现在网络可能没有出现拥塞。 162 | 也有的快重传是把开始时的拥塞窗口cwnd值再增大一点,即等于 ssthresh + 3*MSS 。这样做的理由是:既然发送方收到三个重复的确认,就表明有三个分组已经离开了网络。这三个分组不再消耗网络的资源而是停留在接收方的缓存中。可见现在网络中减少了三个分组。因此可以适当把拥塞窗口扩大些。 163 | 164 | ### TCP如何最大利用带宽? 165 | 166 | TCP速率受到三个因素影响 167 | 168 | - 窗口:即滑动窗口大小,见[TCP如何实现流量控制?](#TCP如何实现流量控制) 169 | - 带宽:这里带宽是指单位时间内从发送端到接收端所能通过的“最高数据率”,是一种硬件限制。TCP发送端和接收端的数据传输数不可能超过两点间的带宽限制。发送端和接收端之间带宽取所通过线路的带宽最小值(如通过互联网连接)。 170 | - RTT:即Round Trip Time,表示从发送端到接收端的一去一回需要的时间,TCP在数据传输过程中会对RTT进行采样(即对发送的数据包及其ACK的时间差进行测量,并根据测量值更新RTT值),TCP根据得到的RTT值更新RTO值,即Retransmission TimeOut,就是重传间隔,发送端对每个发出的数据包进行计时,如果在RTO时间内没有收到所发出的数据包的对应ACK,则任务数据包丢失,将重传数据。一般RTO值都比采样得到的RTT值要大。 171 | 172 |
173 | 带宽时延乘积 174 | 175 | 带宽时延乘积=带宽*RTT,实际上等于发送端到接收端单向通道的数据容积的两倍,这里单向通道的数据容积可以这样来理解,单向通道看成是一条单行道马路,带宽就是马路的车道数,路上跑的汽车就是数据(不过这里所有汽车的速率都是一样的,且不会有人想超车,大家齐头并进),那么单向通道的数据容积就是这条单行道上摆满车,一共可以摆多少辆。带宽就是马路的车道数,带宽数乘以单向通道的数据容积就是路面上所能容纳的全部数据量。当路面上已经摆满的时候,就不能再往里面放了。 176 |
177 | 178 | 设滑动窗口大小为![](https://latex.codecogs.com/svg.latex?W), 发送端和接收端的带宽为![](https://latex.codecogs.com/svg.latex?B), RTT为![](https://latex.codecogs.com/svg.latex?T_r)。 179 | 180 | 前面已经说过了,TCP发送数据时受滑动窗口的限制,当TCP将滑动窗口中的数据都发出后,在收到第一个ACK之前,滑动窗口大小是0,不能再发送数据了,必须等待ACK包使滑动窗口移动。那么在理想情况下,ACK包应该在什么时候到达呢?显然,就是在数据发出后的RTT时间后,ACK包到达。这也就是说,现在在不考虑丢包和拥塞情况下,TCP在一个RTT时间内能发出的最大数据量为 ![](http://latex.codecogs.com/gif.latex?W) ,所以不考虑带宽限制下,TCP能一个时刻能达到的最大速度是 ![](https://latex.codecogs.com/svg.latex?V=\frac{W}{T_r})。 181 | 182 | 现在再考虑带宽限制,前面说过当马路上摆满车的时候,就无法再往里放车了,同理,TCP发送端在 ![](https://latex.codecogs.com/svg.latex?\frac{T_r}{2}) 时间内,能往通道上放的最大数据量为 ![](https://latex.codecogs.com/svg.latex?\frac{V*T_r}{2}) ,通过带宽时延乘积得到的容积限制为 ![](https://latex.codecogs.com/svg.latex?\frac{B*T_r}{2})。当 ![](https://latex.codecogs.com/svg.latex?\frac{B*T_r}{2}%20\geq%20\frac{V*T_r}{2}) 时,单向通道容积不构成瓶颈,速率的限制主要来源于窗口大小限制。而当 ![](https://latex.codecogs.com/svg.latex?\frac{V*T_r}{2}%20\geq%20\frac{B*T_r}{2}) 时,则就受到容积限制,即此时速率限制来源于带宽限制。 183 | 184 | 因此,TCP的最大速率为 ![](https://latex.codecogs.com/svg.latex?V%20=%20\min{(\frac{W}{T_r},%20B)}) 185 | 186 | 在我们平时生活中使用的宽带网络,ADSL等环境下,因为带宽都比较小,从而 ![](https://latex.codecogs.com/svg.latex?B*T_r) 也比较小,再加上网络情况比较复杂,拥塞情况比较常见,所以这些网络环境下,TCP速率的主要限制因素在于带宽,丢包率等。长肥管道一般不太常见,多见于一些单位使用的专线网络,在这些网络中速率的主要限制因素就是窗口大小了,这也是传统TCP在这些网络环境中不能充分利用带宽的原因所在(因为传统TCP的窗口大小是用2字节表示的,所以最大只有65535(不考虑窗口扩大选项)),除了专线网络外,随着网络硬件技术的发展,万兆交换机的出现,局域网中也可能会出现带宽时延乘积较大的情况。 187 | 188 | ### TCP与UDP的区别 189 | 190 | 1. TCP是面向连接的,UDP是无连接的; 191 |
192 | 什么叫无连接? 193 | 194 | UDP发送数据之前不需要建立连接 195 |
196 | 197 | 2. TCP是可靠的,UDP不可靠; 198 |
199 | 什么叫不可靠? 200 | 201 | UDP接收方收到报文后,不需要给出任何确认 202 |
203 | 204 | 3. TCP只支持点对点通信,UDP支持一对一、一对多、多对一、多对多; 205 | 4. TCP是面向字节流的,UDP是面向报文的; 206 |
207 | 什么意思? 208 | 209 | 面向字节流是指发送数据时以字节为单位,一个数据包可以拆分成若干组进行发送,而UDP一个报文只能一次发完。 210 |
211 | 212 | 5. TCP有拥塞控制机制,UDP没有。网络出现的拥塞不会使源主机的发送速率降低,这对某些实时应用是很重要的,比如媒体通信,游戏; 213 | 6. TCP首部开销(20字节)比UDP首部开销(8字节)要大 214 | 7. UDP 的主机不需要维持复杂的连接状态表 215 | 216 | ##### 什么时候选择TCP,什么时候选UDP? 217 | 218 |
219 | 展开 220 | 对某些实时性要求比较高的情况,选择UDP,比如游戏,媒体通信,实时视频流(直播),即使出现传输错误也可以容忍;其它大部分情况下,HTTP都是用TCP,因为要求传输的内容可靠,不出现丢失 221 |
222 | 223 | ##### HTTP可以使用UDP吗? 224 | 225 |
226 | 展开 227 | HTTP不可以使用UDP,HTTP需要基于可靠的传输协议,而UDP不可靠 228 | 229 | 注:**http 3.0 使用udp实现** 230 | https://zh.wikipedia.org/wiki/HTTP/3 231 |
232 | 233 | ##### 面向连接和无连接的区别 234 | 235 |
236 | 展开 237 | 238 | 无连接的网络服务(数据报服务)-- 面向连接的网络服务(虚电路服务) 239 | 240 | 虚电路服务:首先建立连接,所有的数据包经过相同的路径,服务质量有较好的保证; 241 | 242 | 数据报服务:每个数据包含目的地址,数据路由相互独立(路径可能变化);网络尽最大努力交付数据,但不保证不丢失、不保证先后顺序、不保证在时限内交付;网络发生拥塞时,可能会将一些分组丢弃; 243 | 244 | ![virtual circuit](_v_images/20191201081919108_30577.png) 245 |
246 | 247 | ### TCP如何保证传输的可靠性 248 | 249 | 1. 数据包校验 250 | 2. 对失序数据包重新排序(TCP报文具有序列号) 251 | 3. 丢弃重复数据 252 | 4. 应答机制:接收方收到数据之后,会发送一个确认(通常延迟几分之一秒); 253 | 5. 超时重发:发送方发出数据之后,启动一个定时器,超时未收到接收方的确认,则重新发送这个数据; 254 | 6. 流量控制:确保接收端能够接收发送方的数据而不会缓冲区溢出 255 | 256 | ### HTTP和HTTPS有什么区别? 257 | 258 | 1. 端口不同:HTTP使用的是80端口,HTTPS使用443端口; 259 | 2. HTTP(超文本传输协议)信息是明文传输,HTTPS运行在SSL(Secure Socket Layer)之上,添加了加密和认证机制,更加安全; 260 | 3. HTTPS由于加密解密会带来更大的CPU和内存开销; 261 | 4. HTTPS通信需要证书,一般需要向证书颁发机构(CA)购买 262 | 263 | ##### Https的连接过程? 264 |
265 | 展开 266 | ![image-20221212012139142](_v_images/image-20221212012139142.png) 267 | 268 | 269 | 1. 客户端向服务器发送请求,同时发送客户端支持的一套加密规则(包括对称加密、非对称加密、摘要算法); 270 | 2. 服务器从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,**加密公钥**(用于非对称加密),以及证书的颁发机构等信息(证书中的私钥只能用于服务器端进行解密); 271 | 3. 客户端验证服务器的合法性,包括:证书是否过期,CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配; 272 | 4. 如果证书受信任,或者用户接收了不受信任的证书,浏览器会生成一个**随机密钥**(用于对称算法),并用服务器提供的公钥加密(采用非对称算法对密钥加密);使用Hash算法对握手消息进行**摘要**计算,并对摘要使用之前产生的密钥加密(对称算法);将加密后的随机密钥和摘要一起发送给服务器; 273 | 5. 服务器使用自己的私钥解密,得到对称加密的密钥,用这个密钥解密出Hash摘要值,并验证握手消息是否一致;如果一致,服务器使用对称加密的密钥加密握手消息发给浏览器; 274 | 6. 浏览器解密并验证摘要,若一致,则握手结束。之后的数据传送都使用对称加密的密钥进行加密 275 | 276 | 总结:非对称加密算法用于在握手过程中加密生成的密码;对称加密算法用于对真正传输的数据进行加密;HASH算法用于验证数据的完整性。 277 |
278 | 279 | ##### 输入 www.baidu.com,怎么变成 https://www.baidu.com 的,怎么确定用HTTP还是HTTPS? 280 | 281 |
282 | 展开 283 | 284 | [你访问的网站是如何自动切换到 HTTPS 的?](https://www.sohu.com/a/136637876_487516) 285 | 286 | 一种是原始的302跳转,服务器把所有的HTTp流量跳转到HTTPS。但这样有一个漏洞,就是中间人可能在第一次访问站点的时候就劫持。 287 | 解决方法是引入HSTS机制,用户浏览器在访问站点的时候强制使用HTTPS。 288 |
289 | 290 | ##### HTTPS连接的时候,怎么确定收到的包是服务器发来的(中间人攻击)? 291 | 292 |
293 | 展开 294 | 1.验证域名、有效期等信息是否正确。证书上都有包含这些信息,比较容易完成验证; 295 | 296 | 2.判断证书来源是否合法。每份签发证书都可以根据验证链查找到对应的根证书,操作系统、浏览器会在本地存储权威机构的根证书,利用本地根证书可以对对应机构签发证书完成来源验证; 297 | 298 | 3.判断证书是否被篡改。需要与 CA 服务器进行校验; 299 | 300 | 4.判断证书是否已吊销。通过CRL(Certificate Revocation List 证书注销列表)和 OCSP(Online Certificate Status Protocol 在线证书状态协议)实现,其中 OCSP 可用于第3步中以减少与 CA 服务器的交互,提高验证效率 301 | 302 |
303 | 304 | ##### 什么是对称加密、非对称加密?区别是什么? 305 |
306 | 展开 307 | 308 | - 对称加密:加密和解密采用相同的密钥。如:DES、RC2、RC4 309 | - 非对称加密:需要两个密钥:公钥和私钥。如果用公钥加密,需要用私钥才能解密。如:RSA 310 | - 区别:对称加密速度更快,通常用于大量数据的加密;非对称加密安全性更高(不需要传送私钥) 311 |
312 | 313 | ##### 数字签名、报文摘要的原理 314 |
315 | 展开 316 | 317 | - 发送者A用私钥进行签名,接收者B用公钥验证签名。因为除A外没有人有私钥,所以B相信签名是来自A。A不可抵赖,B也不能伪造报文。 318 | - 摘要算法:MD5、SHA 319 |
320 | 321 | ### GET与POST的区别? 322 | 323 | 1. GET是幂等的,即读取同一个资源,总是得到相同的数据,POST不是幂等的; 324 | 2. GET一般用于从服务器获取资源,而POST有可能改变服务器上的资源; 325 | 3. 请求形式上:GET请求的数据附在URL之后,在HTTP请求头中;POST请求的数据在请求体中; 326 | 4. 安全性:GET请求可被缓存、收藏、保留到历史记录,且其请求数据明文出现在URL中。POST的参数不会被保存,安全性相对较高; 327 | 5. GET只允许ASCII字符,POST对数据类型没有要求,也允许二进制数据; 328 | 6. GET的长度有限制(操作系统或者浏览器),而POST数据大小无限制 329 | 330 | ### Session与Cookie的区别? 331 | 332 | Session是服务器端保持状态的方案,Cookie是客户端保持状态的方案 333 | 334 | Cookie保存在客户端本地,客户端请求服务器时会将Cookie一起提交;Session保存在服务端,通过检索Sessionid查看状态。保存Sessionid的方式可以采用Cookie,如果禁用了Cookie,可以使用URL重写机制(把会话ID保存在URL中)。 335 | 336 | ### 从输入网址到获得页面的过程 (越详细越好)? 337 | 338 | 1. 浏览器查询 DNS,获取域名对应的IP地址:具体过程包括浏览器搜索自身的DNS缓存、搜索操作系统的DNS缓存、读取本地的Host文件和向本地DNS服务器进行查询等。对于向本地DNS服务器进行查询,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析(此解析具有权威性);如果要查询的域名不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析(此解析不具有权威性)。如果本地域名服务器并未缓存该网址映射关系,那么将根据其设置发起递归查询或者迭代查询; 339 | 2. 浏览器获得域名对应的IP地址以后,浏览器向服务器请求建立链接,发起三次握手; 340 | 3. TCP/IP链接建立起来后,浏览器向服务器发送HTTP请求; 341 | 4. 服务器接收到这个请求,并根据路径参数映射到特定的请求处理器进行处理,并将处理结果及相应的视图返回给浏览器; 342 | 5. 浏览器解析并渲染视图,若遇到对js文件、css文件及图片等静态资源的引用,则重复上述步骤并向服务器请求这些资源; 343 | 6. 浏览器根据其请求到的资源、数据渲染页面,最终向用户呈现一个完整的页面。 344 | 345 | ### HTTP请求有哪些常见状态码? 346 | 347 | 1. 2xx状态码:操作成功。200 OK 348 | 2. 3xx状态码:重定向。301 永久重定向;302暂时重定向 349 | 3. 4xx状态码:客户端错误。400 Bad Request;401 Unauthorized;403 Forbidden;404 Not Found; 350 | 4. 5xx状态码:服务端错误。500服务器内部错误;501服务不可用 351 | 352 | ### 什么是RIP (Routing Information Protocol, 距离矢量路由协议)? 算法是什么? 353 | 每个路由器维护一张表,记录该路由器到其它网络的”跳数“,路由器到与其直接连接的网络的跳数是1,每多经过一个路由器跳数就加1;更新该表时和相邻路由器交换路由信息;路由器允许一个路径最多包含15个路由器,如果跳数为16,则不可达。交付数据报时优先选取距离最短的路径。 354 | 355 | (PS:RIP是应用层协议:[https://www.zhihu.com/question/19645407](https://www.zhihu.com/question/19645407)) 356 | 357 |
358 | 优缺点 359 | 360 | - 实现简单,开销小 361 | - 随着网络规模扩大开销也会增大; 362 | - 最大距离为15,限制了网络的规模; 363 | - 当网络出现故障时,要经过较长的时间才能将此信息传递到所有路由器 364 |
365 | 366 | ### 计算机网络体系结构 367 | 368 | ![计算机网络体系结构](_v_images/20191129195451183_16713.png) 369 | 370 | - Physical, Data Link, Network, Transport, Application 371 | - 应用层:常见协议: 372 | - FTP(21端口):文件传输协议 373 | - SSH(22端口):远程登陆 374 | - TELNET(23端口):远程登录 375 | - SMTP(25端口):发送邮件 376 | - POP3(110端口):接收邮件 377 | - HTTP(80端口):超文本传输协议 378 | - DNS(53端口):运行在UDP上,域名解析服务 379 | - 传输层:TCP/UDP 380 | - 网络层:IP、ARP、NAT、RIP... 381 | 382 |
383 | 路由器、交换机位于哪一层? 384 | 385 | - 路由器网络层,根据IP地址进行寻址; 386 | - 交换机数据链路层,根据MAC地址进行寻址 387 |
388 | 389 | ### IP地址的分类? 390 | 391 | ![IP address](_v_images/20191201085151639_2895.png) 392 | 393 | 路由器仅根据网络号net-id来转发分组,当分组到达目的网络的路由器之后,再按照主机号host-id将分组交付给主机;同一网络上的所有主机的网络号相同。 394 | 395 | ### 什么叫划分子网? 396 | 397 | 从主机号host-id借用若干个比特作为子网号subnet-id;子网掩码:网络号和子网号都为1,主机号为0;数据报仍然先按照网络号找到目的网络,发送到路由器,路由器再按照网络号和子网号找到目的子网:将子网掩码与目标地址逐比特与操作,若结果为某个子网的网络地址,则送到该子网。 398 | 399 | ### 什么是ARP协议 (Address Resolution Protocol)? 400 | 401 | **ARP协议完成了IP地址与物理地址的映射**。每一个主机都设有一个 ARP 高速缓存,里面有**所在的局域网**上的各主机和路由器的 IP 地址到硬件地址的映射表。当源主机要发送数据包到目的主机时,会先检查自己的ARP高速缓存中有没有目的主机的MAC地址,如果有,就直接将数据包发到这个MAC地址,如果没有,就向**所在的局域网**发起一个ARP请求的广播包(在发送自己的 ARP 请求时,同时会带上自己的 IP 地址到硬件地址的映射),收到请求的主机检查自己的IP地址和目的主机的IP地址是否一致,如果一致,则先保存源主机的映射到自己的ARP缓存,然后给源主机发送一个ARP响应数据包。源主机收到响应数据包之后,先添加目的主机的IP地址与MAC地址的映射,再进行数据传送。如果源主机一直没有收到响应,表示ARP查询失败。 402 | 403 | 如果所要找的主机和源主机不在同一个局域网上,那么就要通过 ARP 找到一个位于本局域网上的某个路由器的硬件地址,然后把分组发送给这个路由器,让这个路由器把分组转发给下一个网络。剩下的工作就由下一个网络来做。 404 | 405 | ### 什么是NAT (Network Address Translation, 网络地址转换)? 406 | 407 | 用于解决内网中的主机要和因特网上的主机通信。由NAT路由器将主机的本地IP地址转换为全球IP地址,分为静态转换(转换得到的全球IP地址固定不变)和动态NAT转换。 408 | 409 | ## HTTP各版本 410 | 411 | ![image-20220528142308368](_v_images/202205281423439.png) 412 | 413 | - HTTP 0.9版本 414 | 415 | - HTTP协议的第一个版本,功能简单,**已弃用** 416 | - 仅支持纯文本数据的传输,虽然支持HTML,但是不支持图片插入 417 | - 仅支持GET请求方式,且不支持请求头 418 | - 无状态,短连接。没有对用户状态的管理;每次请求建立一个TCP连接,响应之后关闭TCP连接。 419 | 420 | - HTTP 1.0版本 421 | 422 | - 支持POST、GET、HEAD三种方法 423 | - **支持长连接keep-alive**(但**默认还是使用短连接**:浏览器每一次请求建立一次TCP连接,请求处理完毕之后断开)。 424 | - 服务器不跟踪用户的行为也不记录用户过往请求。 425 | 426 | - HTTP 1.1版本 427 | 428 | - 新增PUT、DELETE、CONNECT、TRACE、OPTIONS方法,是现今**使用最多**的版本。 429 | - 支持长连接,在一次TCP连接中可以发送多个请求或响应,且默认使用长连接。 430 | - 支持宽带优化、断点续传。请求的对象部分数据,可以不必发送整个对象;文件上传下载支持续传。 431 | - 因为长连接产生的问题:队头阻塞。长连接中,发送请求和响应都是串行化的,前面的消息会造成后面的消息也阻塞。解决方法是创建多个TCP连接,这样就可以基本保证了可用性,浏览器**默认的最大TCP连接数是6个**。 432 | 433 | - HTTP 2.0版本 434 | 435 | - 二进制分帧,所有帧都是用二进制编码,节省了空间 436 | - 多路复用:HTTP 2.0中所有的连接都是持久化的。相比1.1版本可以不用维护更多的TCP连接,在处理并发请求的时候,可以将多个数据流中**互不依赖的帧**可以**乱序发送**,同时还支持**优先级**。接收方接收之后可以根据帧头部信息将帧组合起来。(解决了1.1版本中的队头阻塞问题) 437 | - 头部压缩:1.1版本每次传输都需要传输一份首部,2.0让双方各自缓存一份首部字段表,达到更快传输的目标。 438 | 439 | - HTTP 3.0版本 440 | 441 | - 基于UDP的**QUIC多路复用**:在一个QUIC中可以并发发送多个HTTP请求Stream,且如果各个Stream互不依赖,那么就不会造成**使用TCP带来的队头阻塞问题**。这个问题源头上是因为TCP连接,TCP连接的性质决定了重传会影响队后的数据发送,所以干脆选用UDP来解决这个方案。 442 | - 0RTT建链:RTT表示Round-Trip Time,3.0可以实现0RTT建链。一般来说HTTPS协议要建立完整链接包括**TCP握手**和**TLS握手**,总计需要至少2-3个RTT,普通的HTTP协议也需要至少1个RTT才可以完成握手。基于UDP的QUIC协议可以在第一次发送包的时候直接发送业务数据。但是由于首次连接需要发送公钥数据,所以首次连接并不使用这一方法。 443 | 444 | ![image-202205281424550.gif](_v_images/202205281424550.gif) 445 | 446 | > 参考文档:[图解 | 为什么HTTP3.0要弃用TCP协议,而改用UDP协议?_涛哥聊Python-CSDN博客]( 447 | 448 | ### 参考 449 | - [面试/笔试第一弹 —— 计算机网络面试问题集锦](https://blog.csdn.net/justloveyou_/article/details/78303617) 450 | - [【面试】计算机网络_雨下一整晚real的博客-CSDN博客](https://blog.csdn.net/qq_43103529/article/details/120813469) 451 | - [什么时候选TCP、UDP?](https://blog.csdn.net/yjxsdzx/article/details/71937886) 452 | - [TCP速率与窗口,带宽,RTT之间的关系](https://blog.csdn.net/bad_sheep/article/details/6158676) 453 | -------------------------------------------------------------------------------- /Database.md: -------------------------------------------------------------------------------- 1 | # 数据库 2 | 3 | * 数据库基础 4 | * [事务的概念和特性?](#事务的概念和特性) 5 | * [会出现哪些并发一致性问题?](#会出现哪些并发一致性问题) 6 | * [数据库的四种隔离级别?](#数据库的四种隔离级别) 7 | * [什么是乐观锁和悲观锁?](#什么是乐观锁和悲观锁) 8 | * [常见的封锁类型?](#常见的封锁类型) 9 | * [什么是三级封锁协议?](#什么是三级封锁协议) 10 | * [四种隔离级别的实现原理?](#四种隔离级别的实现原理) 11 | * [什么是两段锁协议?](#什么是两段锁协议) 12 | * [什么是 MVCC?](#什么是-mvcc) 13 | * [数据库的范式?](#数据库的范式) 14 | * [列举几种表连接方式?](#列举几种表连接方式) 15 | * [什么是存储过程?有哪些优缺点?](#什么是存储过程有哪些优缺点) 16 | * [Drop/Delete/Truncate的区别?](#DropDeleteTruncate的区别) 17 | * [什么是视图?什么是游标?](#什么是视图什么是游标) 18 | * MySQL 19 | * [数据库索引的实现原理(B+树)](#数据库索引的实现原理b树) 20 | * [使用索引的优点](#使用索引的优点) 21 | * [哪些情况下索引会失效?](#哪些情况下索引会失效) 22 | * [在哪些地方适合创建索引?](#在哪些地方适合创建索引) 23 | * [索引的分类?](#索引的分类) 24 | * [MySQL的两种存储引擎 InnoDB 和 MyISAM 的区别?](#MySQL的两种存储引擎-InnoDB-和-MyISAM-的区别) 25 | * [如何优化数据库?](#如何优化数据库) 26 | * [什么是主从复制?实现原理是什么?](#什么是主从复制实现原理是什么) 27 | * NoSQL/Redis 28 | * [关系型数据库和非关系型数据库的区别?](关系型数据库和非关系型数据库的区别) 29 | * [参考](#参考) 30 | 31 | --- 32 | 33 | ### 事务的概念和特性? 34 | 35 | 概念:事务(Transaction)是一个操作序列,不可分割的工作单位,以BEGIN TRANSACTION开始,以ROLLBACK/COMMIT结束 36 | 37 | 特性(ACID): 38 | 39 | - **原子性**(Atomicity):逻辑上是不可分割的操作单元,事务的所有操作要么全部提交成功,要么全部失败回滚(用回滚日志实现,反向执行日志中的操作); 40 | - **一致性**(Consistency):事务的执行必须使数据库保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的; 41 | - **隔离性**(Isolation):一个事务所做的修改在最终提交以前,对其它事务是不可见的(并发执行的事务之间不能相互影响); 42 | - **持久性**(Durability):一旦事务提交成功,对数据的修改是永久性的 43 | 44 | ### 会出现哪些并发一致性问题? 45 | 46 | - **丢失修改**:一个事务对数据进行了修改,在事务提交之前,另一个事务对同一个数据进行了修改,覆盖了之前的修改; 47 | - **脏读**(Dirty Read):一个事务读取了被另一个事务修改、但未提交(进行了回滚)的数据,造成两个事务得到的数据不一致; 48 | - **不可重复读**(Nonrepeatable Read):在同一个事务中,某查询操作在一个时间读取某一行数据和之后一个时间读取该行数据,发现数据已经发生修改(针对**update**操作); 49 | - **幻读**(Phantom Read):当同一查询多次执行时,由于其它事务在这个数据范围内执行了插入操作,会导致每次返回不同的结果集(和不可重复读的区别:针对的是一个数据整体/范围;并且针对**insert**操作) 50 | 51 | ### 数据库的四种隔离级别? 52 | 53 | - **未提交读**(Read Uncommited):在一个事务提交之前,它的执行结果对其它事务也是可见的。会导致脏读、不可重复读、幻读; 54 | - **提交读**(Read Commited):一个事务只能看见已经提交的事务所作的改变。可避免脏读问题; 55 | - **可重复读**(Repeatable Read):可以确保同一个事务在多次读取同样的数据时得到相同的结果。(MySQL的默认隔离级别)。可避免不可重复读; 56 | - **可串行化**(Serializable):强制事务串行执行,使之不可能相互冲突,从而解决幻读问题。可能导致大量的超时现象和锁竞争,实际很少使用。 57 | 58 | ### 什么是乐观锁和悲观锁? 59 | 60 | - 悲观锁:认为数据随时会被修改,因此每次读取数据之前都会上锁,防止其它事务读取或修改数据;应用于**数据更新比较频繁**的场景; 61 | - 乐观锁:操作数据时不会上锁,但是更新时会判断在此期间有没有别的事务更新这个数据,若被更新过,则失败重试;适用于**读多写少**的场景。乐观锁的实现方式有: 62 | - 加一个版本号或者时间戳字段,每次数据更新时同时更新这个字段; 63 | - 先读取想要更新的字段或者所有字段,更新的时候比较一下,只有字段没有变化才进行更新 64 | 65 | ### 常见的封锁类型? 66 | 67 | 意向锁是 InnoDB 自动加的, 不需用户干预。 68 | 对于 UPDATE、 DELETE 和 INSERT 语句, InnoDB 69 | 会自动给涉及数据集加排他锁(X); 70 | 对于普通 SELECT 语句,InnoDB 不会加任何锁; 71 | 事务可以通过以下语句显式给记录集加共享锁或排他锁: 72 | 共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。 其他 session 仍然可以查询记录,并也可以对该记录加 share mode 的共享锁。但是如果当前事务需要对该记录进行更新操作,则很有可能造成死锁。 73 | 排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。其他 session 可以查询该记录,但是不能对该记录加共享锁或排他锁,而是等待获得锁 74 | 75 | - **排它锁**(Exclusive Lock)/ X锁:事务对数据加上X锁时,只允许此事务读取和修改此数据,并且其它事务不能对该数据加任何锁; 76 | - **共享锁**(Shared Lock)/ S锁:加了S锁后,该事务只能对数据进行读取而不能修改,并且其它事务只能加S锁,不能加X锁 77 | - **意向锁**(Intention Locks): 78 | - 一个事务在获得某个**数据行**对象的 S 锁之前,必须先获得**整个表**的 IS 锁或更强的锁; 79 | - 一个事务在获得某个数据行对象的 X 锁之前,必须先获得整个表的 IX 锁; 80 | - IS/IX 锁之间都是兼容的; 81 | - 好处:如果一个事务想要对整个表加X锁,就需要先检测是否有其它事务对该表或者该表中的某一行加了锁,这种检测非常耗时。有了意向锁之后,只需要检测整个表是否存在IX/IS/X/S锁就行了 82 | 83 | 锁的作用:用于管理对共享资源的并发访问,保证数据库的完整性和一致性 84 | 85 |
86 | 封锁粒度的概念 87 | 88 | MySQL 中提供了两种封锁粒度:**行级锁**以及**表级锁**。 89 | 90 | 封锁粒度小: 91 | 92 | - 好处:锁定的数据量越少,发生锁争用的可能就越小,系统的**并发程度**就越高; 93 | - 坏处:**系统开销**大(加锁、释放锁、检查锁的状态都需要消耗资源) 94 | 95 |
96 | 97 |
98 | MySQL加锁 99 | 100 | ``` 101 | SELECT ... LOCK In SHARE MODE; 102 | SELECT ... FOR UPDATE; 103 | ``` 104 | 105 |
106 | 107 | ### 什么是三级封锁协议? 108 | 109 | - 一级封锁协议:事务在修改数据之前必须先对其加X锁,直到事务结束才释放。可以解决丢失修改问题(两个事务不能同时对一个数据加X锁,避免了修改被覆盖); 110 | - 二级封锁协议:在一级的基础上,事务在读取数据之前必须先加S锁,读完后释放。可以解决脏读问题(如果已经有事务在修改数据,就意味着已经加了X锁,此时想要读取数据的事务并不能加S锁,也就无法进行读取,避免了读取脏数据); 111 | - 三级封锁协议:在二级的基础上,事务在读取数据之前必须先加S锁,直到事务结束才能释放。可以解决不可重复读问题(避免了在事务结束前其它事务对数据加X锁进行修改,保证了事务期间数据不会被其它事务更新) 112 | 113 | ### 四种隔离级别的实现原理? 114 | 115 | - 未提交读(Read Uncommited):啥都不做。; 116 | - (一级封锁协议 ----> 解决丢失修改); 117 | - 提交读(Read Commited):二级封锁协议 ----> 解决脏读。; 118 | - 可重复读(Repeatable Read): 三级封锁协议 ----> 解决不可重复读。; 119 | - 可串行化(Serializable):强制事务串行执行 ----> 解决幻读问题。; 120 | - (其中提交读和可重复读也可以由MVCC实现); 121 | 122 | ### 什么是两段锁协议? 123 | 124 | 事务必须严格分为两个阶段对数据进行**加锁和解锁**的操作,第一阶段加锁,第二阶段解锁。也就是说一个事务中一旦释放了锁,就不能再申请新锁了。 125 | 126 | **可串行化调度**是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。事务遵循两段锁协议是保证可串行化调度的充分条件。 127 | 128 | ### 什么是 MVCC? 129 | 130 | 多版本并发控制(Multi-Version Concurrency Control, MVCC),MVCC在每行记录后面都保存有两个隐藏的列,用来存储**创建版本号**和**删除版本号**。 131 | 132 | - 创建版本号:创建一个数据行时的事务版本号(**事务版本号**:事务开始时的系统版本号;系统版本号:每开始一个新的事务,系统版本号就会自动递增); 133 | - 删除版本号:删除操作时的事务版本号; 134 | - 各种操作: 135 | - 插入操作时,记录创建版本号; 136 | - 删除操作时,记录删除版本号; 137 | - 更新操作时,先记录删除版本号,再新增一行记录创建版本号; 138 | - 查询操作时,要符合以下条件才能被查询出来:删除版本号未定义或大于当前事务版本号(删除操作是在当前事务启动之后做的);创建版本号小于或等于当前事务版本号(创建操作是事务完成或者在事务启动之前完成) 139 | 140 | 通过版本号减少了锁的争用,**提高了系统性能**;可以实现**提交读**和**可重复读**两种隔离级别,未提交读无需使用MVCC 141 | 142 |
143 | 快照读与当前读 144 | 145 | 使用 MVCC 读取的是快照中的数据,这样可以减少加锁所带来的开销: 146 | 147 | ``` 148 | select * from table ...; 149 | ``` 150 | 151 | 当前读读取的是最新的数据,需要加锁。以下第一个语句需要加 S 锁,其它都需要加 X 锁: 152 | 153 | ``` 154 | select * from table where ? lock in share mode; 155 | select * from table where ? for update; 156 | insert; 157 | update; 158 | delete; 159 | ``` 160 | 161 |
162 | 163 | ### 数据库的范式? 164 | 165 | - **第一范式**(1NF,Normal Form):**属性不应该是可分的**。举例:如果将“电话”作为一个属性(一列),是不符合1NF的,因为电话这个属性可以分解为家庭电话和移动电话...如果将“移动电话”作为一个属性,就符合1NF; 166 | - **第二范式** 2NF:每个非主属性**完全依赖**于主属性集(候选键集); 167 | - B完全依赖于A,就是说A中的所有属性唯一决定B,属性少了就不能唯一决定,属性多了则有冗余(叫依赖不叫完全依赖)。举例:(学号,课程名)这个主属性集可以唯一决定成绩,但是对于学生姓名这个属性,(学号,课程名)这个属性集就是冗余的,所以学生姓名不完全依赖于(学号,课程名)这一属性集; 168 | - 主属性集/候选码集:某一组属性能够唯一确定其它的属性(主键就是从候选键集中选的一个键),而其子集不能,这样的属性组中的属性就是主属性;不在候选码集中的属性成为非主属性; 169 | - 可以通过分解来满足 2NF:将(学号,课程名,成绩)做成一张表;(学号,学生姓名)做成另一张表,避免大量的数据冗余; 170 | 满足1NF后,要求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述一件事情; 171 | - **第三范式** 3NF:在 2NF 的基础上,非主属性**不传递依赖**于主属性 172 | - 传递依赖:如果C依赖于B,B依赖于A,那么C传递依赖于A; 173 | - 3NF在2NF的基础上,消除了非主属性之间的依赖;比如一个表中,主属性有(学号),非主属性有(姓名,院系,院长名),可以看到院长名这个非主属性依赖于院系,传递依赖于学号。消除的办法是分解。 174 | 必须先满足第二范式(2NF),要求:表中的每一列只与主键直接相关而不是间接相关,(表中的每一列只能依赖于主键); 175 | 176 |
177 | 不符合范式会出现哪些异常? 178 | 179 | - 冗余数据:某些同样的数据多次出现(如学生姓名); 180 | - 修改异常:修改了一个记录中的信息,另一个记录中相同的信息却没有修改; 181 | - 删除异常:删除一个信息,那么也会丢失其它信息(删除一个课程,丢失了一个学生的信息); 182 | - 插入异常:无法插入(插入一个还没有课程信息的学生) 183 | 184 |
185 | 186 | ### 列举几种表连接方式? 187 | 188 | ![SQL连接](_v_images/20191207081711185_20242.png) 189 | 190 | - 内连接(Inner Join):仅将两个表中满足连接条件的行组合起来作为结果集 191 | - 自然连接:只考虑属性相同的元组对; 192 | - 等值连接:给定条件进行查询 193 | - 外连接(Outer Join) 194 | - 左连接:左边表的所有数据都有显示出来,右边的表数据只显示共同有的那部分,没有对应的部分补NULL; 195 | - 右连接:和左连接相反; 196 | - 全外连接(Full Outer Join):查询出左表和右表所有数据,但是去除两表的重复数据 197 | - 交叉连接(Cross Join):返回两表的笛卡尔积(对于所含数据分别为m、n的表,返回m*n的结果) 198 | 199 | ### 什么是存储过程?有哪些优缺点? 200 | 201 | 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合。想要实现相应的功能时,只需要调用这个存储过程就行了(类似于函数,输入具有输出参数)。 202 | 203 | 优点: 204 | 205 | - 预先编译,而不需要每次运行时编译,提高了数据库执行**效率**; 206 | - 封装了一系列操作,对于一些数据交互比较多的操作,相比于单独执行SQL语句,可以**减少网络通信量**; 207 | - 具有**可复用性**,减少了数据库开发的工作量; 208 | - **安全性高**,可以让没有权限的用户通过存储过程间接操作数据库; 209 | - 更**易于维护** 210 | 211 | 缺点: 212 | 213 | - **可移植性差**,存储过程将应用程序绑定到了数据库上; 214 | - **开发调试复杂**:没有好的IDE; 215 | - **修改复杂**,需要重新编译,有时还需要更新程序中的代码以更新调用 216 | 217 | ### Drop/Delete/Truncate的区别? 218 | 219 | - **Delete**用来删除表的全部或者**部分数据**,执行delete之后,用户**需要提交**之后才会执行,会触发表上的DELETE**触发器**(包含一个OLD的虚拟表,可以只读访问被删除的数据),DELETE之后表结构还在,删除很慢,一行一行地删,因为会记录日志,可以利用日志还原数据; 220 | - **Truncate**删除表中的所有数据,这个操作**不能回滚**,也不会触发这个表上的触发器。操作比DELETE快很多(直接把表drop掉,再创建一个新表,删除的数据不能找回)。如果表中有自增(AUTO_INCREMENT)列,则重置为1; 221 | - **Drop**命令从数据库中**删除表**,所有的数据行,索引和约束都会被删除;不能回滚,不会触发触发器; 222 | 223 |
224 | 什么是触发器? 225 | 226 | 触发器(TRIGGER)是由事件(比如INSERT/UPDATE/DELETE)来触发运行的操作(不能被直接调用,不能接收参数)。在数据库里以独立的对象存储,用于**保证数据完整性**(比如可以检验或转换数据)。 227 | 228 |
229 | 230 |
231 | 有哪些约束类型? 232 | 233 | 约束(Constraint)类型:主键(Primary Key)约束,唯一约束(Unique),检查约束,非空约束,外键(Foreign Key)约束。 234 | 235 |
236 | 237 | ### 什么是视图?什么是游标? 238 | 239 | - 视图:从数据库的基本表中通过查询选取出来的数据组成的**虚拟表**(数据库中存放视图的定义)。可以对其进行增/删/改/查等操作。视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);可以跟基本表一样,进行增删改查操作(ps:增删改操作有条件限制);如连表查询产生的视图无法进行,对视图的增删改会影响原表的数据。好处: 240 | - 通过只给用户访问视图的权限,保证数据的**安全性**; 241 | - **简化**复杂的SQL操作,隐藏数据的复杂性(比如复杂的连接); 242 | - 游标(Cursor):用于定位在查询返回的**结果集的特定行**,以对特定行进行操作。使用游标可以方便地对结果集进行移动遍历,根据需要滚动或对浏览/修改任意行中的数据。主要用于交互式应用。 243 | 244 | --- 245 | 246 | ### 数据库索引的实现原理(B+树) 247 | 248 | 见[数据结构部分:B树,B+树](https://github.com/wolverinn/Iridescent/blob/master/Data%20Structure.md#b%E6%A0%91) 249 | 250 | ##### 使用B树和B+树的比较 251 | 252 | InnoDB的索引使用的是B+树实现,B+树对比B树的好处: 253 | 254 | - IO次数少:B+树的中间结点只存放索引,数据都存在叶结点中,因此中间结点可以存更多的数据,让索引树更加矮胖; 255 | - 范围查询效率更高:B树需要中序遍历整个树,只B+树需要遍历叶结点中的链表; 256 | - 查询效率更加稳定:每次查询都需要从根结点到叶结点,路径长度相同,所以每次查询的效率都差不多 257 | 258 | ##### 使用B树索引和哈希索引的比较 259 | 260 | 哈希索引能以 O(1) 时间进行查找,但是只支持精确查找,无法用于部分查找和范围查找,无法用于排序与分组;B树索引支持大于小于等于查找,范围查找。哈希索引遇到大量哈希值相等的情况后查找效率会降低。哈希索引不支持数据的排序。 261 | 262 | ### 使用索引的优点 263 | 264 | - 大大加快了数据的**检索速度**; 265 | - 可以显著减少查询中**分组和排序**的时间; 266 | - 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性; 267 | - 将随机 I/O 变为**顺序 I/O**(B+Tree 索引是有序的,会将相邻的数据都存储在一起) 268 | 269 | 缺点:建立和维护索引耗费时间空间,更新索引很慢。 270 | 271 | ### 哪些情况下索引会失效? 272 | 273 | - 以“%(表示任意0个或多个字符)”开头的LIKE语句; 274 | - OR语句前后没有同时使用索引; 275 | - 数据类型出现隐式转化(如varchar不加单引号的话可能会自动转换为int型); 276 | - 对于多列索引,必须满足 **最左匹配原则**/最左前缀原则 (最左优先,eg:多列索引col1、col2和col3,则 索引生效的情形包括 col1或col1,col2或col1,col2,col3); 277 | - 如果MySQL估计全表扫描比索引快,则不使用索引(比如非常小的表) 278 | 279 | ### 在哪些地方适合创建索引? 280 | 281 | - 某列经常作为最大最小值; 282 | - 经常被查询的字段; 283 | - 经常用作表连接的字段; 284 | - 经常出现在ORDER BY/GROUP BY/DISDINCT后面的字段 285 | 286 | ##### 创建索引时需要注意什么? 287 | 288 |
289 | 展开 290 | 291 | - 只应建立在**小字段**上,而不要对大文本或图片建立索引(一页存储的数据越多一次IO操作获取的数据越大效率越高); 292 | - 建立索引的字段应该**非空**,在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。应该用0、一个特殊的值或者一个空串代替NULL; 293 | - 选择**数据密度大**(唯一值占总数的百分比很大)的字段作索引 294 | 295 |
296 | 297 | ### 索引的分类? 298 | 299 | - 普通索引 300 | - 唯一索引 UNIQUE:索引列的值必须唯一,但允许有空值; 301 | - 主键索引 PRIMARY KEY:必须唯一,不允许空值(是一种特殊的唯一索引;MySQL创建主键时默认为聚集索引,但主键也可以是非聚集索引); 302 | - 单列索引和多列索引/复合索引(Composite):索引的列数; 303 | - 覆盖(Covering)索引:索引包含了所有满足查询所需要的数据,查询的时候只需要读取索引而不需要回表读取数据; 304 | - 聚集(Clustered)索引/非聚集索引:对磁盘上存放数据的物理地址重新组织以使这些数据按照指定规则排序的一种索引(数据的物理排列顺序和索引排列顺序一致)。因此每张表只能创建一个聚集索引(因为要改变物理存储顺序)。优点是查询速度快,因为可以直接按照顺序得到需要数据的物理地址。缺点是进行修改的速度较慢。对于需要经常搜索范围的值很有效。非聚集索引只记录逻辑顺序,并不改变物理顺序; 305 | - 分区索引(?) 306 | - 虚拟索引(Virtual):模拟索引的存在而不用真正创建一个索引,用于快速测试创建索引对执行计划的影响。没有相关的索引段,不增加存储空间的使用 307 | 308 | ### MySQL的两种存储引擎 InnoDB 和 MyISAM 的区别? 309 | 310 | - InnoDB**支持事务**,可以进行Commit和Rollback; 311 | - MyISAM 只支持表级锁,而 InnoDB 还**支持行级锁**,提高了并发操作的性能; 312 | - InnoDB **支持外键**; 313 | - MyISAM **崩溃**后发生损坏的概率比 InnoDB 高很多,而且**恢复的速度**也更慢; 314 | - MyISAM 支持**压缩**表和空间数据索引,InnoDB需要更多的内存和存储; 315 | - InnoDB 支持在线**热备份** 316 | 317 |
318 | 应用场景 319 | 320 | - **MyISAM** 管理非事务表。它提供高速存储和检索(MyISAM强调的是性能,每次查询具有原子性,其执行速度比InnoDB更快),以及全文搜索能力。如果表比较小,或者是只读数据(有大量的SELECT),还是可以使用MyISAM; 321 | - **InnoDB** 支持事务,并发情况下有很好的性能,基本可以替代MyISAM 322 | 323 |
324 | 325 |
326 | 热备份和冷备份 327 | 328 | - 热备份:在数据库运行的情况下备份的方法。优点:可按表或用户备份,备份时数据库仍可使用,可恢复至任一时间点。但是不能出错 329 | - 冷备份:数据库正常关闭后,将关键性文件复制到另一位置的备份方式。优点:操作简单快速,恢复简单 330 | 331 |
332 | 333 | 更详细的可以参考:[MySQL 数据库的存储引擎与适用场景 - Images](https://imageslr.github.io/2020/db-engine.html) 334 | 335 | ### 如何优化数据库? 336 | 337 |
338 | SQL 语句的优化 339 | 340 | > 分析慢查询日志:记录了在MySQL中响应时间超过阀值long_query_time的SQL语句,通过日志去找出IO大的SQL以及发现未命中索引的SQL 341 | 342 | > 使用 Explain 进行分析:通过explain命令可以得到表的读取顺序、数据读取操作的操作类型、哪些索引可以使用、**哪些索引被实际使用**、表之间的引用以及**被扫描的行数**等问题; 343 | 344 | - 应尽量避免在 where 子句中使用```!=```、```<```、```>```操作符或对字段进行null值判断,否则将引擎放弃使用索引而进行全表扫描; 345 | - 只返回必要的列:最好不要使用 SELECT * 语句; 346 | - 只返回必要的行:使用 LIMIT 语句来限制返回的数据; 347 | - 将一个大连接查询分解成对每一个表进行一次单表查询,然后在应用程序中进行关联,这样做的好处有: 348 | - 让缓存更高效。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用; 349 | - 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余的查询; 350 | - 减少锁竞争 351 | 352 |
353 | 354 |
355 | 索引的优化 356 | 357 | 注意会引起索引失效的情况,以及在适合的地方建立索引 358 | 359 |
360 | 361 |
362 | 数据库表结构的优化 363 | 364 | - 设计表时遵循**三大范式**; 365 | - 选择合适的**数据类型**:尽可能不要存储NULL字段;使用简单的数据类型(int, varchar/ text); 366 | - 表的**水平切分**(Sharding):将同一个表中的记录拆分到多个结构相同的表中(策略:哈希取模;根据ID范围来分)。当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓解单个数据库的压力; 367 | - 表的**垂直切分**:将一张表按列切分成多个表。可以将不常用的字段单独放在同一个表中;把大字段独立放入一个表中;或者把经常使用的字段(关系密切的)放在一张表中。垂直切分之后业务更加清晰,系统之间整合或扩展容易,数据维护简单 368 | 369 |
370 | 371 |
372 | 系统配置的优化 373 | 374 | - 操作系统:增加TCP支持的队列数; 375 | - MySQL配置文件优化:缓存池大小和个数设置 376 | 377 |
378 | 379 |
380 | 硬件的优化 381 | 382 | - 磁盘性能:固态硬盘; 383 | - CPU:多核且高频; 384 | - 内存:增大内存 385 | 386 |
387 | 388 | ### 什么是主从复制?实现原理是什么? 389 | 390 | 主从复制(Replication)是指数据可以从一个MySQL数据库主服务器复制到一个或多个从服务器,从服务器可以复制主服务器中的所有数据库或者特定的数据库,或者特定的表。默认采用异步模式。 391 | 392 | 实现原理: 393 | 394 | - 主服务器 **binary log dump 线程**:将主服务器中的数据更改(增删改)日志写入 Binary log 中; 395 | - 从服务器 **I/O 线程**:负责从主服务器读取binary log,并写入本地的 Relay log; 396 | - 从服务器 **SQL 线程**:负责读取 Relay log,解析出主服务器已经执行的数据更改,并在从服务器中重新执行(Replay),保证主从数据的一致性 397 | 398 | ##### 为什么要主从复制? 399 | 400 |
401 | 展开 402 | 403 | - 读写分离:主服务器负责写,从服务器负责读 404 | - 缓解了锁的争用,即使主服务器中加了锁,依然可以进行读操作; 405 | - 从服务器可以使用 MyISAM,提升查询性能以及节约系统开销; 406 | - 增加冗余,提高可用性 407 | - 数据实时备份,当系统中某个节点发生故障时,可以方便的故障切换 408 | - 降低单个服务器磁盘I/O访问的频率,提高单个机器的I/O性能 409 | 410 |
411 | 412 | ### 关系型数据库和非关系型数据库的区别? 413 | - 前者高度组织化结构化数据;后者存储的数据结构不固定更加灵活,可以减少一些空间和时间的开销 414 | - 后者更加容易水平扩展 415 | - 前者支持结构化查询语言,支持复杂的查询功能和表关联。后者只能进行简单的查询 416 | - 前者支持事务,具有ACID特性。后者则是BASE,最终一致性 417 | 418 | ### 参考 419 | 420 | - [数据库六大范式详解 -- CSDN博客](https://blog.csdn.net/weixin_43433032/article/details/89293663) 421 | - [delete,truncate 和 delete之间的区别 -- 博客园](https://www.cnblogs.com/alice-cj/p/10354737.html) 422 | - [深度探索MySQL主从复制原理](https://baijiahao.baidu.com/s?id=1617888740370098866&wfr=spider&for=pc) 423 | - 数据库程序员面试笔试宝典-机械工业出版社 424 | - [CS-Notes/数据库系统原理 -- GitHub](https://github.com/CyC2018/CS-Notes/blob/master/notes/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86.md) 425 | - [面试/笔试第三弹 —— 数据库面试问题集锦 -- CSDN博客](https://blog.csdn.net/justloveyou_/article/details/78308460) 426 | - [史上最全的数据库面试题,不看绝对后悔 -- 博客园](https://www.cnblogs.com/wenxiaofei/p/9853682.html) 427 | 428 | ### 待完成 429 | 430 | - [ ] E-R 模型 431 | - [ ] 数据库的三级模式和二级映像 432 | - [ ] [数据类型](https://github.com/CyC2018/CS-Notes/blob/master/notes/MySQL.md#%E5%9B%9B%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B):VARCHAR和CHAR的区别,DATETIME和TIMESATMP的区别 433 | - [ ] Redis 面试 434 | - [CyC2018](https://github.com/CyC2018/CS-Notes/blob/master/notes/Redis.md) 435 | - [几率大的Redis面试题(含答案) - CSDN](https://blog.csdn.net/Butterfly_resting/article/details/89668661) 436 | - [Redis面试题总结 - 简书](https://www.jianshu.com/p/65765dd10671) 437 | - [Redis常见面试题 - 博客园](https://www.cnblogs.com/jasontec/p/9699242.html) 438 | - [0voice/interview_internal_reference](https://github.com/0voice/interview_internal_reference#10) 439 | - [ ] [史上最全的数据库面试题,不看绝对后悔 -- 博客园](https://www.cnblogs.com/wenxiaofei/p/9853682.html) 440 | -------------------------------------------------------------------------------- /Design Pattern.md: -------------------------------------------------------------------------------- 1 | # 设计模式 2 | 3 | ## 设计模式是什么 4 | 设计模式是一个通过定义、使用、测试去解决特定问题的方法,是针对软件设计中在给定条件下会重复性发生的问题而提出的一种通用性的可重用解决方案,设计模式不是可以直接转化为代码的完整设计,它是用于描述在不同情况下解决问题的通用方案。 5 | ## 设计模式的作用 6 | 设计模式通过提供经过验证的行之有效的开发范式加快开发过程,预防重大的隐患问题,提高代码可读性。 7 | 8 | 9 | ## 设计模式的分类 10 | **这里主要讨论GoF所提出的23种设计模式,可将其分为三种类型:** 11 | 12 | 1. 创造型设计模式 13 | 1. 结构型设计模式 14 | 1. 行为型设计模式 15 | ### 创造型设计模式 16 | 注重完成对象的实例化,相比于直接实例化对象,根据实际情况选择合适的设计模式完成对象的实例化,可以为复杂的业务场景带来更高的灵活性。 17 | 创造型设计模式主要包括以下几种: 18 | 19 | 1. 抽象工厂设计模式 20 | 1. 生成器设计模式 21 | 1. 工厂方法设计模式 22 | 1. 原型设计模式 23 | 1. 单例设计模式 24 | ### 结构型设计模式 25 | 结构型设计模式用于指导我们完成对代码的结构划分,如此,代码结构会更加清晰,更易理解,也提高了软件的可维护性。 26 | 结构型设计模式主要包括以下几种: 27 | 28 | 1. 适配器设计模式 29 | 1. 桥接设计模式 30 | 1. 组合设计模式 31 | 1. 装饰设计模式 32 | 1. 门面设计模式 33 | 1. 享元设计模式 34 | 1. 代理设计模式 35 | ### 行为型设计模式 36 | 行为型设计模式主要用于定义对象之间的通信与流程控制,主要的设计模式都非常注重优化对象之间的数据交互方式。 37 | 行为型设计模式主要包括以下几种: 38 | 39 | 1. 职责链设计模式 40 | 1. 命令设计模式 41 | 1. 解释器设计模式 42 | 1. 迭代器设计模式 43 | 1. 中介者设计模式 44 | 1. 备忘录设计模式 45 | 1. 观察者设计模式 46 | 1. 策略设计模式 47 | 1. 状态设计模式 48 | 1. 模板方法设计模式 49 | 1. 访问者设计模式 50 | ## 如何学习设计模式 51 | 52 | - 模式名称是什么? 53 | - 模式类型是什么?是创造型,结构型,还是行为型? 54 | - 模式的目的是什么?(作用是什么?解决了什么问题?) 55 | - 模式的别名是什么? 56 | - 什么情况下使用该模式? 57 | - 该模式的基本示例 58 | - 该模式的UML图是什么样的?是类图还是交互图? 59 | - 都有那些对象在模式中参与活动?列出设计模式中使用的类和对象,并说明他们各自的角色 60 | - 模式中的类和对象是怎么进行交互的? 61 | - 通过应用设计模式能获取什么好处,有哪些坏处?如何权衡? 62 | - 如何实现该模式 63 | - 与该模式相近的设计模式是什么?这几种相近的模式有哪些异同点? 64 | ## 正确看待设计模式 65 | 恰当使用设计模式能够提高代码的复用性,但是由于复用性往往会引入封装与间接调用,这些会降低系统性能,增加代码复杂程度。因此,除非设计模式能够帮助我们完成代码的实现或者后续的维护工作,否则没有必要去引入设计模式。 66 | 学习设计模式的关键并不在于学习设计模式本身,而是在于识别应用场景与潜在的风险,并将设计模式用之有道,这般,设计模式才能算作得心应手的工具。 67 | 在没有必要的情况大可不必去使用设计模式,因为设计模式有可能会牺牲代码的简洁性,而且滥用设计模式多会引入新的问题却没有解决原来的问题。 68 | **保持代码的整洁,模块化和可读性,同时不要让各类之间过度耦合。** 69 | 70 | ## 创造型设计模式 71 | 创造型设计模式主要关注的是类的实例化,也就是说体现的是对象的创建方法,利用这些模式,我们可以在适当的情况下以适当的形式创建对象,创造型设计模式通过控制对象的创建来解决设计中的问题。 72 | 创造型设计模式主要包含以下子类别: 73 | 74 | 1. 对象创造型设计模式: 75 | 76 | 主要完成对象创建,并将对象中部分内容放到其他对象中创建。 77 | 78 | 2. 类创造型设计模式: 79 | 80 | 主要完成类的实例化,并将类中的部分对象放到子类中创建,此类模式在实例化过程中高效地利用了继承机制 81 | 创造型设计模式主要包含以下5种具体的设计模式: 82 | 83 | 1. 抽象工厂设计模式 84 | 85 | 提供一个用于创建相关对象或相互依赖对象的接口,无需指定对象的具体类 86 | 87 | 2. 生成器设计模式 88 | 89 | 将复杂对象的构建与其表示相互分离,使得同样的构建过程可以创建不同的表示 90 | 91 | 3. 工厂方法设计模式 92 | 93 | 允许在子类中实现本类的实例化类 94 | 95 | 4. 原型设计模式 96 | 97 | 使用一个原型实例来指定创建对象的种类,然后通过拷贝这些原型实现新对象的创建 98 | 99 | 5. 单例模式 100 | 101 | 确保某个类在系统中仅有一个实例,并提供一个访问它的全局访问点 102 | 103 | 104 | 105 | | 对象创造型设计模式 | 类创造型设计模式 | 106 | | :---: | :---: | 107 | | 抽象工厂设计模式 | 工厂方法设计模式 | 108 | | 生成器设计模式 | | 109 | | 原型设计模式 | | 110 | | 单例设计模式 | | 111 | 112 | ### 工厂方法设计模式 113 | 工厂方法的作用是创建对象,用来从一组实现特定逻辑的类中实例化某个对象。 114 | #### 模式中包括的类 115 | 116 | - 产品类(Product)中定义了工厂方法创建的对象接口。 117 | - 具体产品类( Concrete Product)实现产品类接口。 118 | - 工厂类( Creator,因为由它来创建产品类,所以叫作工厂类)声明工厂方法,返回一个产品类对象。可用于调用创建产品类对象的生成方法。 119 | - 具体工厂类( Concrete Creator)重写用于创建具体产品类对象的方法。 120 | #### UML图 121 | ![image.png](_v_images/1588679646408-22276075-76c2-42b2-8b20-84e3401fdbf7.png#align=left&display=inline&height=231&margin=%5Bobject%20Object%5D&name=image.png&originHeight=381&originWidth=1228&size=220064&status=done&style=none&width=746) 122 | #### 功能及应用场景 123 | 124 | - 当需要创建一个类,而在编程时不能确定这个类的类型时(需要运行时确定)。 125 | - 当一个类希望由其子类来指定所创建对象的具体类型时。 126 | - 当我们想要定位被创建类,并获取相关信息时。 127 | 128 | 129 | 130 | ### 抽象工厂设计模式 131 | 抽象工厂模式相比于工厂方法模式的抽象层次更高。这意味着抽象工厂返回的是一组类的工厂。与工厂方法模式类似(返回多个子类中的一个),此方法会返回一个工厂,而这个工厂会返回多个子类中的一个。简单来说,抽象工厂是一个工厂对象,该对象又会返回若干工厂中的一个。 132 | 工厂模式是创造型模式的典型示例。抽象工厂设计模式是工厂方法模式的扩展,从而使我们无须担心所创建对象的实际类就能够创建对象。抽象工厂模式扩展了工厂方法模式,允许创建更多类型的对象。 133 | #### 模式中包括的类 134 | 135 | - 抽象工厂(AbstractFactory)声明一个用于完成抽象产品对象创建操作的接口。 136 | - 具体工厂(ConcreteFactory)实现创建具体产品对象的操作。 137 | - 抽象产品(AbstractProduct)声明一个用于一类产品对象的接口。 138 | - 具体产品(ConcreteProduct)定义由相应的具体工厂来创建的产品对象。 139 | - 客户端(Client)使用由抽象工厂和抽象产品类声明的唯一接口。 140 | 141 | 142 | 143 | #### UML图 144 | ![image.png](_v_images/1588681690229-615d93e2-9429-42cc-812e-fa8cb7eb49a4.png#align=left&display=inline&height=307&margin=%5Bobject%20Object%5D&name=image.png&originHeight=565&originWidth=1374&size=368470&status=done&style=none&width=746) 145 | #### 功能及应用场景 146 | 抽象工厂模式的主要优点之一是它屏蔽了这些具体类的创建方法。实际应用的类名称不需要再让客户端(将客户端与具体类解耦)知道。由于具体类是屏蔽的,因此我们可以在不同的工厂(实现方法)之间进行切换。 147 | 148 | 149 | ### 生成器设计模式 150 | 生成器模式,能够从简单的对象一步一步生成复杂的对象。生成器模式是一种用来逐步构建复杂对象并在最后一步返回对象的创造型模式。 151 | 构造一个对象的过程是通过泛型实现的,以便它能够用于对同一对象创建不同的表示形式。 152 | #### 模式中包括的类 153 | 154 | - 生成器类( Builder)提供一个接口用于创建产品的各个组成部件。具体生成器(Concrete Builder)提供此接的实现。 155 | - 具体生成器( ConcreteBuilder)会跟踪其所创建对象的表现形式,并在创建对象的同时提供一个接口获取产品(Product)。 156 | - 导演类( Director)通过生成器提供的接口构造对象。产品类用于表示被构造的复杂对象。这包括对我们构建的所有类进行定义。 157 | #### UML图 158 | ![image.png](_v_images/1588687137859-38493900-8c93-43ef-bbe7-c67c14e9ba75.png#align=left&display=inline&height=286&margin=%5Bobject%20Object%5D&name=image.png&originHeight=364&originWidth=951&size=131071&status=done&style=none&width=746) 159 | #### 功能及应用场景 160 | 生成器模式隐藏了产品构建过程中的内部细节。各个生成器之间都是相互独立的。这提高了代码的模块化,并使其他的生成器更方便地创建对象。因为每个生成器都能够逐步创建对象,这让我们能够很好地对最终产品进行掌控。 161 | ### 单例设计模式 162 | 在应用程序的整个生命周期中,对象只有一个实例的时候,就会使用单例设计模式。单例类总是在第一次被访问时完成实例化,直至应用程序退出之前,都只会使用同一个实例。单一实例创建策略:我们通过限制构造函数(通过设置其为私有)从而限制单例类的实例化。之后在定义类时包含一个该类的静态私有对象,以便创建单例类的实例。 163 | 在单例模式中,最棘手的部分是对单一实例的实现和管理。 164 | 在单例模式的定义过程中,有两点需要注意的地方: 165 | 166 | - 该类仅允许存在一个实例。 167 | - 需要为该单一实例提供一个全局访问点。 168 | 169 | 单例模式中的主动实例化和被动实例化(饿汉、懒汉) 170 | 线程安全的单例:双重同步锁、静态变量、枚举 171 | #### 模式中包括的类 172 | 173 | - 单例类 174 | #### UML图 175 | ![image.png](_v_images/1588689300339-c33a3d0d-7544-4754-8695-b08fc843183d.png#align=left&display=inline&height=208&margin=%5Bobject%20Object%5D&name=image.png&originHeight=208&originWidth=334&size=51899&status=done&style=none&width=334) 176 | #### 功能及应用场景 177 | 在应用程序的整个生命周期中,对象只有一个实例的时候,就会使用单例设计模式。 178 | 179 | ### 原型设计模式 180 | 相比于以往创建一个复杂对象总是费时费力,原型模式只需要复制现有的相似对象,并根据需要做适当修改。原型意味着使用克隆方法。克隆方法是一种复制对象的操作。克隆出的对象副本被初始化为调用克隆方法时原始对象的当前状态。这意味着对象的克隆避免了创建新对象。如果创建一个新对象的开销很大,而且有可能引起资源紧张时,我们就克隆对象。 181 | 182 | - 浅层复制:当原始对象变化时,新对象也跟着改变。这主要是因为浅层复制并没有实际复制新的对象,而只是对原有对象的一个引用。 183 | - 深层复制:当原始对象变化时,新对象不受影响,因为原始对象所包含的所有参数、对象和引用在复制新对象的过程中都建立了新的拷贝。 184 | 185 | 使用克隆方法来复制对象时,具体是使用浅层复制还是深层复制是由业务需求来决定的。在使用原型模式时,使用克隆方法来复制对象仅仅是一个设计上的决策。克隆方法对于原型模式来说并不是强制性的最佳选择。 186 | #### 模式中包括的类 187 | 188 | - 客户端(Client):通过调用原型类的克隆操作创建一个新对象。 189 | - 原型类( Prototype):声明一个接口用于克隆自己。 190 | - 具体原型类( Concrete Prototype):实现克隆自己的操作。 191 | 192 | 193 | 194 | #### UML图 195 | ![image.png](_v_images/1588746617916-a21ed08c-42df-40c0-bc79-6701209c2f55.png#align=left&display=inline&height=564&margin=%5Bobject%20Object%5D&name=image.png&originHeight=564&originWidth=951&size=191697&status=done&style=none&width=951) 196 | #### 功能及应用场景 197 | 198 | 1. 当一个系统应该独立于其产品的创建、组合和表示。 199 | 1. 当需要实例化的类是在运行时定义的,例如动态加载,或避免建立一个平行于产品类继承层次的工厂类继承层次时。 200 | 1. 当一个类的实例仅可以拥有若干不同的状态组合中的一个时。使用原型模式建立相应数量的原型和克隆方法,会比每次都手动实例化类并配置相应状态更加方便。 201 | 202 | **主要难点:** 203 | 204 | - 每个原型类的子类都必须实现克隆操作。这实现起来可能有难度。例如,当类已经存在的时候添加克隆方法可能比较困难。 205 | - 对象内部包含其他不支持克隆的对象或具有循环引用的对象时,实现克隆方法会比较困难。 206 | 207 | **优点:** 208 | 209 | - 原型模式意味着使用克隆方法。克隆方法是一种复制对象的操作。相比于耗时的复制对象创建过程,原型模式仅复制类似的现有对象,再根据需要对复制出的副本进行修改。 210 | - 客户端可以在运行时添加或移除原型对象。 211 | - 通过各种参数来定义新对象:高度动态的系统允许我们通过使用对象组合来定义新的特征,例如为对象变量指定相应的参数值,而不是重新定义一个类。我们通过实例化现有类可以有效地定义新类型的对象,并为客户端对象注册原型实例。客户端可以通过向原型类委派某个责任而使其具有新的特征。这种设计允许用户无须大量编程就能轻松定义新的类。事实上,克隆一个原型本质上是类似于类的实例化的。但原型模式能够大大降低系统所需的类的数量。 212 | 213 | **副作用:** 214 | 215 | - 使用原型模式,我们可以根据需要通过对象克隆来实现运行时对象的添加和删除。我们可以根据程序运行情况在运行时修改类的内部数据表示形式。 216 | - 在Java中实现原型模式的一大困难是如果这些类已经存在,我们未必能够通过添加所需要的克隆方法或深层克隆方法对类进行修改。此外,那些与其他类具有循环引用关系的类并不能真正实现克隆。 217 | - 需要在这些类中具有足够的数据访问权限或方法,以便在克隆完成后对相应的数据进行修改。这可能需要在这些原型类中添加相应的数据访问方法,以便我们对类完成克隆之后可以修改数据。 218 | 219 | 220 | 221 | ## 结构型设计模式 222 | 结构型模式主要描述如何将对象和类组合在一起以组成更复杂的结构。在软件工程中结构型模式是用于帮助设计人员通过简单的方式来识别和实现对象之间关系的设计模式。结构型模式会以组的形式组织程序。这种划分形式使代码更加清晰,维护更加简便。结构型模式用于代码和对象的结构组织。 223 | 结构型模式会以组的形式组织程序。这种划分形式使代码更加清晰,维护更加简便。 224 | **结构型模式又分为以下子类别:** 225 | 226 | 1. 对象结构型模式:用于对象之间相互关联与组织,以便形成更大、更复杂的结构。 227 | 1. 类结构型模式:用于实现基于继承的代码抽象,并且会介绍如何通过该模式提供更有用的程序接口。 228 | 229 | **具体包括:** 230 | 231 | | 对象结构型模式 | 类结构型模式 | 232 | | :---: | :---: | 233 | | 桥接模式 | 类适配器模式 | 234 | | 组合模式 | | 235 | | 装饰模式 | | 236 | | 门面模式 | | 237 | | 享元模式 | | 238 | | 对象适配器模式 | | 239 | | 代理模式 | | 240 | 241 | 242 | 243 | 1. 组合模式:它能够为客户端处理各种复杂和灵活的树状结构。这些树结构可以由各种不同类型的容器和叶节点组成,其深度或组合形式能够在运行时调整或确定。 244 | 1. 装饰模式:允许我们通过附加新的功能或修改现有功能,在运行时动态地修改对象。 245 | 1. 门面模式:允许我们为客户端创建一个统一的接口以访问不同子系统的不同接口,从而简化客户端。 246 | 1. 享元模式:客户端调用类时会在运行时创建大量对象,该模式会重新设计类以优化内存开销。 247 | 1. 代理模式:为其他对象提供一种代理以控制对这个对象的访问。这种模式的目的是一个对象不适合或者不能直接引用另一个对象,简化客户端并实现对象访问,同时避免任何副作用。 248 | 1. 适配器模式:允许我们为一个已有的类提供一个新的接口,并在客户端请求不同接口时实现类的重用。 249 | 1. 桥接模式:允许我们将类与其接口相互解耦。允许类及其接口随着时间相互独立变化,增加类重用的次数,提高后续可扩展性。它也允许运行时对接口的不同实现方式动态切换,使代码更加灵活。 250 | ### 适配器设计模式 251 | 软件适配器的工作原理也和插座适配器完全一样。我们也经常需要在程序中使用到不同的类或模块。假设有一段代码写得很烂,如果我们直接将这些代码集成到程序中,会将现有的代码搞乱。但是我们又不得不调用这段代码,因为我们需要实现相关的功能,而从头写起会耽误很多宝贵的时间。这时的最佳实践就是编写适配器,并将所需要的代码包装进去。这样我们就能够使用自定义的接口,从而降低对外部代码的依赖。 252 | 适配器模式会将现有接口转换为新的接口,已实现对应用程序中不相关的类的兼容性和可重用性的目标。适配器模式也被称为包装模式。适配器模式能够帮助那些因为接口不兼容而无法一起工作的类,以便它们能够一同工作。 253 | 适配器模式也负责将数据转换成适当的形式。当客户端在接口中指定了其对数据格式的要求时,我们通常可以创建新的类以实现现有类的接口和子类。这种实现方式也会通过创建类适配器,实现对客户端调用命和现有类中被调用方法之间接口的转换。 254 | #### 模式中包括的类 255 | 256 | - 客户端(Client)调用目标类的类或程序。 257 | - 目标类(Target)客户端想要使用的接口。 258 | - 适配对象类(Adapetee)需要进行适配的类或对象。 259 | - 适配器类( Adapter)按照目标类接口的要求对适配对象接口实现接口形式的适配转换。 260 | - request方法:客户端想要执行的操作。 261 | - specificRequest方法:适配对象中能够完成 request方法功能的实现。 262 | #### UML图 263 | **![image.png](_v_images/1588761010089-ced9b3a9-3232-4729-943a-67c133909d7c.png#align=left&display=inline&height=395&margin=%5Bobject%20Object%5D&name=image.png&originHeight=395&originWidth=1149&size=182309&status=done&style=none&width=1149)** 264 | #### 功能及应用场景 265 | 在具体实践上,有两种实际应用适配器模式的方法: 266 | 267 | 1. 使用继承[类适配器] 268 | 1. 使用关联[对象适配器] 269 | 270 | **应用场景:** 271 | 272 | - 我们想要使用现有的类,但它的接口不符合我们的需要。 273 | - 我们想要创建一个可重用的类,能够与一些无关的类或不可预见的类进行协作,同时这个类无须具有兼容的接口。 274 | - (仅适用于对象适配器)我们需要使用多个已经存在的子类,而我们为每一个子类都做接口适配显然是不切实际的。使用对象适配器可以直接适配其父类的接口。 275 | 276 | 277 | 278 | ### 桥接设计模式 279 | 桥接模式是结构型模式中的另一个典型模式。桥接模式用于将类的接口与接口的实现相互解耦。这样做提高了系统的灵活性使得接口和实现两者均可独立变化。 280 | 举一个例子,让我们想一下家用电器及其开关。例如,风扇的开关。开关是电器的控制接口,而一旦闭合开关,实际让风扇运转的是风扇电机。 281 | 所以,在这个示例中,开关和风扇之间是彼此独立的。如果我们将开关接到电灯泡的供电线路上,那么我们还可以选用其他开关来控制风扇。 282 | #### 模式中包括的类 283 | 284 | - 抽象化对象(Abstraction)桥接设计模式的核心,并定义了关键症结所在。包含对实现化对象的引用。 285 | - 扩充抽象化对象(RefinedAbstraction)扩展抽象化对象,并将抽象化对象细化到新的层次。对实现化对象隐藏细节元素。 286 | - 实现化对象(Implementor)该接口比抽象化对象的层次更高。只对基本操作进行定义。 287 | - 具体实现化对象(Concretelmplementor)通过提供具体实现来执行实现化对象的具体功能。 288 | #### UML图 289 | ![image.png](_v_images/1588760917772-e4e10a15-0c43-456e-88f2-279fdd3e2d12.png#align=left&display=inline&height=411&margin=%5Bobject%20Object%5D&name=image.png&originHeight=411&originWidth=1027&size=184618&status=done&style=none&width=1027) 290 | #### 功能及应用场景 291 | 桥接模式主要适用于系统的多个维度上都经常发生变化的情况。桥接模式能够将不同的抽象维度进行衔接。通过桥接模式,抽象化对象和实现化对象不会在编译时进行绑定,而能够在各自的类被调用时独立扩展。 292 | 当你经常需要在运行时在多个实现之间进行切换时,桥接模式也非常有用。 293 | 294 | 295 | ### 组合设计模式 296 | 在大部分系统开发过程中,程序员都会遇到某个组件既可以是独立的个体对象,也能够作为对象集合的情况。组合模式就用于此类情况的设计。简单来说,组合模式是一组对象的集合,而这组对象中的每一个对象本身也是一个组合模式构成的对象,或者只是一个原始对象。 297 | 组合模式中存在着一个树形结构,并且在该结构中的分支节点和叶节点上都能够执行相同的操作。树形结构中每一个分支节点都包含子节点的类(能继承出叶节点和分支节点),这样的分支节点本身就是一个组合模式构成的节点。树形结构中的叶子节点仅是一个原始对象,其没有子节点(不能继承出叶节点和分支节点)。组合模式的子类(下一级节点)可以是叶子节点或其他组合模式。 298 | 299 | 300 | #### 模式中包括的类 301 | 302 | - 组件对象:(Component,结构) 303 | - 组件对象在整个继承结构的最顶端。它是对组合模式的抽象。 304 | - 它声明了组合模式中的对象接口。 305 | - 可以选择性地定义一个接口,以便对递归结构中组件的父类进行访问,并在需要的时候实现该接口。 306 | - 叶子节点:(Leaf,原始对象) 307 | - 树形结构的末端且不会再有子节点。 308 | - 定义了组合结构中单个对象的行为。 309 | - 分支节点类:(Composite,组) 310 | - 包含了子组件并为它们定义行为。 311 | - 实现子节点的相关操作。 312 | #### UML图 313 | ![image.png](_v_images/1588762859910-c08b6230-8358-42e8-aa48-5835af2d2940.png#align=left&display=inline&height=395&margin=%5Bobject%20Object%5D&name=image.png&originHeight=395&originWidth=1149&size=182309&status=done&style=none&width=1149) 314 | #### 功能及应用场景 315 | 316 | - 当对象的集合需要采用与单个对象相同的处理方式时。 317 | - 操纵单个对象的方式与操纵一组对象的方式类似时。 318 | - 注意存在能够组合的递归结构或树形结构。 319 | - 客户端能够通过组件对象访问整个继承结构,而它们却不会知道自己所处理的是叶子节点还是分支节点。 320 | 321 | 组合模式的目的是能够使独立对象(单个分支节点或叶子节点)和对象集合(子树)都能够以同样的方式组织起来。组合模式中所有的对象都来自于其本身(成为一种嵌套结构)。组合模式允许我们使用递归的方式将类似的对象组合成一种树形结构,来实现复杂结构对象的构建。 322 | ### 装饰者设计模式 323 | 装饰设计模式用来在运行时扩展或修改一个实例的功能。一般来说,继承可以扩展类的功能(用于类的所有实例)。但与继承不同的是,通过装饰模式,我们可以选择一个类的某个对象,并对其进行修改,而不会影响这个类中其他的实例。继承会直接为类增加功能,而装饰模式则会通过将对象与其他对象进行包装的方式将功能添加到类。 324 | #### 模式中包括的类 325 | 326 | - 抽象组件(Component)给出一个抽象接口,用于能够动态添加功能的对象。 327 | - 具体组件(Concrete Component)定义一个实现组件接口的对象。这是实际需要加以装饰的对象,但其对装饰的过程一无所知。 328 | #### UML图 329 | ![image.png](_v_images/1588776261625-d6b2f2b2-85c7-4752-ba71-ac38f9ca639c.png#align=left&display=inline&height=529&margin=%5Bobject%20Object%5D&name=image.png&originHeight=628&originWidth=886&size=170487&status=done&style=none&width=746) 330 | #### 功能及应用场景 331 | 装饰设计模式用来在运行时扩展或修改一个实例的功能。一般来说,继承可以扩展类的功能(用于类的所有实例)。但与继承不同的是,通过装饰模式,我们可以选择一个类的某个对象,并对其进行修改,而不会影响这个类中其他的实例。继承会直接为类增加功能,而装饰模式则会通过将对象与其他对象进行包装的方式将功能添加到类。 332 | ### 门面设计模式 333 | 许多业务流程都会涉及复杂的业务类操作。由于流程很复杂,所以其涉及了多个业务对象,这往往会导致各个类之间的紧密耦合,从而降低系统的灵活性和设计的清晰度。底层业务组件间的复杂关系会使客户端的代码编写变得很困难。 334 | 门面模式简化了到复杂系统的外部接口。为此它会对所有的类进行整合,并构建一个复杂系统的子系统。 335 | 门面模式能够将用户与系统内部复杂的细节相互屏蔽,并只为用户提供简化后的更容易使用的外部接口。同时它也将系统内部代码与接口子系统的代码相互解耦,以便修改和升级系统代码。 336 | 相比于其他设计模式,门面模式更注重实现代码的解耦。它所强调的是代码设计中很重要的一点,即代码抽象。通过提供一个简单的接口并隐藏其后的复杂性,从而实现抽象。 337 | 在这种方式下,代码的实现完全交由门面层处理。客户端只会与一个接口交互,同时也只有和这个接口交互的权限。这样就能隐藏全部系统的复杂性。总而言之,门面模式通过提供一个简单的接口为客户端简化了与复杂系统的交互。 338 | 从另一方面看,门面模式也保证了能够在不修改客户端代码的情况下对具体实现方法进行修改。 339 | 340 | 341 | #### 模式中包括的类 342 | 343 | - 门面层( Facade):它知道子系统内各个类的具体功能,并将客户端请求转换成对系统内部对象的调用。 344 | - 系统内部类( ComplicatedClass):这些类会实现系统功能,处理门面层对象分配的各项工作任务。它们本身并不知道门面层的存在,也没有对其进行任何的引用。 345 | 346 | 347 | 348 | 349 | 350 | #### UML图 351 | ![image.png](_v_images/1588776769193-d3a6ae4a-83d5-4fbf-b187-339039a22f25.png#align=left&display=inline&height=650&margin=%5Bobject%20Object%5D&name=image.png&originHeight=650&originWidth=996&size=196580&status=done&style=none&width=996) 352 | #### 功能及应用场景 353 | 354 | - 想要为一个复杂的子系统提供一个简单接口。子系统随着其自身的发展往往变得越来越复杂。它们应用的大多数的设计模式会导致类的数量更多、代码段更小。这使得该子系统可重用更好,也更容易进行自定义。而对于某些无法自定义的客户端来说,它也变得难以使用。门面层可以提供对大多数客户端来说足够好的简化的调用接口。只有极少数高度定制化的客户端需要直接调用门面层之后的底层代码。 355 | - 在客户端和抽象层的实现类之间存在大量的依赖关系。引入一个门面层能够将客户端的子系统与其他子系统进行解耦,从而促进子系统的独立性和可移植性。 356 | - 你想要为你的子系统增加层级。使用一个门面层对每个子系统级别分别定义一个入口点。如果子系统之间存在依赖关系,那么你可以通过令这些子系统之间的交互全部需要经由门面层来简化彼此的依赖关系。 357 | ### 代理设计模式 358 | 根据目的不同,有各种不同类型的代理。例如,有保护性代理,控制对某个对象的访问权限;有虚拟代理,处理开销过大而难以创建的对象,并通过远程访问控制来访问远程对象。 359 | #### 模式中包括的类 360 | 361 | 362 | 363 | 364 | #### UML图 365 | ![image.png](_v_images/1588778531181-f78a0447-263d-40cf-bbfd-dfc565997dcd.png#align=left&display=inline&height=624&margin=%5Bobject%20Object%5D&name=image.png&originHeight=624&originWidth=934&size=174488&status=done&style=none&width=934) 366 | #### 功能及应用场景 367 | 代理模式主要用于当我们需要用一个简单对象来表示一个复杂对象的情形。如果创建对象的开销很大,那么可以推迟其创建,并使用一个简单对象来代理其功能直到必须立即创建的时候。这个简单对象就可以称为复杂对象的代理。 368 | 369 | 370 | ### 享元设计模式 371 | 享元模式能够减少用于创建和操作大量相似的细碎对象所花费的成本。享元模式主要用在需要创建大量类似性质的对象时。大量的对象会消耗高内存,享元模式给出了一个解决方案,即通过共享对象来减少内存负载它的具体实现则是根据对象属性将对象分成两种类型:内蕴状态和外蕴状态。 372 | 共享是享元模式的关键。 373 | #### 模式中包括的类 374 | 375 | - 抽象享元角色( Flyweight)声明一个为具体享元角色规定了必须实现的接口,而外蕴状态就是以参数的形式通过此方法传入。 376 | - 具体享元角色( Concrete Flyweight)实现享元模式接口,并存储内蕴状态。具体享元角色必须是共享的。具体享元角色必须保持其内蕴状态不变,并且能够操纵外蕴状态。 377 | - 享元工厂角色(FlyweightFactory)负责创建和管理享元角色。此外,该工厂确保了享元角色的共享。工厂维护了不同的享元对象池,并负责在对象创建完成时从对象池返回对象,以及向对象池添加对象。 378 | - 客户端(Client)维护对所有享元对象的引用,而且需要存储和计算对应的外蕴状态。 379 | #### UML图 380 | ![image.png](_v_images/1588820461937-2a508c21-4203-4629-bcc1-ca0750f9fe84.png#align=left&display=inline&height=372&margin=%5Bobject%20Object%5D&name=image.png&originHeight=515&originWidth=1032&size=209323&status=done&style=none&width=746) 381 | #### 功能及应用场景 382 | 当我们选择享元模式的时候,需要考虑以下因素: 383 | 384 | - 需要创建大量的对象时。 385 | - 由于对象众多,内存的开销是一个制约因素。 386 | - 大多数对象属性可以分为内蕴状态和外蕴状态。 387 | - 应用程序需要使用多种对象,且创建对象后需要多次重复使用。 388 | - 外蕴状态最好是通过计算得到的,而不需要进行存储。 389 | ## 行为型模式 390 | 行为型模式是一类主要关注对象间相互通信(交互)的设计模式。这些对象之间的相互作用既能保证对象间能够交换数据,同时对象间仍然能够保持松耦合。 391 | 紧耦合一般会发生在一组紧密关联(相互依赖)的类之间。在面向对象的设计过程中,耦合引用的数量和设计过程中类与类之间的相互依赖是成正比的。用通俗的话讲,就是当一个类变化的时候,有多少可能需要同时修改其他类呢? 392 | 松耦合是软件架构设计的关键。在行为型模式中,功能实现与调用该实现的客户端之间应该是松耦合的,以避免硬编码和依赖性。 393 | 行为型模式处理不同的对象之间的通信关系,为其提供基本的通信方式,并提供实现这种通信方式的最常用、最灵活的解决方案。 394 | 行为型模式描述的不仅是类或对象的模式,同时也包括了它们之间的通信模式。行为型模式能够用来避免硬编码和依赖性。 395 | **行为型模式又分为以下子类别:** 396 | 397 | 1. 对象行为型模式:对象行为型模式使用对象组合而非继承。描述一组对象如何合作执行部分任务,而单个对象无法执行这些任务。 398 | 2. 类行为型模式:类行为型模式使用继承而不是对象组合来描述算法和流程控制。 399 | 400 | **具体包括:** 401 | 402 | - 职责链模式(COR):在一系列对象链之间传递请求的方法。 403 | - 命令模式:命令模式主要用于在需要向对象发出请求的情况,发出请求的对象无须了解请求的操作内容,也无须了解请求的实际接收对象。 404 | - 解释器模式:解释器提供了在代码中使用特定语言的一种方法。解释器模式就是一种用于在程序中解析特定语言的设计模式。 405 | - 迭代器模式:迭代器用于顺序访问集合(组合)对象中的元素,而无须了解其内部结构。 406 | - 中介者模式:定义简单的类间通信。 407 | - 备忘录模式:捕获和恢复对象的内部状态。 408 | - 观察者模式:一种通知多个类进行改变的方式。 409 | - 状态模式:当一个对象状态改变时改变其功能。 410 | - 策略模式:在类中进行算法封装。 411 | - 模板方法模式:将算法中的部分步骤延迟到子类中进行计算。 412 | - 访问者模式:在不改变类的条件下为该类定义一个新的操作。 413 | 414 | | **对象行为型模式** | **类行为型模式** | 415 | | :-------------: | :-----------: | 416 | | 职责链模式 | | 417 | | 解释器模式 | | 418 | | 命令模式 | 模板方法模式 | 419 | | 迭代器模式 | | 420 | | 中介者模式 | | 421 | | 备忘录模式 | | 422 | | 观察者模式 | | 423 | | 状态模式 | | 424 | | 策略模式 | | 425 | | 访问者模式 | | 426 | 427 | ### 职责链设计模式 428 | 在职责链模式中,由发送端发送一个请求到一个对象链中,链中的对象自行处理请求。如果链中的对象决定不响应请求,它会将请求转发给链中的下一个对象。 429 | 职责链的目的是通过特定设计对请求的发送者和接收者之间进行解耦。解耦是软件设计中很重要的一个方面。通过该设计模式能够使我们彻底地将发送者和接收者之间完全解耦。发送者是用于调用操作的对象,接收者是接收请求并执行相关操作的对象。通过解耦,发送者不需要关心接收者的接口。 430 | 在职责链模式中,职责是前后传递的。对于链中的对象,决定谁来响应请求的责任由整个链中左侧的对象来承担。这就像问答测验的时候传递问题一样。当提问者向一个人提问,如果他不知道答案,他就把问题传给下一个人,以此类推。当一个人回答了问题,问题就会停止向下传递。有时,也可能到达最后一个人时,还是没有人能回答问题。 431 | 我们能举出若干个职责链模式的例子:硬币分拣机、ATM取款机、Servlet过滤器和Java的异常处理机制。 432 | 在Java中,我们可以在catch语句中列出的异常序列时就抛出一个异常,catch列表从上到下逐条扫描。如果赶上第一个进行异常处理就可以立刻完成任务,否则责任转移到下一行,直到最后一行。 433 | #### 模式中包括的类 434 | 435 | - 抽象处理者(Handler):定义用于处理请求的接口。 436 | - 具体处理者( Concrete Handler):它负责处理请求。如果它能够处理这样的要求就会自行处理,否则会将请求发送到下一个处理者。 437 | - 客户端(Client):将命令发送到职责链中第一个能够处理该请求的对象。 438 | #### UML图 439 | ![image.png](_v_images/1588839044031-1dcdb9c4-a7c0-43b0-af86-4fb919336801.png#align=left&display=inline&height=483&margin=%5Bobject%20Object%5D&name=image.png&originHeight=483&originWidth=942&size=137762&status=done&style=none&width=942) 440 | #### 功能及应用场景 441 | 442 | - 发送者并不知道在链中的哪个对象会响应请求。 443 | - 职责链中的每一个对象都有责任决定是否对请求进行响应,如果这些对象有能力响应请求就会响应请求。 444 | - 如果对象(或节点)决定向后传递请求它需要具有选择下一个节点和继续传递的能力。 445 | - 也有可能没有任何一个节点能够响应请求(有些请求可能无法得到处理) 446 | - 会在运行时确定哪些对象能够响应请求。 447 | ### 命令设计模式 448 | 命令模式(也称为行动模式、业务模式)是一个对象行为型模式。 449 | 这使我们能够实现发送者和接收者之间完全解耦。发送者是调用操作的对象,接收者是接收请求并执行特定操作的对象。通过解耦,发送者无须了解接收者的接口。在这里,请求的含义是需要被执行的命令。 450 | #### 模式中包括的类 451 | 452 | - 抽象命令类(Command):在类中对需要执行的命令接口进行声明。 453 | - 具体命令类( ConcreteCommand):将接收者对象和行为之间进行绑定。它通过调用接收者中相应的操作实现 execute方法。 454 | - 客户端( Client):客户端完成对命令对象的实例化并提供随后需要调用的方法的信息。 455 | - 调用者(Invoker):调用者决定合适的调用方法。 456 | - 接收者(Receiver):接收者是包含方法代码的类的一个实例。这意味着它知道如何处理一个请求并执行相应的操作。任何一个类都可以作为接收者。 457 | #### UML图 458 | **![image.png](_v_images/1588841461626-35402966-4817-4f7c-bc64-7fa4dbfc6a84.png#align=left&display=inline&height=344&margin=%5Bobject%20Object%5D&name=image.png&originHeight=433&originWidth=938&size=126130&status=done&style=none&width=746)** 459 | 460 | 461 | #### 功能及应用场景 462 | 463 | - 通过参数化对象实现功能执行。命令是面向对象式的,而不是回调函数式的。 464 | - 指定消息队列并在不同的时间执行请求一个命令对象可以有独立于原始请求的生命周期。如果一个请求的接收者可以由一个独立地址空间的方式来表示,那么你可以将请求对应的命令对象转换到不同的进程并在其中完成请求。 465 | - 支持撤销。命令的执行操作可以作为状态进行存储,并在需要时实现命令撤销。命令接口必须增加一个unexecute操作,支持撤销之前命令调用的执行效果。执行的命令存储在命令的历史列表中。无限次数的撤销和重做是通过遍历这个列表并分别调用 unexecute和 execute来实现的。 466 | - 支持日志记录变化,在系统崩溃的情况下使命令可以重新应用。通过增加load和 store操作命令接口参数,你可以保存一个持续变化的日志。从系统崩溃中恢复需要从磁盘重新加载日志命令和使用 Execute作重新执行这些命令。 467 | - 通过在原生操作基础上的高层操作构建系统。这样的结构在支持交易操作的信息系统中很常见。一个交易事务封装一组变化的数据。命令模式提供了一种交易模型。命令都有一个共同的接口,允许你使用相同的方式调用所有的交易。这种模式也使得它很容易与新的交易系统进行交互扩展。 468 | 469 | **注意事项:** 470 | 471 | - 目的:将请求封装为一个对象,从而使客户端可以将不同的请求、队列、日志请求及其他支持撤销的操作进行参数化。 472 | 473 | - 发出请求的对象无须知道请求对应的操作或请求接收者的任何信息。 474 | - 后果: 475 | - 将调用操作的对象和执行操作的对象之间对命令进行解耦。即调用者和接收者之间解耦。 476 | - 命令转换为一类对象。使其可以像其他对象那样进行操作和扩展。 477 | - 我们可以将命令组合成一个组合命令。一般来说,组合命令是一个组合模式的实例。 478 | - 很容易添加新的命令,因为我们无须改变现有的类。 479 | ### 解释器设计模式 480 | 解释器模式是一种用于在程序中解析特定语法的设计模式。解释器模式是组合模式的一种应用。 481 | 对于特定的某种语言,解释器模式能够定义针对其语法表示形式的解释器,并实现对该语言语句的翻译和解释。 482 | #### 模式中包括的类 483 | 484 | - 内容类(Context):包含解释器的全局信息 485 | - 表达式(AbstractExpression):带有名叫 interpret抽象方法的抽象类。它会声明执行操作的接口。 486 | - 终结符表达式(TerminalExpression):就是带有终结符的表达式。 487 | - 非终结符表达式( NonterminalExpression):在两个终结符表达式或非终结符表达式之间实现逻辑运算(与或运算)的表达式。 488 | - 客户端(Client):建立抽象树,并调用抽象树中的 interpret方法。 489 | #### UML图 490 | ![image.png](_v_images/1588846767979-ce72003e-375a-4eea-8d13-eed6b726aa3b.png#align=left&display=inline&height=649&margin=%5Bobject%20Object%5D&name=image.png&originHeight=649&originWidth=992&size=178099&status=done&style=none&width=992) 491 | #### 功能及应用场景 492 | 解释器模式的适用范围非常有限。我们可以说解释器模式仅仅用于需要进行正式语法解释的地方,但这些领域往往已经有了更好的标准的解决方法,因此,在实际使用中,并不会经常使用该模式。该模式可以用于解释使用了特定语法的表达式或者建立某个简单的规则引擎的时候。 493 | ### 迭代器设计模式 494 | 迭代器模式也是一种行为型模式。迭代器模式允许对一组对象元素的遍历(也叫收集)以完成功能实现。 495 | #### 模式中包括的类 496 | 497 | - 迭代器(Iterator):它会实现一个用于定义迭代器的抽象迭代器接口。 498 | - 具体迭代器(Concretel):这是迭代器的实现(实现迭代器接口)。 499 | - 抽象容器(Container):这是用于定义聚合关系的接口。 500 | - 具体容器(ConcreteContainer):一个聚合关系的实现。 501 | #### UML图 502 | ![image.png](_v_images/1588848682603-c5da8658-bbda-4c63-9c3f-f9bc80a93299.png#align=left&display=inline&height=462&margin=%5Bobject%20Object%5D&name=image.png&originHeight=462&originWidth=816&size=135540&status=done&style=none&width=816) 503 | #### 功能及应用场景 504 | 505 | - 需要访问一个聚合(也称为容器)对象的内容,而无须了解其内部表示。- 506 | - 支持对聚合对象的多种遍历方式。 507 | - 为遍历不同的聚合结构提供统一的接口(即支持多态迭代)。 508 | - 迭代器模式允许我们访问集合对象中的内容,而无须暴露其内部数据结构。 509 | - 支持多个迭代器同时遍历集合对象。这意味着我们可以对相同的集合创建多个独立的迭代器。 510 | - 为遍历不同的集合提供统一的接口。 511 | ### 中介者设计模式 512 | 中介者模式主要是关于数据交互的设计模式。中介者设计模式很容易理解,却难以实现。该模式的核心是一个中介者对象,负责协调一系列对象之间一系列不同的数据请求。这一系列对象称为同事类。 513 | 同事类会让中介者知道它们会发生变化这样中介者负责处理变化对不同对象之间交互的影响。 514 | #### 模式中包括的类 515 | 516 | - 中介者接口(Mediator):它定义了一个接口来实现同事类对象之间的沟通。 517 | - 具体中介者( ConcreteMediator):它知道各个同事类,并和这些同事类保持相互引用。它实现了与同事类之间的通信和消息传递。 518 | - 同事类( Colleague):这些类保存了对中介者的引用。无论它们想和任何其他同事类进行交互,都必须通过与中介类通信来实现。 519 | #### UML图 520 | ![image.png](_v_images/1588850989407-80696883-cc5d-472b-a4de-0d5f5edd4cc4.png#align=left&display=inline&height=437&margin=%5Bobject%20Object%5D&name=image.png&originHeight=437&originWidth=979&size=149617&status=done&style=none&width=979) 521 | #### 功能及应用场景 522 | 523 | - 一组对象使用了标准的通信方式,但整体通信的连接都非常复杂。由此产生的相互依赖的结果导致系统难以结构化,也很难理解。 524 | - 由于对象之间的通信和相互引用,导致对象难以重用。 525 | - 分布在多个类中的行为能够被统一定制化,而无须创建过多的子类。 526 | 527 | **需要注意的问题:** 528 | 实际使用中介者模式的时候,反而会让问题变得越来越复杂。所以最佳的实践是仅让中介者类负责对象之间的通信部分。 529 | 530 | - 定义一个对象来负责一系列对象之间的交互。 531 | - 同事类发送和接收请求都需要通过中介者。 532 | 533 | **功能:** 534 | 535 | - 它对同事类进行解耦。中介类实现了同事类之间的松耦合。你可以相互独立地对不同的同事类进行修改和重用。 536 | - 它简化了对象协议。中介者取代了许多交互作用,而实现了与多个同事类之间一对多的通信方式。一对多关系更容易理解、维护和扩展。 537 | - 它集中了控制。中介者模式在中介者中集成了系统交互的复杂性。因此通过中介封装协议之后,它会比任何单一的同事类都更为复杂。这会使中介者作为一个整体也很难维护。 538 | - 门面模式不同于中介者模式的是,它抽象了对象的子系统以提供一个更方便的接口。该种抽象是单向的。也就是说,门面对象会向子系统中的各个类发出请求,反之则不会。相比之下,中介者模式更像是同事类对象之间通过中介者的合作行为,系统的交互都是多向的。 539 | - 当各个同事类只和一个中介者对象交互时,没有必要再去定义一个抽象的中介者类。抽象中介者只用于多个同事类通过多个抽象中介者的子类进行交互的情况,反之则不同。 540 | ### 备忘录设计模式 541 | 我们每天至少会使用一次这种模式。备忘录模式提供了一种使对象恢复到其以前状态的能力(通过回滚撤销)。备忘录模式是通过两个对象实现的:发起者和管理者。发起者是具有内部状态的某个对象。管理者则会对发起者执行一些操作,并实现撤销更改。 542 | #### 模式中包括的类 543 | 544 | - 发起者(Originator):发起者知道如何保存自己。这是我们想要保存状态的类。 545 | - 管理者( Caretaker):管理者是用于管理发起者进行状态保存的对象,具体处理发起者何时、如何、为何对状态进行存储。管理员应能够对发起者进行修改,同时也能够撤销这些修改。 546 | - 备忘录(Memento):备忘录会保存发起人的状态信息,而这些状态不能由管理者修改。 547 | #### UML图 548 | ![image.png](_v_images/1588858153516-9c6b4ce0-aa41-42c4-b4c5-ae14e7faae51.png#align=left&display=inline&height=360&margin=%5Bobject%20Object%5D&name=image.png&originHeight=360&originWidth=994&size=145133&status=done&style=none&width=994) 549 | #### 功能及应用场景 550 | 当我们在实际应用中需要提供撤销机制,当一个对象有可能需要在后续操作中恢复其内部状态时,就需要使用备忘录模式。结合本设计模式实现对象状态序列化,能够使其易于保存对象的状态并进行状态回滚。 551 | 当一个对象状态的快照必须被存储,且在后续操作过程中需要被恢复时,就可以使用备忘录模式。 552 | ### 观察者设计模式 553 | 在观察者模式中,一种叫作被观察者的对象维护了观察者对象的集合。当被观察者对象变化时,它会通知观察者。 554 | 在被观察者对象所维护的观察者集合中能够添加或删除观察者。被观察者的状态变化能够传递给观察者。这样观察者能够根据被观察者的状态变化做出相应的改变。 555 | #### 模式中包括的类 556 | 557 | - 被观察者(Listener):定义了向客户端添加和移除观察者操作的接口或抽象类。 558 | - 具体被观察者( ConcreteListener):具体被观察者类。它维护了对象的状态,并在当其状态改变时通知各个观察者。 559 | - 观察者(Observer):定义了用于通知对象的接口或抽象类。 560 | - 具体观察者( ConcreteObserver):具体实现了观察者。 561 | #### UML图 562 | ![image.png](_v_images/1588859146567-662ae183-11ae-475d-8d8d-a8549f3d4026.png#align=left&display=inline&height=431&margin=%5Bobject%20Object%5D&name=image.png&originHeight=431&originWidth=978&size=180698&status=done&style=none&width=978) 563 | #### 功能及应用场景 564 | 565 | - 当一个对象的改变需要其他对象同时改变,而我们并不知道需要有多少个对象一起改变时。 566 | - 当一个对象必须通知其他对象,而无须了解这些对象是谁时。 567 | - 当一个抽象包含有两个方面,其中一个依赖于另一个。将这些方面封装成独立的对象,以便我们独立改变和重复使用它们时。 568 | ### 状态设计模式 569 | 状态模式是一种行为型模式。状态模式背后的理念是根据其状态变化来改变对象的行为。状态模式允许对象根据内部状态(内容类)实现不同的行为。内容类可以具有大量的内部状态,每当对内容类调用 request方法时,消息就被委托给状态类进行处理。 570 | 状态类接口定义了一个对所有具体状态类都有效的通用接口,并在其中封装了与特定状态相关的所有操作。具体状态类对请求提供各自具体的实现。当内容类的状态变化时,那么与之关联的具体状态类也会发生一定相应的改变。 571 | #### 模式中包括的类 572 | 573 | - 内容类( Context):内容类主要用于状态模式的客户端。客户端并不直接访问对象的状态。内容类拥有一个具体的状态对象并根据其当前状态提供所需实现的行为。 574 | - 抽象状态类( State):这个抽象类是所有具体状态类的基类。状态类定义了一个通用接口。内容类对象能够通过使用该接口实现对不同功能的改变。在状态类及其子类的各个条目或属性中,本身并没有任何的状态。 575 | - 具体状态类( ConcreteState):具体状态类根据内容类所提供的状态实现真正的功能改变。每个状态类所提供的行为都适用于内容类对象的某一个状态。它们也包含着由内容类状态变化所下发的指令。 576 | #### UML图 577 | ![image.png](_v_images/1588860191434-2b5ff1d1-06e8-4036-8f95-0adfe7e383c1.png#align=left&display=inline&height=397&margin=%5Bobject%20Object%5D&name=image.png&originHeight=397&originWidth=1013&size=178430&status=done&style=none&width=1013) 578 | #### 功能及应用场景 579 | 580 | - 状态模式为对象提供了一个清晰的状态表示。 581 | - 它允许一个对象在运行时部分清晰明了地改变其类型。 582 | ### 策略设计模式 583 | 策略模式主要用于需要使用不同的算法来处理不同的数据(对象)时。这意味着策略模式定义了一系列算法,并且使其可以替换使用。策略模式是一种可以在运行时选择算法的设计模式。 584 | 本模式可以使算法独立于调用算法的客户端。策略模式也称为政策模式。在使用多种不同的算法(每种算法都可以对应一个单独的类,而每个类的功能又各不相同)时可以运用策略模式。 585 | #### 模式中包括的类 586 | 587 | - 抽象策略类(Strategy):定义一个所有算法都支持的通用接口。内容类会使用这个接口来调用由具体策略类定义的各个算法。 588 | - 具体策略类( ContreteStrategy):每个具体策略类都会实现一个相应的算法。 589 | - 内容类( Context):包含一个对策略对象的引用。它可以定义一个用于策略类访问内容类数据的接口。内容类对象包含了对将要使用的具体策略对象的引用。当需要进行特定操作时,会从对应的策略类对象中运行相应的算法。内容类本身觉察不到策略类的执行。如果有必要的话,还可以定义专用的对象来传递从内容类对象到策略类的数据。内容类对象接收来自客户端的请求,并将其委托给策略类对象。通常具体策略类是由客户端创建,并传递给内容类。从这一点来讲,客户端仅与内容类进行交互。 590 | #### UML图 591 | ![image.png](_v_images/1588861529453-aa147daa-653f-4559-b2ee-fdb0a370bf11.png#align=left&display=inline&height=426&margin=%5Bobject%20Object%5D&name=image.png&originHeight=426&originWidth=1095&size=182081&status=done&style=none&width=1095) 592 | #### 功能及应用场景 593 | 当我们有多种不同的算法可供选择(每种算法都可以对应一个单独的类,而每个类的功能又各不相同)时,可以应用策略模式。策略模式会定义一组算法并能够使其相互替代使用。 594 | ### 模板方法设计模式 595 | 模板方法会定义算法的各个执行步骤。算法的一个或多个步骤可以由子类通过重写来实现,同时保证算法的完整性并能够实现多种不同的功能。 596 | 类行为型模式使用继承来实现模式的功能。在模板方法模式中,会有一个方法( Template method方法)来定义算法的各个步骤。这些步骤(即方法)的具体实现会放到子类中。也就是说,在模板方法中定义了特定算法,但该算法的具体步骤仍然需要通过子类来定义。模板方法会由一个抽象类来实现在这个抽象类中还会声明该算法的各个步骤(方法),最后将其具体实现的方法声明实现为抽象类的子类。 597 | #### 模式中包括的类 598 | 599 | - 抽象类( AbstractClass):定义了算法的抽象操作,并交由具体的子类完成这些操作的具体实现。它实现了一个模板方法,它该方法包含了算法的各个步骤。该模板方法还会在抽象类中定义各个相应步骤的基本操作。 600 | - 具体类( ConcreteClass):他们通过执行基本操作来实现算法类的具体步骤。当调用一个具体类时,模板方法代码会从基类执行,而模板方法所使用的各个方法由派生类实现和调用。 601 | #### UML图 602 | ![image.png](_v_images/1588862264475-f62b4542-a18a-410e-b841-96049a3f2b44.png#align=left&display=inline&height=427&margin=%5Bobject%20Object%5D&name=image.png&originHeight=561&originWidth=980&size=162268&status=done&style=none&width=746) 603 | #### 功能及应用场景 604 | **应用场景:** 605 | 606 | - 当一个算法的功能需要能够改变,并通过在子类中对功能重写来实现这种改变。 607 | - 当我们要避免代码重复时,能够在子类中实现算法不同的变化。 608 | - 在一开始,模板方法可能不是一个显而易见的选择。最明显的现象会是当我们发现几乎完全一样的类在执行某些类似的逻辑。这时,我们就应该考虑使用模板方法模式来清理现有代码。 609 | ### 访问者设计模式 610 | 访问者模式用来简化对象相关操作的分组。这些操作是由访问者来执行的,而不是把这些代码放在被访问的类中。由于访问的操作是由访问者执行的,而不是由被访问的类,这样执行操作的代码会集中在访问者中,而不是分散在对象分组中。这为代码提供了更好的可维护性。访问者模式也避免了使用 instanceof运算符对相似的类执行计算。 611 | #### 模式中包括的类 612 | 613 | - 访问者( Visitor):包括一个接口或抽象类,用于声明在所有类型的可访问对象中访问哪些操作。通常操作的名称是相同的,而是由该方法的参数来区分不同的操作。由输入对象类型来决定访问该方法中的哪一个。 614 | - 具体访问者( Concrete Visitor):用于实现各个类型的访问者和各个类型的访问方法。它在抽象访问者中进行声明,并各自独立实现。每一个具体访问者会负责实现不同的功能。当定义一个新的访问者时,只需要将其传递给对象结构即可。 615 | - 元素类(Element):一个抽象对象用于声明所接受的操作。它是一个入口点,能够允许哪一类访问者对象访问。在集合中的每个对象都需要实现该抽象对象,以便相应访问者能够实现对其进行访问。 616 | - 具体元素类( Concrete Element):这些类实现了抽象元素类的接口或类,并定义了所接受的操作。通过其可接受的操作,能够将访问者对象传递给该对象。 617 | - 结构对象( ObjectStruture):这是一个包含了所有可访问对象的类。它提供了一种机制来遍历所有元素。这种结构不一定是一个集合,也可以是一个极其复杂的结构,如组合对象。 618 | #### UML图 619 | ![image.png](_v_images/1588863690354-5649da92-3741-4812-9f63-b5b7d0960238.png#align=left&display=inline&height=835&margin=%5Bobject%20Object%5D&name=image.png&originHeight=835&originWidth=1141&size=373163&status=done&style=none&width=1141) 620 | #### 功能及应用场景 621 | 在 visitCollection()方法中,我们调用 Visitable.accept(this)来实现对正确的访问者方法进行调用。这叫作双重分派。访问者调用元素类中的方法,又会回到对访问者类中进行调用。 622 | **模式问题:** 623 | 在使用访问者模式的情况下,要想添加新的具体元素(数据结构)会更加困难。添加一个 ConcreteElement会涉及向访问者接口添加新的操作和在每一个具体访问者实现中添加对应的实现。**访问者模式更适用于对象结构非常稳定,而对象的操作却需要经常变化的情况下。** 624 | 访问者模式只提供处理每种数据类型的方法,并且让数据对象确定调用哪个方法。由于数据对象本质上都知道其自身的类型,所以在访问者模式中算法决定所调用的方法所起到的作用是微不足道的。 625 | 因此,数据的整体处理包括对数据对象的分发以及通过对适当的访问者处理方法的二次分发。这就叫作双重分派。 626 | 使用访问者模式的一个主要优点是,对于在我们的数据结构中添加需要执行的新的操作来说,是非常容易的。我们所要做的就是创建一个新的访问者,并定义相应的操作。 627 | 访问者模式的主要问题是,因为每个访问者需要有相应的方法来处理每一种可能的具体数据,那么一旦实现了访问者模式,其具体类的数量和类型就不能被轻易改变。 628 | -------------------------------------------------------------------------------- /Git-ComdLine-REST.md: -------------------------------------------------------------------------------- 1 | # Git/RESTful API/命令行 2 | 3 | * [Git](#git) 4 | * [Git 常用命令](#git-常用命令) 5 | * [Git 标签管理](#git-标签管理) 6 | * [Git 撤销与回滚](#git-撤销与回滚) 7 | * [Git 分支管理](#git-分支管理) 8 | * [RESTful API](#restful-api) 9 | * [Linux 常用命令](#linux-常用命令) 10 | * [参考](#参考) 11 | 12 | ------ 13 | 14 | ## Git 15 | 16 | #### Git 常用命令 17 | - ```git init``` 18 | - ```git clone``` 19 | - ```git remote add origin ***.git``` 20 | - ```git push -u origin master``` 21 | - 推送到远程仓库的dev分支:```git push origin dev``` 22 | - ```git log``` 23 | - ```git log --graph --pretty=oneline --abbrev-commit``` 24 | - ```git status``` 25 | - ```git diff``` 26 | - ```git add *``` 27 | - ```git commit -m "message"``` 28 | - commit之后又改了一个小bug,但是又不想增加一个commit,可以用:```git commit --amend --no-edit```,直接将改动添加到上一次的commit中 29 | - ```git push``` 30 | - ```git pull``` 31 | - ```touch .gitignore``` 32 | 33 | #### Git 标签管理 34 | - 首先切换到需要打标签的分支上,然后使用```git tag v1.0```就可以在当前commit打上v1.0的标签 35 | - ```git tag v1.0 commitID``` 对特定commit打标签 36 | - 打标签时加上message:```git tag -a -m "message"``` 37 | - ```git tag``` 查看所有标签 38 | - ```git show [tagname]``` 查看标签详细信息 39 | - ```git push origin ```可以推送一个本地标签到远程仓库 40 | - ```git push origin --tags```可以推送全部未推送过的本地标签 41 | - ```git tag -d ```可以删除一个本地标签 42 | - ```git push origin :refs/tags/```可以删除一个远程标签(先从本地删除) 43 | 44 | #### Git 撤销与回滚 45 | - **暂存区**:```git add```之后commit之前存在的区域;**工作区**:```git commit```之后存在的区域;**远程仓库**:```git push```之后; 46 | - 作了修改,但还没```git add```,撤销到上一次提交:```git checkout -f -- filename```;```git checkout -f -- .``` 47 | - 作了修改,并且已经```git add```,但还没```git commit```: 48 | - 先将暂存区的修改撤销:```git reset HEAD filename```/```git reset HEAD```;此时修改只存在于工作区,变为了 "unstaged changes"; 49 | - 再利用上面的checkout命令从工作区撤销修改 50 | - ```git add```之后,作了修改,想丢弃这次修改:```git checkout -f --filename```会回到最近一次```git add``` 51 | - 作了修改,并且已经```git commit```了,想撤销这次的修改: 52 | - ```git revert commitID```. 其实,```git revert```可以用来撤销任意一次的修改,不一定要是最近一次 53 | - ```git reset --hard commitID```/```git reset --hard HEAD^```(HEAD表示当前版本,几个^表示倒数第几个版本,倒数第100个版本可以用HEAD~100);参数```--hard```:强制将暂存区和工作区都同步到指定的版本 54 | - ```git reset```和```git revert```的区别是:reset是用来回滚的,将HEAD的指针指向了想要回滚的版本,作为最新的版本,而后面的版本也都没有了;而revert只是用来撤销某一次更改,对之后的更改并没有影响 55 | - 然后再用```git push -f```提交到远程仓库 56 | 57 | #### Git 分支管理 58 | - 创建分支: ```git branch test``` 59 | - 切换分支: ```git checkout test``` 60 | - 创建并切换分支:```git checkout -b test``` 61 | - 将test分支的更改合并到master分支:先在test分支上commit、push,再:```git checkout master```; ```git merge test``` 62 | - 如果合并时产生冲突:先手动解决冲突,再合并 63 | - 删除分支:```git branch -d test``` 64 | - ```git stash``` 65 | - 如果当前分支还有任务没有做完,也不想提交,但此时需要切换或者创建其它分支,就可以使用stash将当前分支的所有修改(包括暂存区)先储藏起来;然后就可以切换到其它分支 66 | - 在其它分支工作完成之后,首先切换回原来的分支,然后使用```git stash list```命令查看 67 | - 可以使用```git stash apply ```恢复之前储藏的工作现场,再使用```git stash drop ```删除掉储藏的内容 68 | - 也可以直接用```git stash pop```恢复并删除内容 69 | - 如果在其它分支上做了一个修改(比如修复了一个bug,这次修改有一个commitID),想要将这次修改应用到当前分支上,可以使用:```git cherry-pick commitID```,可以复制一个特定的提交到当前分支 70 | 71 | ## RESTful API 72 | REST指Representational State Transfer,可以翻译为“表现层状态转化” 73 | 74 | #### 主要思想 75 | - 对网络上的所有资源,都有一个**统一资源标识符** URI(Uniform Resource Identifier); 76 | - 这些资源可以有多种表现形式,即REST中的“表现层”Representation,比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现。URI只代表资源的实体,不代表它的形式; 77 | - “无状态(Stateless)”思想:服务端不应该保存客户端状态,只需要处理当前的请求,不需了解请求的历史,客户端每一次请求中包含处理该请求所需的一切信息; 78 | - 客户端使用HTTP协议中的 GET/POST/PUT/DELETE 方法对服务器的资源进行操作,即REST中的”状态转化“ 79 | 80 | #### 设计原则 81 | - URL设计 82 | - 最好只使用名词,而使用 GET/POST/PUT/DELETE 方法的不同表示不同的操作;比如使用```POST /user```代替```/user/create``` 83 | - GET:获取资源;POST:新建/更新资源;PUT:更新资源;DELETE:删除资源; 84 | - 对于只支持GET/POST的客户端,使用```X-HTTP-Method-Override```属性,覆盖POST方法; 85 | - 避免多级URL,比如使用```GET /authors/12?categories=2```代替```GET /authors/12/categories/2```; 86 | - 避免在URI中带上版本号。不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI,版本号可以在HTTP请求头信息的Accept字段中进行区分 87 | - 状态码:服务器应该返回尽可能精确的状态码,客户端只需查看状态码,就可以判断出发生了什么情况。见计算机网络部分 -- [HTTP请求有哪些常见状态码?](Computer%20Network.md#HTTP请求有哪些常见状态码) 88 | - 服务器回应:在响应中放上其它API的链接,方便用户寻找 89 | 90 | ## Linux 常用命令 91 | 92 | ### 参考 93 | - [Learn Git Branching - 可视化的学习 Git 操作](https://learngitbranching.js.org/?demo=&locale=zh_CN) 94 | - [Git教程 - 廖雪峰的官方网站](https://www.liaoxuefeng.com/wiki/896043488029600) 95 | - [RESTful API 最佳实践 - 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html) 96 | - [GitHub - jlevy/the-art-of-command-line: Master the command line, in one page](https://github.com/jlevy/the-art-of-command-line/blob/master/README-zh.md) 97 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Operating Systems.md: -------------------------------------------------------------------------------- 1 | # 操作系统 2 | 3 | * 进程和线程 4 | * [进程和线程有什么区别?](#进程和线程有什么区别) 5 | * [进程间通信有哪些方式?](#进程间通信有哪些方式) 6 | * [进程同步问题](#进程同步问题) 7 | * [进程有哪几种状态?](#进程有哪几种状态) 8 | * [进程调度策略有哪些?](#进程调度策略有哪些) 9 | * [什么是僵尸进程?](#什么是僵尸进程) 10 | * [线程同步有哪些方式?](#线程同步有哪些方式) 11 | * [什么是协程?](#什么是协程) 12 | * [进程的异常控制流:陷阱、中断、异常和信号](#进程的异常控制流:陷阱、中断、异常和信号) 13 | * [什么是IO多路复用?怎么实现?](#什么是IO多路复用怎么实现) 14 | * [什么是用户态和内核态?](#什么是用户态和内核态) 15 | * 死锁 16 | * [什么是死锁?](#什么是死锁) 17 | * [死锁产生的必要条件?](#死锁产生的必要条件) 18 | * [死锁有哪些处理方法?](#死锁有哪些处理方法) 19 | * 内存管理 20 | * [分页和分段有什么区别?](#分页和分段有什么区别) 21 | * [什么是虚拟内存?](#什么是虚拟内存) 22 | * [有哪些页面置换算法?](#有哪些页面置换算法) 23 | * [缓冲区溢出问题](#缓冲区溢出问题) 24 | * [磁盘调度](#磁盘调度) 25 | * [参考](#参考) 26 | 27 | ------ 28 | 29 | ### 进程和线程有什么区别? 30 | - 进程(Process)是系统进行资源分配和调度的基本单位,线程(Thread)是CPU调度和分派的基本单位; 31 | - 线程依赖于进程而存在,一个进程至少有一个线程; 32 | - 进程有自己的独立地址空间,线程共享所属进程的地址空间; 33 | - 进程是拥有系统资源的一个独立单位,而线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),和其他线程共享本进程的相关资源如内存、I/O、cpu等; 34 | - 在进程切换时,涉及到整个当前进程CPU环境的保存环境的设置以及新被调度运行的CPU环境的设置,而线程切换只需保存和设置少量的寄存器的内容,并不涉及存储器管理方面的操作,可见,进程切换的开销远大于线程切换的开销; 35 | - 线程之间的通信更方便,同一进程下的线程共享全局变量等数据,而进程之间的通信需要以进程间通信(IPC)的方式进行; 36 | - 多线程程序只要有一个线程崩溃,整个程序就崩溃了,但多进程程序中一个进程崩溃并不会对其它进程造成影响,因为进程有自己的独立地址空间,因此多进程更加健壮 37 | 38 | 进程操作代码实现,可以参考:[多进程 - 廖雪峰的官方网站](https://www.liaoxuefeng.com/wiki/1016959663602400/1017628290184064) 39 | 40 | ##### 同一进程中的线程可以共享哪些数据? 41 |
42 | 展开 43 | 44 | - 进程代码段 45 | - 进程的公有数据(全局变量、静态变量...) 46 | - 进程打开的文件描述符 47 | - 进程的当前目录 48 | - 信号处理器/信号处理函数:对收到的信号的处理方式 49 | - 进程ID与进程组ID 50 |
51 | 52 | ##### 线程独占哪些资源? 53 |
54 | 展开 55 | 56 | - 线程ID 57 | - 一组寄存器的值 58 | - 线程自身的栈(堆是共享的) 59 | - 错误返回码:线程可能会产生不同的错误返回码,一个线程的错误返回码不应该被其它线程修改; 60 | - 信号掩码/信号屏蔽字(Signal mask):表示是否屏蔽/阻塞相应的信号(SIGKILL,SIGSTOP除外) 61 |
62 | 63 | ### 进程间通信有哪些方式? 64 | 65 | 1. 管道(Pipe) 66 |
67 | 展开 68 | 69 | - 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 70 | - 一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据; 71 | - 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程) 72 |
73 | 74 | 2. 命名管道 75 | 3. 消息队列 76 | 4. 信号(Signal) 77 | 5. 共享内存 78 | 6. 信号量(Semaphore):初始化操作、P操作、V操作;P操作:信号量-1,检测是否小于0,小于则进程进入阻塞状态;V操作:信号量+1,若小于等于0,则从队列中唤醒一个等待的进程进入就绪态 79 | 7. 套接字(Socket) 80 | 81 | 更详细的可以参考(待整理): 82 | - https://imageslr.github.io/2020/02/26/ipc.html 83 | - https://www.jianshu.com/p/c1015f5ffa74 84 | 85 | ### 进程同步问题 86 | 87 | > 进程的同步是目的,而进程间通信是实现进程同步的手段 88 | 89 |
90 | 管程 Monitor 91 | 92 | 管程将共享变量以及对这些共享变量的操作封装起来,形成一个具有一定接口的功能模块,这样只能通过管程提供的某个过程才能访问管程中的资源。进程只能互斥地使用管程,使用完之后必须释放管程并唤醒入口等待队列中的进程。 93 | 94 | 当一个进程试图进入管程时,在**入口等待队列**等待。若P进程唤醒了Q进程,则Q进程先执行,P在**紧急等待队列**中等待。(**HOARE管程**) 95 | 96 | wait操作:执行wait操作的进程进入条件变量链末尾,唤醒紧急等待队列或者入口队列中的进程;signal操作:唤醒条件变量链中的进程,自己进入紧急等待队列,若条件变量链为空,则继续执行。(**HOARE管程**) 97 | 98 | **MESA管程**:将HOARE中的signal换成了notify(或者broadcast通知所有满足条件的),进行通知而不是立马交换管程的使用权,在合适的时候,条件队列首位的进程可以进入,进入之前必须用while检查条件是否合适。优点:没有额外的进程切换 99 |
100 | 101 |
102 | 生产者-消费者问题 103 | 104 | > 问题描述:使用一个缓冲区来存放数据,只有缓冲区没有满,生产者才可以写入数据;只有缓冲区不为空,消费者才可以读出数据 105 | 106 | 代码实现: 107 | ```c 108 | // 伪代码描述 109 | // 定义信号量 full记录缓冲区物品数量 empty代表缓冲区空位数量 mutex为互斥量 110 | semaphore full = 0, empty = n, mutex = 1; 111 | 112 | // 生产者进程 113 | void producer(){ 114 | do{ 115 | P(empty); 116 | P(mutex); 117 | 118 | // 生产者进行生产 119 | 120 | V(mutex); 121 | V(full); 122 | } while(1); 123 | } 124 | 125 | void consumer(){ 126 | do{ 127 | P(full); 128 | P(mutex); 129 | 130 | // 消费者进行消费 131 | 132 | V(mutex); 133 | V(empty); 134 | } while(1); 135 | } 136 | 137 | ``` 138 |
139 | 140 |
141 | 哲学家就餐问题 142 | 143 | > 问题描述:有五位哲学家围绕着餐桌坐,每一位哲学家要么思考,要么吃饭。为了吃饭,哲学家必须拿起两双筷子(分别放于左右两端)不幸的是,筷子的数量和哲学家相等,所以每只筷子必须由两位哲学家共享。 144 | 145 | 代码实现: 146 | ```c 147 | #define N 5 // number of philosopher 148 | #define LEFT (i + N - 1)%N // number of i's left neighbors 149 | #define RIGHT (i + 1)%N // number of i's right neighbors 150 | #define THINKING 0 151 | #define HUNGRY 1 152 | #define EATING 2 153 | typedef int semaphore; 154 | int state[N]; // array to keep track of everyone's state 155 | semaphore mutex = 1; // mutual exclusion of critical region 156 | semaphore s[N]; 157 | 158 | void philosopher(int i) { 159 | while (TRUE) { 160 | think(); 161 | take_forks(i); 162 | eat(); 163 | put_forks(i); 164 | } 165 | } 166 | 167 | void take_forks(int i) { 168 | down(&mutex); // enter critical region 169 | state[i] = HUNGRY; // record that i is hungry 170 | test_forks(i); // try to acquire two forks 171 | up(&mutex); // exit critical region 172 | down(&s[i]); // block if forks are not acquired 173 | } 174 | 175 | void put_forks(int i) { 176 | down(&mutex); // enter critical region 177 | state[i] = THINKING; // record that has finished eating 178 | test_forks(LEFT); // see if left neighbor can now eat 179 | test_forks(RIGHT); // see if right neighbor can now eat 180 | up(&mutex); // exit critical region 181 | } 182 | 183 | void test_forks(int i) { 184 | if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) { 185 | state[i] = EATING; 186 | up(&s[i]); 187 | } 188 | } 189 | ``` 190 |
191 | 192 |
193 | 读者-写者问题 194 | 195 | 196 |
197 | 198 | ##### 临界区的概念? 199 |
200 | 展开 201 | 202 | 各个进程中对临界资源(互斥资源/共享变量,一次只能给一个进程使用)进行操作的程序片段 203 |
204 | 205 | ##### 同步与互斥的概念? 206 |
207 | 展开 208 | 209 | - 同步:多个进程因为合作而使得进程的执行有一定的先后顺序。比如某个进程需要另一个进程提供的消息,获得消息之前进入阻塞态; 210 | - 互斥:多个进程在同一时刻只有一个进程能进入临界区 211 |
212 | 213 | ##### 并发、并行、异步的区别? 214 | 215 |
216 | 展开 217 | 218 | 并发:在一个时间段中同时有多个程序在运行,但其实任一时刻,只有一个程序在CPU上运行,宏观上的并发是通过不断的切换实现的; 219 | 220 | 多线程:并发运行的一段代码。是实现异步的手段 221 | 222 | 并行(和串行相比):在多CPU系统中,多个程序无论宏观还是微观上都是同时执行的 223 | 224 | 异步(和同步相比):同步是顺序执行,异步是在等待某个资源的时候继续做自己的事 225 |
226 | 227 | ### 进程有哪几种状态? 228 | 229 | ![Process State](_v_images/image-20221216125538480.png) 230 | 231 | - 就绪状态:进程已获得除处理机以外的所需资源,等待分配处理机资源 232 | - 运行状态:占用处理机资源运行,处于此状态的进程数小于等于CPU数 233 | - 阻塞状态: 进程等待某种条件,在条件满足之前无法执行 234 | 235 | ### 进程调度策略有哪些? 236 | 237 | 1. **批处理系统**: 238 | 239 |
240 | 先来先服务 first-come first-serverd(FCFS) 241 | 242 | 按照请求的顺序进行调度。非抢占式,开销小,无饥饿问题,响应时间不确定(可能很慢); 243 | 244 | 对短进程不利,对IO密集型进程不利。 245 |
246 | 247 |
248 | 最短作业优先 shortest job first(SJF) 249 | 250 | 按估计运行时间最短的顺序进行调度。非抢占式,吞吐量高,开销可能较大,可能导致饥饿问题; 251 | 252 | 对短进程提供好的响应时间,对长进程不利。 253 |
254 | 255 |
256 | 最短剩余时间优先 shortest remaining time next(SRTN) 257 | 258 | 按剩余运行时间的顺序进行调度。(最短作业优先的抢占式版本)。吞吐量高,开销可能较大,提供好的响应时间; 259 | 260 | 可能导致饥饿问题,对长进程不利。 261 |
262 | 263 |
264 | 最高响应比优先 Highest Response Ratio Next(HRRN) 265 | 266 | 响应比 = 1+ 等待时间/处理时间。同时考虑了等待时间的长短和估计需要的执行时间长短,很好的平衡了长短进程。非抢占,吞吐量高,开销可能较大,提供好的响应时间,无饥饿问题。 267 |
268 | 269 | 2. **交互式系统** 270 | 交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。 271 | 272 |
273 | 时间片轮转 Round Robin 274 | 275 | 将所有就绪进程按 FCFS 的原则排成一个队列,用完时间片的进程排到队列最后。抢占式(时间片用完时),开销小,无饥饿问题,为短进程提供好的响应时间; 276 | 277 | 若时间片小,进程切换频繁,吞吐量低;若时间片太长,实时性得不到保证。 278 |
279 | 280 |
281 | 优先级调度算法 282 | 283 | 为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。 284 |
285 | 286 |
287 | 多级反馈队列调度算法 Multilevel Feedback Queue 288 | 289 | 设置多个就绪队列1、2、3...,优先级递减,时间片递增。只有等到优先级更高的队列为空时才会调度当前队列中的进程。如果进程用完了当前队列的时间片还未执行完,则会被移到下一队列。 290 | 291 | 抢占式(时间片用完时),开销可能较大,对IO型进程有利,可能会出现饥饿问题。 292 |
293 | 294 | ##### 什么叫优先级反转?如何解决? 295 |
296 | 展开 297 | 298 | 高优先级的进程等待被一个低优先级进程占用的资源时,就会出现优先级反转,即优先级较低的进程比优先级较高的进程先执行。此处详细解释优先级反转带来的问题:如果有一个中等优先级的进程将低优先级的进程抢占,那么此时低优先级的进程无法正常进行并在后续释放被占用的资源,导致高优先级的任务一直被挂起,直到中等优先级的进程完成后,低优先级的进程才可以继续并在后续释放占用的资源,最后高优先级的进程才可以执行。导致的问题就是高优先级的进程在中等优先级的进程调度之后。 299 | 300 | 解决方法: 301 | - 优先级天花板(priority ceiling):当任务申请某资源时,把该任务的优先级提升到可访问这个资源的所有任务中的最高优先级,这个优先级称为该资源的优先级天花板。简单易行。 302 | - 优先级继承(priority inheritance):当任务A申请共享资源S时,如果S正在被任务C使用,通过比较任务C与自身的优先级,如发现任务C的优先级小于自身的优先级,则将任务C的优先级提升到自身的优先级,任务C释放资源S后,再恢复任务C的原优先级。 303 |
304 | 305 | ### 什么是僵尸进程? 306 | 一个子进程结束后,它的父进程并没有等待它(调用wait或者waitpid),那么这个子进程将成为一个僵尸进程。僵尸进程是一个已经死亡的进程,但是并没有真正被销毁。它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程表中保留一个位置,记载该进程的进程ID、终止状态以及资源利用信息(CPU时间,内存使用量等等)供父进程收集,除此之外,僵尸进程不再占有任何内存空间。这个僵尸进程可能会一直留在系统中直到系统重启。 307 | 308 | 危害:占用进程号,而系统所能使用的进程号是有限的;占用内存。 309 | 310 | 以下情况不会产生僵尸进程: 311 | - 该进程的父进程先结束了。每个进程结束的时候,系统都会扫描是否存在子进程,如果有则用Init进程接管,成为该进程的父进程,并且会调用wait等待其结束。 312 | - 父进程调用wait或者waitpid等待子进程结束(需要每隔一段时间查询子进程是否结束)。wait系统调用会使父进程暂停执行,直到它的一个子进程结束为止。waitpid则可以加入```WNOHANG```(wait-no-hang)选项,如果没有发现结束的子进程,就会立即返回,不会将调用waitpid的进程阻塞。同时,waitpid还可以选择是等待任一子进程(同wait),还是等待指定pid的子进程,还是等待同一进程组下的任一子进程,还是等待组ID等于pid的任一子进程; 313 | - 子进程结束时,系统会产生```SIGCHLD```(signal-child)信号,可以注册一个信号处理函数,在该函数中调用waitpid,等待所有结束的子进程(注意:一般都需要循环调用waitpid,因为在信号处理函数开始执行之前,可能已经有多个子进程结束了,而信号处理函数只执行一次,所以要循环调用将所有结束的子进程回收); 314 | - 也可以用```signal(SIGCLD, SIG_IGN)```(signal-ignore)通知内核,表示忽略```SIGCHLD```信号,那么子进程结束后,内核会进行回收。 315 | 316 | ##### 什么是孤儿进程? 317 |
318 | 展开 319 | 320 | 一个父进程已经结束了,但是它的子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程会被Init(进程ID为1)接管,当这些孤儿进程结束时由Init完成状态收集工作。 321 |
322 | 323 | ### 线程同步有哪些方式? 324 | 325 | > 为什么需要线程同步:线程有时候会和其他线程共享一些资源,比如内存、数据库等。当多个线程同时读写同一份共享资源的时候,可能会发生冲突。因此需要线程的同步,多个线程按顺序访问资源。 326 | 327 | - **互斥量** Mutex:互斥量是内核对象,只有拥有互斥对象的线程才有访问互斥资源的权限。因为互斥对象只有一个,所以可以保证互斥资源不会被多个线程同时访问;当前拥有互斥对象的线程处理完任务后必须将互斥对象交出,以便其他线程访问该资源; 328 | - **信号量** Semaphore:信号量是内核对象,它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。信号量对象保存了**最大资源计数**和**当前可用资源计数**,每增加一个线程对共享资源的访问,当前可用资源计数就减1,只要当前可用资源计数大于0,就可以发出信号量信号,如果为0,则将线程放入一个队列中等待。线程处理完共享资源后,应在离开的同时通过```ReleaseSemaphore```函数将当前可用资源数加1。如果信号量的取值只能为0或1,那么信号量就成为了互斥量; 329 | - **事件** Event:允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。事件分为手动重置事件和自动重置事件。手动重置事件被设置为激发状态后,会唤醒所有等待的线程,而且一直保持为激发状态,直到程序重新把它设置为未激发状态。自动重置事件被设置为激发状态后,会唤醒**一个**等待中的线程,然后自动恢复为未激发状态。 330 | - **临界区** Critical Section:任意时刻只允许一个线程对临界资源进行访问。拥有临界区对象的线程可以访问该临界资源,其它试图访问该资源的线程将被挂起,直到临界区对象被释放。 331 | 332 | ##### 互斥量和临界区有什么区别? 333 |
334 | 展开 335 | 336 | 互斥量是可以命名的,可以用于不同进程之间的同步;而临界区只能用于同一进程中线程的同步。创建互斥量需要的资源更多,因此临界区的优势是速度快,节省资源。 337 |
338 | 339 | ### 什么是协程? 340 | 341 | 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。 342 | 343 | ##### 协程与线程进行比较? 344 |
345 | 展开 346 | 347 | 1. 一个线程可以拥有多个协程,一个进程也可以单独拥有多个协程,这样python中则能使用多核CPU。 348 | 349 | 2. 线程进程都是同步机制,而协程则是异步 350 | 351 | 3. 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态 352 |
353 | 354 | ### 进程的异常控制流:陷阱、中断、异常和信号 355 | 356 | 陷阱是**有意**造成的“异常”,是执行一条指令的结果。陷阱是同步的。陷阱的主要作用是实现**系统调用**。比如,进程可以执行 `syscall n` 指令向内核请求服务。当进程执行这条指令后,会中断当前的控制流,**陷入**到内核态,执行相应的系统调用。内核的处理程序在执行结束后,会将结果返回给进程,同时退回到用户态。进程此时继续执行**下一条指令**。 357 | 358 | 中断由处理器**外部**的**硬件**产生,不是执行某条指令的结果,也无法预测发生时机。由于中断独立于当前执行的程序,因此中断是异步事件。中断包括 I/O 设备发出的 I/O 中断、各种定时器引起的时钟中断、调试程序中设置的断点等引起的调试中断等。 359 | 360 | 异常是一种错误情况,是执行当前指令的结果,可能被错误处理程序修正,也可能直接终止应用程序。异常是同步的。这里特指因为执行当前指令而产生的**错误情况**,比如除法异常、缺页异常等。有些书上为了区分,也将这类“异常”称为**“故障”**。 361 | 362 | 信号是一种**更高层的**软件形式的异常,同样会中断进程的控制流,可以由进程进行处理。一个信号代表了一个消息。信号的作用是用来**通知进程**发生了某种系统事件。 363 | 364 | 更详细的可以参考:https://imageslr.github.io/2020/07/09/trap-interrupt-exception.html 365 | 366 | ### 什么是IO多路复用?怎么实现? 367 | IO多路复用(IO Multiplexing)是指单个进程/线程就可以同时处理多个IO请求。 368 | 369 | 实现原理:用户将想要监视的文件描述符(File Descriptor)添加到select/poll/epoll函数中,由内核监视,函数阻塞。一旦有文件描述符就绪(读就绪或写就绪),或者超时(设置timeout),函数就会返回,然后该进程可以进行相应的读/写操作。 370 | 371 |
372 | select/poll/epoll三者的区别? 373 | 374 | - ```select```:将文件描述符放入一个集合中,调用select时,将这个集合从用户空间拷贝到内核空间(缺点1:每次都要复制,**开销大**),由内核根据就绪状态修改该集合的内容。(缺点2)**集合大小有限制**,32位机默认是1024(64位:2048);采用水平触发机制。select函数返回后,需要通过遍历这个集合,找到就绪的文件描述符(缺点3:**轮询的方式效率较低**),当文件描述符的数量增加时,效率会线性下降; 375 | - ```poll```:和select几乎没有区别,区别在于文件描述符的存储方式不同,poll采用链表的方式存储,没有最大存储数量的限制; 376 | - ```epoll```:通过内核和用户空间共享内存,避免了不断复制的问题;支持的同时连接数上限很高(1G左右的内存支持10W左右的连接数);文件描述符就绪时,采用回调机制,避免了轮询(回调函数将就绪的描述符添加到一个链表中,执行epoll_wait时,返回这个链表);支持水平触发和边缘触发,采用边缘触发机制时,只有活跃的描述符才会触发回调函数。 377 | 378 | 总结,区别主要在于: 379 | - 一个线程/进程所能打开的最大连接数 380 | - 文件描述符传递方式(是否复制) 381 | - 水平触发 or 边缘触发 382 | - 查询就绪的描述符时的效率(是否轮询) 383 |
384 | 385 |
386 | 什么时候使用select/poll,什么时候使用epoll? 387 | 388 | 当连接数较多并且有很多的不活跃连接时,epoll的效率比其它两者高很多;但是当连接数较少并且都十分活跃的情况下,由于epoll需要很多回调,因此性能可能低于其它两者。 389 |
390 | 391 |
392 | 什么是文件描述符? 393 | 394 | 文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。 395 | 396 | 内核通过文件描述符来访问文件。文件描述符指向一个文件。 397 |
398 | 399 | ##### 什么是水平触发?什么是边缘触发? 400 |
401 | 展开 402 | 403 | - 水平触发(LT,Level Trigger)模式下,只要一个文件描述符就绪,就会触发通知,如果用户程序没有一次性把数据读写完,下次还会通知; 404 | - 边缘触发(ET,Edge Trigger)模式下,当描述符从未就绪变为就绪时通知一次,之后不会再通知,直到再次从未就绪变为就绪(缓冲区从不可读/写变为可读/写)。 405 | - 区别:边缘触发效率更高,减少了被重复触发的次数,函数不会返回大量用户程序可能不需要的文件描述符。 406 | - 为什么边缘触发一定要用非阻塞(non-block)IO:避免由于一个描述符的阻塞读/阻塞写操作让处理其它描述符的任务出现饥饿状态。 407 |
408 | 409 | ##### 有哪些常见的IO模型? 410 |
411 | 展开 412 | 413 | - 同步阻塞IO(Blocking IO):用户线程发起IO读/写操作之后,线程阻塞,直到可以开始处理数据;对CPU资源的利用率不够; 414 | - 同步非阻塞IO(Non-blocking IO):发起IO请求之后可以立即返回,如果没有就绪的数据,需要不断地发起IO请求直到数据就绪;不断重复请求消耗了大量的CPU资源; 415 | - IO多路复用 416 | - 异步IO(Asynchronous IO):用户线程发出IO请求之后,继续执行,由内核进行数据的读取并放在用户指定的缓冲区内,在IO完成之后通知用户线程直接使用。 417 |
418 | 419 | ### 什么是用户态和内核态? 420 | 421 | 为了限制不同程序的访问能力,防止一些程序访问其它程序的内存数据,CPU划分了用户态和内核态两个权限等级。 422 | 423 | - 用户态只能受限地访问内存,且不允许访问外围设备,没有占用CPU的能力,CPU资源可以被其它程序获取; 424 | - 内核态可以访问内存所有数据以及外围设备,也可以进行程序的切换。 425 | 426 | 所有用户程序都运行在用户态,但有时需要进行一些内核态的操作,比如从硬盘或者键盘读数据,这时就需要进行系统调用,使用**陷阱指令**,CPU切换到内核态,执行相应的服务,再切换为用户态并返回系统调用的结果。 427 | 428 | ##### 为什么要分用户态和内核态? 429 |
430 | 展开 431 | 432 | (我自己的见解:) 433 | 434 | - 安全性:防止用户程序恶意或者不小心破坏系统/内存/硬件资源; 435 | - 封装性:用户程序不需要实现更加底层的代码; 436 | - 利于调度:如果多个用户程序都在等待键盘输入,这时就需要进行调度;统一交给操作系统调度更加方便。 437 |
438 | 439 | ##### 如何从用户态切换到内核态? 440 |
441 | 展开 442 | 443 | - 系统调用:比如读取命令行输入。本质上还是通过中断实现 444 | - 用户程序发生异常时:比如缺页异常 445 | - 外围设备的中断:外围设备完成用户请求的操作之后,会向CPU发出中断信号,这时CPU会转去处理对应的中断处理程序 446 |
447 | 448 | ### 什么是死锁? 449 | 450 | 在两个或者多个并发进程中,每个进程持有某种资源而又等待其它进程释放它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁(deadlock)。 451 | 452 | ### 死锁产生的必要条件? 453 | - **互斥**:一个资源一次只能被一个进程使用; 454 | - **占有并等待**:一个进程至少占有一个资源,并在等待另一个被其它进程占用的资源; 455 | - **非抢占**:已经分配给一个进程的资源不能被强制性抢占,只能由进程完成任务之后自愿释放; 456 | - **循环等待**:若干进程之间形成一种头尾相接的环形等待资源关系,该环路中的每个进程都在等待下一个进程所占有的资源。 457 | 458 | ### 死锁有哪些处理方法? 459 |
460 | 鸵鸟策略 461 | 462 | 直接忽略死锁。因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。 463 |
464 | 465 |
466 | 死锁预防 467 | 468 | 基本思想是破坏形成死锁的四个必要条件: 469 | - 破坏互斥条件:允许某些资源同时被多个进程访问。但是有些资源本身并不具有这种属性,因此这种方案实用性有限; 470 | - 破坏占有并等待条件: 471 | - 实行资源预先分配策略(当一个进程开始运行之前,必须一次性向系统申请它所需要的全部资源,否则不运行); 472 | - 或者只允许进程在没有占用资源的时候才能申请资源(申请资源前先释放占有的资源); 473 | - 缺点:很多时候无法预知一个进程所需的全部资源;同时,会降低资源利用率,降低系统的并发性; 474 | - 破坏非抢占条件:允许进程强行抢占被其它进程占有的资源。会降低系统性能; 475 | - 破坏循环等待条件:对所有资源统一编号,所有进程对资源的请求必须按照序号递增的顺序提出,即只有占有了编号较小的资源才能申请编号较大的资源。这样避免了占有大号资源的进程去申请小号资源。 476 |
477 | 478 |
479 | 死锁避免 480 | 481 | 动态地检测资源分配状态,以确保系统处于安全状态,只有处于安全状态时才会进行资源的分配。所谓安全状态是指:即使所有进程突然请求需要的所有资源,也能存在某种对进程的资源分配顺序,使得每一个进程运行完毕。 482 | 483 | > 银行家算法 484 |
485 | 486 |
487 | 死锁解除 488 | 489 | > 如何检测死锁:检测有向图是否存在环;或者使用类似死锁避免的检测算法。 490 | 491 | 死锁解除的方法: 492 | - 利用抢占:挂起某些进程,并抢占它的资源。但应防止某些进程被长时间挂起而处于饥饿状态; 493 | - 利用回滚:让某些进程回退到足以解除死锁的地步,进程回退时自愿释放资源。要求系统保持进程的历史信息,设置还原点; 494 | - 利用杀死进程:强制杀死某些进程直到死锁解除为止,可以按照优先级进行。 495 |
496 | 497 | ### 存储管理方式 498 | 499 | 内存管理方式分为**连续分配管理**和**非连续分配管理**。连续分配管理分为单一连续分配、固定分区分配、动态分区分配以及动态重定位分区分配四种;非连续分配管理又叫离散分配方式,如果离散分配的基本单位是页Page,则称为分页存储管理方式;如果离散分配的基本单位是段Segment,则称为分段存储管理方式。 500 | 501 | **连续分配管理方式**允许一个用户程序分配一个连续的内存空间。 502 | 503 | - 单一连续分配:多用于单用户单任务的操作系统中,是一种简单的存储管理方式。单一连续分配中,会将存储空间分配为**系统区**和**用户区**。系统区存放系统进程,用户区存放用户进程,这样的管理可以避免用户进程影响到系统进程。这种分配方式中,比如0-a的地址空间存放系统区,那么a+1-n的地址空间都存放用户区。 504 | - 固定分区分配:是一种最简单的可运行多道程序的存储管理方式。固定分区分配首先要**划分分区**,之后进行**内存分配**。 505 | - 内存分区分为分区大小相等和分区大小不等两种。分区大小相等的情况下,如果进程大小不相等容易造成内存浪费或者内存不够进程无法运行的问题,所以通常用于进程内存大小相等的情况中。分区大小不相等,就是根据常用的大小(较多的小分区,适量的中分区,少量的大分区)进行分区,这样就可以更好地利用内存空间,但是这样的方式需要维护一个分区使用表。 506 | - 内存分配要维护一张分区使用表,通常按照进程大小进行排序。每次在进行内存分配的时候,要查看哪些分区能够容纳该进程。 507 | 508 | ![image-20220527171132306](_v_images/202205271711368.png) 509 | 510 | - 动态分区分配:根据进程的需要,动态地分配内存空间。这样的分配方式涉及到分区中的数据结构、分区分配算法以及分区的分配和回收操作三个问题。 511 | 512 | - 分区分配中的数据结构主要分为空闲分区表和空闲分区链两种。空闲分区表维护空闲分区的序号、空闲分区的起始地址以及空闲分区的大小数据。空闲分区链相当于一个双向链表,维护空闲分区;为了方便检索在分区尾部设置一个分区的状态位以及分区大小。 513 | - 分区分配算法主要有五种方法。**首次适应算法(First Fit)**,利用空闲分区链实现,将空闲分区按照地址递增(注意与后面的最佳适应区分,这里按照的是地址递增)进行排序,然后根据进程的大小**从链首查找空闲分区链**,第一个能够适应的就分配。**循环首次适应算法(Next Fit)**,不是每次都从链首开始查找,而是从上一次找到的空闲分区的下一个空闲分区开始查找,直到查找到一个能够使用的分区,之后动态地分配内存(会导致后续大空闲分区变少)。**最佳适应算法(Best Fit)**,将空闲分区链按照大小进行排序,找到第一个适应的空闲分区即可(最大限度利用空闲分区)。**最坏适应算法(Worst Fit)**,与最佳适应相反,排序之后每次挑选最大的分区使用,对中小作业有利,不易产生碎片。**快速适应算法(Quick Fit)**,根据大小将空闲分区进行分类,维护多个空闲分区链;这样的好处是可以加快检索,相比一条链能够更快地检索目标进程。 514 | - 分区分配和回收:主要操作是内存的分配和内存的回收。内存分配中,若空闲分区内存大小-用户进程内存大小<=预设不可切分内存大小,则进行一次内存的分配;否则将剩余的内存空间放到空闲内存链中,继续下次的使用。内存回收,主要看是否和空闲分区相邻,如果相邻就直接合并;否则就建立新的表项,维护回收区的内存起始地址和大小。 515 | 516 | - 动态重定位分区分配:在连续分配方式中,必须把系统进程或者用户进程装入一个连续的内存空间中。这个时候可能会因为程序的大小与分区的大小不一致的问题产生内存碎片。这个时候我们要想插入新的进程,即使碎片空间总和支持进程,也无法再分配空间,所以我们要把内存空间进行一个整理。 517 | 518 | ![image-20220527171146904](_v_images/202205271711967.png) 519 | 520 | - 整理内存地址,是将程序的内存地址整理成在物理上相邻的状态。程序使用的地址在分区装载之后仍然是相对地址,要想将相对地址转换为相邻物理地址,必然会影响到程序的执行。为了不影响程序的执行,需要在硬件上提供对程序的内存地址转换支持,于是引入重定位寄存器,用它来存放程序在内存中的起始地址。 521 | 522 | ![image-20220527171158815](_v_images/202205271711882.png) 523 | 524 | **非连续分配管理方式**允许将一个程序分散地装入不相邻的内存分区。根据内存分区的大小分为分页式存储管理方式和分段式存储管理方式。 525 | 526 | - 页存储:页存储首先需要将一个进程的**逻辑内存空间划分为多个内存大小相等的页**,然后将物理内存空间划分为相等的大小个数的物理块Block(页框Frame)。分配的时候将多个页面放入多个不相邻的物理块中。这样的划分之后,通常进程的最后一页存不满,会产生内存碎片——”页内碎片“。 527 | 528 | - 页面大小:页面大小的选定需要适当。如果过小,虽然可以减少页内碎片的产生,但是需要更大的页表,而且页面切换更频繁;如果太大就会产生较大的内存碎片。所以大小的选择应该适中,通常为2的整数次幂,范围为512B至8KB。 529 | 530 | - 页表:页表主要保存进程占用的页数,同时存储逻辑内存空间页到物理内存块的映射。 531 | 532 | ![image-20220527171217837](_v_images/202205271712893.png) 533 | 534 | - 地址转换:页表要存储地址映射,那么首先得有一个地址变换机构。基本地址变换机构,主要用来建立逻辑地址到物理内存空间地址的映射。传统系统中,主要使用寄存器来存放页表(寄存器速度快,有利于变换地址),那么每一个页表都需要寄存器来存放,成本过高。进程数量过多的情况下,首先将页表的**起始地址和页表长度**存放在PCB中,之后在进程运行的时候再将数据读取到PTR(Page-Table Register,页表寄存器)。读取数据的时候,地址转换机构会将相对地址转换为页号以及页内地址两部分,之后根据页号检索页表。检索之前会将页号和页表长度进行比较,如果页号大于或等于页表长度,则说明出现了访问越界,会出现越界中断。 535 | 536 | ![image-20220527171233940](_v_images/202205271712003.png) 537 | 538 | - 具有块表的地址转换机构:页表存放在内存中,那么将要先查页表,计算得出物理地址之后访问物理地址,是两次检索过程。 539 | 540 | - > 为了提高地址变换速度,可在地址变换机构中增设一个具有并行查寻能力的特殊高速 缓冲寄存器,又称为“联想寄存器”(Associative Memory),或称为“快表”。 541 | 542 | 对于32位操作系统,使用两级页表结构式合适的;但是对于64位操作系统,建议采用多级页表。 543 | 544 | - 段存储:使用段存储而不再使用页存储,第一个原因是提高内存的利用率,第二个原因是满足开发者在编程中的多种需求。主要是满足编程中的几个新的需求:**方便编程(简化逻辑地址访问方式)、信息共享(段式信息的逻辑单位)、信息保护(对信息的逻辑单位实现保护)、动态增长(分段更加满足动态增长的需求)、动态链接(链接装载使用段更符合需求)**。 545 | 546 | - 分段:作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息。 547 | - 段表:为每个分段分配一个连续的分区,进程每个段可以离散地存放到不同分区中,所以也需要维护一张段表,使得进程能够查到逻辑地址对应的物理地址,这个表就是段映射表,简称段表。 548 | - 地址变换机构:为了实现逻辑地址到物理地址的映射,系统设置了一个段表寄存器,用于存放段表地址和段表长度,如果段号大于段表长度,则表示发生了越界访问,产生越界中断;若未越界,找出该段对应段表项的位置,读出内存中的起始地址;再检查段内地址是否超过段长,如果超过段长,发出越界中断;否则将基址与段内地址相加,得出内存的物理地址。 549 | - 分段和分页的主要区别:①页是信息的物理单位,段是信息的逻辑单位;②页的大小由系统决定,段的大小不固定;③分页作业地址空间是一维的,分段作业地址空间则是二维的。即页的地址空间可以用一个符号来标识,而段的地址空间不仅要知道段名还要知道段内地址。 550 | 551 | - 段页存储:分页存储能提高内存利用率,分段存储能满足用户的更多需求。为了各取所长,产生了段页存储的管理方式。 552 | 553 | - 基本原理:段页存储,就是既分段也分页,先分段再分页。地址结构由段号、段内页号、页内地址三部分组成。 554 | - 地址变换过程:首先也需要准备一个段表寄存器,存放段表起始地址和段表长。首先将段号和段表长相比较是否越界;再利用段表起始地址和段表号来找到段表项在段表中的位置,从而得到页表地址;再之后使用段内页号来获取页表项的位置,找出物理块号,用物理块号和页内地址来构成物理地址。 555 | 556 | #### 分页和分段有什么区别? 557 | 558 | - 页式存储:用户空间划分为大小相等的部分称为页(page),内存空间划分为同样大小的区域称为页框,分配时以页为单位,按进程需要的页数分配,逻辑上相邻的页物理上不一定相邻; 559 | - 段式存储:用户进程地址空间按照自身逻辑关系划分为若干个段(segment)(如代码段,数据段,堆栈段),内存空间被动态划分为长度不同的区域,分配时以段为单位,每段在内存中占据连续空间,各段可以不相邻; 560 | - 段页式存储:用户进程先按段划分,段内再按页划分,内存划分和分配按页。 561 | 562 | 区别: 563 | - 目的不同:分页的目的是管理内存,用于虚拟内存以获得更大的地址空间;分段的目的是满足用户的需要,使程序和数据可以被划分为逻辑上独立的地址空间; 564 | - 大小不同:段的大小不固定,由其所完成的功能决定;页的大小固定,由系统决定; 565 | - 地址空间维度不同:分段是二维地址空间(段号+段内偏移),分页是一维地址空间(每个进程一个页表/多级页表,通过一个逻辑地址就能找到对应的物理地址); 566 | - 分段便于信息的保护和共享;分页的共享收到限制; 567 | - 碎片:分段没有内碎片,但会产生外碎片;分页没有外碎片,但会产生内碎片(一个页填不满) 568 | 569 | ### 什么是虚拟内存? 570 | 每个程序都拥有自己的地址空间,这个地址空间被分成大小相等的页,这些页被映射到物理内存;但不需要所有的页都在物理内存中,当程序引用到不在物理内存中的页时,由操作系统将缺失的部分装入物理内存。这样,对于程序来说,逻辑上似乎有很大的内存空间,只是实际上有一部分是存储在磁盘上,因此叫做虚拟内存。 571 | 572 | 虚拟内存的优点是让程序可以获得更多的可用内存。 573 | 574 | 虚拟内存的实现方式、页表/多级页表、缺页中断、不同的页面淘汰算法:[答案](https://imageslr.github.io/2020/07/08/tech-interview.html#virtual-memory)。 575 | 576 | ##### 如何进行地址空间到物理内存的映射? 577 |
578 | 展开 579 | 580 | **内存管理单元**(MMU)管理着逻辑地址和物理地址的转换,其中的页表(Page table)存储着页(逻辑地址)和页框(物理内存空间)的映射表,页表中还包含包含有效位(是在内存还是磁盘)、访问位(是否被访问过)、修改位(内存中是否被修改过)、保护位(只读还是可读写)。逻辑地址:页号+页内地址(偏移);每个进程一个页表,放在内存,页表起始地址在PCB/寄存器中。 581 |
582 | 583 | ### 有哪些页面置换算法? 584 | 在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘中来腾出空间。页面置换算法的主要目标是使页面置换频率最低(也可以说缺页率最低)。 585 | 586 | - **最佳页面置换算法**OPT(Optimal replacement algorithm):置换以后不需要或者最远的将来才需要的页面,是一种理论上的算法,是最优策略; 587 | - **先进先出**FIFO:置换在内存中驻留时间最长的页面。缺点:有可能将那些经常被访问的页面也被换出,从而使缺页率升高; 588 | - **第二次机会算法**SCR:按FIFO选择某一页面,若其访问位为1,给第二次机会,并将访问位置0; 589 | - **时钟算法** Clock:SCR中需要将页面在链表中移动(第二次机会的时候要将这个页面从链表头移到链表尾),时钟算法使用环形链表,再使用一个指针指向最老的页面,避免了移动页面的开销; 590 | - **最近未使用算法**NRU(Not Recently Used):检查访问位R、修改位M,优先置换R=M=0,其次是(R=0, M=1); 591 | - **最近最少使用算法**LRU(Least Recently Used):置换出未使用时间最长的一页;实现方式:维护时间戳,或者维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。 592 | - **最不经常使用算法**LFU(Least Frequently Used):置换出访问次数最少的页面 593 | 594 |
595 | 局部性原理 596 | 597 | - 时间上:最近被访问的页在不久的将来还会被访问; 598 | - 空间上:内存中被访问的页周围的页也很可能被访问。 599 |
600 | 601 |
602 | 什么是颠簸现象 603 | 604 | 颠簸本质上是指频繁的页调度行为。进程发生缺页中断时必须置换某一页。然而,其他所有的页都在使用,它置换一个页,但又立刻再次需要这个页。因此会不断产生缺页中断,导致整个系统的效率急剧下降,这种现象称为颠簸。内存颠簸的解决策略包括: 605 | 606 | - 修改页面置换算法; 607 | - 降低同时运行的程序的数量; 608 | - 终止该进程或增加物理内存容量。 609 |
610 | 611 | ### 缓冲区溢出问题 612 | 613 |
614 | 什么是缓冲区溢出? 615 | C 语言使用运行时栈来存储过程信息。每个函数的信息存储在一个栈帧中,包括寄存器、局部变量、参数、返回地址等。C 对于数组引用不进行任何边界检查,因此**对越界的数组元素的写操作会破坏存储在栈中的状态信息**,这种现象称为缓冲区溢出。缓冲区溢出会破坏程序运行,也可以被用来进行攻击计算机,如使用一个指向攻击代码的指针覆盖返回地址。 616 |
617 | 618 |
619 | 缓冲区溢出的防范方式 620 | 621 | 防范缓冲区溢出攻击的机制有三种:随机化、栈保护和限制可执行代码区域。 622 | - 随机化:包括栈随机化(程序开始时在栈上分配一段随机大小的空间)和地址空间布局随机化(Address-Space Layout Randomization,ASLR,即每次运行时程序的不同部分,包括代码段、数据段、栈、堆等都会被加载到内存空间的不同区域),但只能增加攻击一个系统的难度,不能完全保证安全。 623 | - 栈保护:在每个函数的栈帧的局部变量和栈状态之间存储一个**随机产生的**特殊的值,称为金丝雀值(canary)。在恢复寄存器状态和函数返回之前,程序检测这个金丝雀值是否被改变了,如果是,那么程序异常终止。 624 | - 限制可执行代码区域:内存页的访问形式有三种:可读、可写、可执行,只有编译器产生的那部分代码所处的内存才是可执行的,其他页限制为只允许读和写。 625 | 626 |
627 | 628 | 更详细的可以参考:https://imageslr.github.io/2020/07/08/tech-interview.html#stackoverflow 629 | 630 | ### 磁盘调度 631 | 过程:磁头(找到对应的盘面);磁道(一个盘面上的同心圆环,寻道时间);扇区(旋转时间)。为减小寻道时间的调度算法: 632 | 633 | - 先来先服务 634 | - 最短寻道时间优先 635 | - 电梯算法:电梯总是保持一个方向运行,直到该方向没有请求为止,然后改变运行方向。 636 | 637 | ### 参考 638 | - [进程间通信IPC -- 简书](https://www.jianshu.com/p/c1015f5ffa74) 639 | - [【面试】计算机操作系统-CSDN博客](https://blog.csdn.net/qq_43103529/article/details/121022006) 640 | - [面试/笔试第二弹 —— 操作系统面试问题集锦 - CSDN博客](https://blog.csdn.net/justloveyou_/article/details/78304294) 641 | - [线程同步与并发 - - SegmentFault](https://segmentfault.com/a/1190000018970361) 642 | - [彻底搞懂epoll高效运行的原理](http://baijiahao.baidu.com/s?id=1641172494287388070&wfr=spider&for=pc) 643 | - [用户态与内核态的切换](https://www.cnblogs.com/lirong21/p/4213028.html) 644 | 645 | ### 待完成 646 | - [ ] IPC 647 | - [ ] 进程同步问题:生产者-消费者问题... 648 | - [ ] 银行家算法 649 | - [ ] 文件与文件系统、文件管理? 650 |
651 | 652 |
653 | -------------------------------------------------------------------------------- /Python Handbook.md: -------------------------------------------------------------------------------- 1 | # Python 2 | 3 | * [什么是 Python 生成器?](#什么是-Python-生成器) 4 | * [什么是 Python 迭代器?](#什么是-Python-迭代器) 5 | * [list 和 tuple 有什么区别?](#list-和-tuple-有什么区别) 6 | * [Python 中的 list 和 dict 是怎么实现的?](#Python-中的-list-和-dict-是怎么实现的) 7 | * [Python 中使用多线程可以达到多核CPU一起使用吗?](#Python-中使用多线程可以达到多核CPU一起使用吗) 8 | * [什么是装饰器?](#什么是装饰器) 9 | * [Python 如何进行内存管理?](#Python-如何进行内存管理) 10 | * [Python 中的垃圾回收机制?](#Python-中的垃圾回收机制) 11 | * [什么是 lambda 表达式?](#什么是-lambda-表达式) 12 | * [什么是深拷贝和浅拷贝?](#什么是深拷贝和浅拷贝) 13 | * [双等于和 is 有什么区别?](#双等于和-is-有什么区别) 14 | * [其它 Python 知识点](#其它-Python-知识点) 15 | * [参考](#参考) 16 | 17 | ------ 18 | 19 | ## 什么是 Python 生成器? 20 | generator,有两种产生生成器对象的方式:一种是列表生成式加括号: 21 | 22 | ```g1 = (x for x in range(10))``` 23 | 24 | 一种是在函数定义中包含```yield```关键字: 25 | 26 | ```py 27 | def fib(max): 28 | n, a, b = 0, 0, 1 29 | while n < max: 30 | yield b 31 | a, b = b, a + b 32 | n = n + 1 33 | return 'done' 34 | 35 | g2 = fib(8) 36 | ``` 37 | 38 | 对于generator对象g1和g2,可以通过```next(g1)```不断获得下一个元素的值,如果没有更多的元素,就会报错```StopIteration``` 39 | 40 | 也可以通过for循环获得元素的值。 41 | 42 | 生成器的好处是不用占用很多内存,只需要在用的时候计算元素的值就行了。 43 | 44 | ## 什么是 Python 迭代器? 45 | Python中可以用于for循环的,叫做可迭代```Iterable```,包括list/set/tuple/str/dict等数据结构以及生成器;可以用以下语句判断一个对象是否是可迭代的: 46 | 47 | ```py 48 | from collections import Iterable 49 | isinstance(x, Iterable) 50 | ``` 51 | 52 | 迭代器```Iterator```,是指可以被```next()```函数调用并不断返回下一个值,直到```StopIteration```;生成器都是Iterator,而列表等数据结构不是;可以通过以下语句将list变为Iterator: 53 | 54 | ```iter([1,2,3,4,5])``` 55 | 56 | 生成器都是Iterator,但迭代器不一定是生成器。 57 | 58 | ## list 和 tuple 有什么区别? 59 | - list 长度可变,tuple不可变; 60 | - list 中元素的值可以改变,tuple 不能改变; 61 | - list 支持```append```; ```insert```; ```remove```; ```pop```等方法,tuple 都不支持 62 | 63 | ## Python 中的 list 和 dict 是怎么实现的? 64 | 65 | ## Python 中使用多线程可以达到多核CPU一起使用吗? 66 | 67 | Python中有一个被称为Global Interpreter Lock(GIL)的东西,它会确保任何时候你的多个线程中,只有一个被执行。线程的执行速度非常之快,会让你误以为线程是并行执行的,但是实际上都是轮流执行。经过GIL这一道关卡处理,会增加执行的开销。 68 | 69 | 可以通过多进程实现多核任务。 70 | 71 | ## GIL(Global Interpreter Lock) 72 | 全局解释器锁 73 | 74 | 全局解释器锁(Global Interpreter Lock)是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。即便在多核处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程,常见的使用 GIL 的解释器有CPython与Ruby MRI。可以看到GIL并不是Python独有的特性,是解释型语言处理多线程问题的一种机制而非语言特性。 75 | 76 | ### GIL的设计初衷? 77 |
78 | 展开 79 | 单核时代高效利用CPU, 针对解释器级别的数据安全(不是thread-safe 线程安全)。 80 | 首先需要明确的是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。当Python虚拟机的线程想要调用C的原生线程需要知道线程的上下文,因为没有办法控制C的原生线程的执行,所以只能把上下文关系传给原生线程,同理获取结果也是线 81 | 程在python虚拟机这边等待。那么要执行一次计算操作,就必须让执行程序的线程组串行执行。 82 |
83 | 84 | ### 为什么要加在解释器,而不是在其他层? 85 |
86 | 展开 87 | GIL锁加在解释器一层,也就是说Python调用的Cython解释器上加了GIL锁,因为你python调用的所有线程都是原生线程。原生线程是通过C语言提供原生接口,相当于C语言的一个函数。你一调它,你就控制不了了它了,就必须等它给你返回结果。只要已通过python虚拟机 88 | ,再往下就不受python控制了,就是C语言自己控制了。加在Python虚拟机以下加不上去,只能加在Python解释器这一层。 89 |
90 | 91 | ### GIL的实现是线程不安全?为什么? 92 |
93 | 展开 94 | 是不安全的,具体情况要分类讨论。 95 | 96 | 单核情况下: 97 | 98 | ![单核情况下——线程不安全](https://images2017.cnblogs.com/blog/1088183/201709/1088183-20170926140930839-80064182.png) 99 | 100 | > 解释: 101 | > 1. 到第5步的时候,可能这个时候python正好切换了一次GIL(据说python2.7中,每100条指令会切换一次GIL),执行的时间到了,被要求释放GIL,这个时候thead 1的count=0并没有得到执行,而是挂起状态,count=0这个上下文关系被存到寄存器中. 102 | > 2. 然后到第6步,这个时候thead 2开始执行,然后就变成了count = 1,返回给count,这个时候count=1. 103 | > 3. 然后再回到thead 1,这个时候由于上下文关系,thead 1拿到的寄存器中的count = 0,经过计算,得到count = 1,经过第13步的操作就覆盖了原来的count = 1的值,所以这个时候count依然是count = 1,所以这个数据并没有保护起来。 104 | 105 | python2.x和3.x都是在执行IO操作的时候,强制释放GIL,使其他线程有机会执行程序。 106 | 107 | Python2.x Python使用计数器ticks计算字节码,当执行100个字节码的时候强制释放GIL,其他线程获取GIL继续执行。ticks可以看作是Python自己的计数器,专门作用于GIL,释放后归零,技术可以调整。 108 | 109 | Python3.x Python使用计时器,执行时间达到阈值后,当前线程释放GIL。总体来说比Python3.x对CPU密集型任务更好,但是依然没有解决问题。 110 | 111 | 多核情况下: 112 | 113 | 多个CPU情况下,单个CPU释放GIL锁,其他CPU上的线程也会竞争,但是CPU-A可能又马上拿到了GIL,这样其他CPU上的线程只能继续等待,直到重新回到待调度状态。造成多线程在多核CPU情况下,效率反而会下降,出现了大量的资源浪费。 114 |
115 | 116 | ## 什么是装饰器? 117 | 118 | ## Python 中的垃圾回收机制? 119 | [Python垃圾回收机制--完美讲解!](https://www.jianshu.com/p/1e375fb40506) 120 | 121 | ## 什么是 lambda 表达式? 122 | 简单来说,lambda表达式通常是当你需要使用一个函数,但是又不想费脑袋去命名一个函数的时候使用,也就是通常所说的匿名函数。 123 | 124 | lambda表达式一般的形式是:关键词lambda后面紧接一个或多个参数,紧接一个冒号“:”,紧接一个表达式 125 | 126 | ## 什么是深拷贝和浅拷贝? 127 | 赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。 128 | 129 | 浅拷贝 copy.copy:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变) 130 | 131 | 深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数} 132 | 133 | ## 双等于和 is 有什么区别? 134 | ```==```比较的是两个变量的 value,只要值相等就会返回True 135 | 136 | ```is```比较的是两个变量的 id,即```id(a) == id(b)```,只有两个变量指向同一个对象的时候,才会返回True 137 | 138 | 但是需要注意的是,比如以下代码: 139 | 140 | ``` 141 | a = 2 142 | b = 2 143 | print(a is b) 144 | ``` 145 | 146 | 按照上面的解释,应该会输出False,但是事实上会输出True,这是因为Python中对小数据有缓存机制,-5~256之间的数据都会被缓存。 147 | 148 | ------ 149 | 150 | ## 其它 Python 知识点 151 | 152 | ### 类型转换 153 | - list(x) 154 | - str(x) 155 | - set(x) 156 | - int(x) 157 | - tuple(x) 158 | 159 | ### try...except 160 | 161 | ### list 162 | - ```lst[a:b]```:左闭右开 163 | - ```lst.append(value)```:在末尾添加元素,复杂度O(1) 164 | - ```lst.pop()```:弹出列表末尾元素,复杂度O(1) 165 | - ```lst.pop(index)```:弹出任意位置元素,将后面的元素前移,复杂度O(n) 166 | - ```lst.insert(index, value)```:插入元素,后面的元素后移,复杂度O(n) 167 | - ```lst.remove(value)```:移除等于value的第一个元素,后面的元素前移,复杂度O(n) 168 | - ```lst.count(value)```:计数值为value的元素个数 169 | - ```lst.sort(reverse = False)```:排序,默认升序 170 | 171 | ### 参考 172 | - [生成器 - 廖雪峰的官方网站](https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128) 173 | - [Python中的is和==的区别](https://www.cnblogs.com/yjtxin/p/11793243.html) 174 | - [为什么Python多线程无法利用多核](https://www.mdeditor.tw/pl/pXhj) 175 | - [GIL锁、线程锁(互斥锁)、递归锁(RLock)](https://www.cnblogs.com/Keep-Ambition/p/7596098.html) 176 | 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Waking-Up 2 | 3 | > 大多数人都高估了他们一天能做的事情,但低估了他们一年能做的事情 4 | 5 |
6 | 7 |
8 | 9 | 这是我用来准备后端开发校招面试的一个笔记本。按照计算机基础知识的不同版块,记录了面试中常见的问题以及比较规范的答案,大部分问题都带有更加细节的知识点追问。我用它来收集整理自己遇到的一些面试题,并且在面试前回顾。 10 | 11 |
12 | 13 | |    计算机网络    |    操作系统    |     数据库     |    设计模式    |      工具      |     Python     |      面经      | 14 | | :----------------------------------------: | :--------------------------------------------------: | :-------------------------------------------------------------: | :--------------------------------------------------: | :-----------------------------------------------------------------------: | :-------------------------------------------------------------: | :--------: | 15 | | [:cloud:](#1-计算机网络) | [:computer:](#2-操作系统) | [:floppy_disk:](#3-数据库) | [:art:](#4-设计模式) | [:wrench:](#5-工具) | [:snake:](#6-python) | [:memo:](#7-面经) | 16 |
17 | 18 | ### 如何使用? 19 | 20 | 这份笔记采用的并不是对每一个知识点进行讲解的形式,它的目的很纯粹,就是为了快速备战面试考点,因此全都是采用【常见面试问题 + follow-up questions + 可以直接采用的答案】的形式,力求达到效率备战的目的。 21 | 22 | 你可以将其作为**模拟面试**的问题来源,测试你的熟练程度;也可以当作面试前的**知识点梳理**,对一些细节问题进行填补; 23 | 24 | 当然,这个笔记本也同样适用于那些能够通过简历筛选,但是对计算机基础所知甚少的人,如果你之前从未在学校修过或者自学过这些课程,你依然可以通过这份笔记**快速备战面试**。 25 | 26 | 当你浏览每个版块的目录时,你可能会觉得并没有涉及到多少问题,但其实,**每个问题下的一连串追问**才是这些笔记的精华所在。如果你觉得你已经对目录中的问题了然于胸,你可以点进这些问题,多看看它们的 follow-up questions. 27 | 28 | 这个repo没有包含数据结构与算法部分,你可以查看我的另一个repo:[Solid data structure and algorithms](https://github.com/wolverinn/Iridescent),在这个repo中我系统地练习了各种数据结构和算法,并提供了Python代码 29 | 30 | ### Contribute 31 | 32 | 这个仓库目前还在不断完善之中,有些问题还没加入到笔记,有些问题的思路和答案可以做得更好!如果你有很棒的想法,欢迎提 issues 或者 pull requests! 33 | 34 | 感谢所有参与到这个项目中的伙伴们(如果下面漏掉了你,可以提醒我一下)~ 35 | 36 | Contributers: 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | ## 1. [计算机网络](Computer%20Network.md) 94 | 95 |
96 | 97 |
98 | 99 | ## 2. [操作系统](Operating%20Systems.md) 100 | 101 |
102 | 103 |
104 | 105 | ## 3. [数据库](Database.md) 106 | 107 |
108 | 109 |
110 | 111 | ## 4. [设计模式](Design%20Pattern.md) 112 | 113 | Provided by @[lutherlau](https://github.com/lutherlau) 114 | 115 |
116 |
117 |
118 |
119 | 120 | ## 5. [工具](Git-ComdLine-REST.md) 121 | 122 |
123 | 124 |
125 | 126 | ## 6. [Python](Python%20Handbook.md) 127 | 128 |
129 | 130 |
131 | 132 | ## 7. [面经](https://www.nowcoder.com/discuss/359048) 133 | 以下是我的面经,以及备战面试上岸经历分享 134 | - [字节跳动后端开发三轮面经](https://www.nowcoder.com/discuss/359048) 135 | - [字节跳动后端一面面经](https://mp.weixin.qq.com/s?__biz=MzU2OTk2Mzg3Mg==&mid=2247483685&idx=1&sn=933611d3dec4b4054cdbc33738261243&chksm=fcf7e52acb806c3c2390999e99a08e02ad51c484d5e47a9188fbcdb15e8693e11558915db842&token=1562114548&lang=zh_CN#rd) 136 | - [上岸经历分享](https://mp.weixin.qq.com/s?__biz=MzU2OTk2Mzg3Mg==&mid=2247483707&idx=1&sn=605d5f502dff18d6c335fefc677c0c55&chksm=fcf7e534cb806c22588ced14f6040e907a08d0c815a7ea8ba0f4cd2be0ac2d7821c490104764&token=1562114548&lang=zh_CN#rd) 137 | 138 | ## 补充:eyeglasses:: 139 | - 字节跳动内推(实习/社招/校招),请戳[:raising_hand::raising_hand:这里:raising_hand::raising_hand:](https://github.com/wolverinn/Waking-Up/issues/16) 140 | - 查看我的最新项目:[技术学习Roadmap](https://github.com/wolverinn/Build-your-programming-skills)(工作之后的个人技术成长路线) 141 | - 我的公众号:[Hardy的小屋](https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1807403091504250883),聊聊个人成长,欢迎关注 142 | 143 |
144 | 145 |
146 | 147 | 148 | ------ 149 | 150 | > 这个笔记本的名字来源于电影《Lone Survivor》中的配乐《Waking Up》;在电影中,这段配乐出现的场景,是两名队员在基地外面的大草原上晨跑。 151 | 152 | > 电影中我很喜欢的一句话: 153 | > Anything in life worth doing is worth overdoing. Moderation is for cowards. 154 | 155 | 156 |
157 | 158 |
159 | -------------------------------------------------------------------------------- /_v_images/1588679646408-22276075-76c2-42b2-8b20-84e3401fdbf7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588679646408-22276075-76c2-42b2-8b20-84e3401fdbf7.png -------------------------------------------------------------------------------- /_v_images/1588681690229-615d93e2-9429-42cc-812e-fa8cb7eb49a4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588681690229-615d93e2-9429-42cc-812e-fa8cb7eb49a4.png -------------------------------------------------------------------------------- /_v_images/1588687137859-38493900-8c93-43ef-bbe7-c67c14e9ba75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588687137859-38493900-8c93-43ef-bbe7-c67c14e9ba75.png -------------------------------------------------------------------------------- /_v_images/1588689300339-c33a3d0d-7544-4754-8695-b08fc843183d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588689300339-c33a3d0d-7544-4754-8695-b08fc843183d.png -------------------------------------------------------------------------------- /_v_images/1588746617916-a21ed08c-42df-40c0-bc79-6701209c2f55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588746617916-a21ed08c-42df-40c0-bc79-6701209c2f55.png -------------------------------------------------------------------------------- /_v_images/1588760917772-e4e10a15-0c43-456e-88f2-279fdd3e2d12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588760917772-e4e10a15-0c43-456e-88f2-279fdd3e2d12.png -------------------------------------------------------------------------------- /_v_images/1588761010089-ced9b3a9-3232-4729-943a-67c133909d7c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588761010089-ced9b3a9-3232-4729-943a-67c133909d7c.png -------------------------------------------------------------------------------- /_v_images/1588762859910-c08b6230-8358-42e8-aa48-5835af2d2940.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588762859910-c08b6230-8358-42e8-aa48-5835af2d2940.png -------------------------------------------------------------------------------- /_v_images/1588776261625-d6b2f2b2-85c7-4752-ba71-ac38f9ca639c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588776261625-d6b2f2b2-85c7-4752-ba71-ac38f9ca639c.png -------------------------------------------------------------------------------- /_v_images/1588776769193-d3a6ae4a-83d5-4fbf-b187-339039a22f25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588776769193-d3a6ae4a-83d5-4fbf-b187-339039a22f25.png -------------------------------------------------------------------------------- /_v_images/1588778531181-f78a0447-263d-40cf-bbfd-dfc565997dcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588778531181-f78a0447-263d-40cf-bbfd-dfc565997dcd.png -------------------------------------------------------------------------------- /_v_images/1588820461937-2a508c21-4203-4629-bcc1-ca0750f9fe84.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588820461937-2a508c21-4203-4629-bcc1-ca0750f9fe84.png -------------------------------------------------------------------------------- /_v_images/1588839044031-1dcdb9c4-a7c0-43b0-af86-4fb919336801.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588839044031-1dcdb9c4-a7c0-43b0-af86-4fb919336801.png -------------------------------------------------------------------------------- /_v_images/1588841461626-35402966-4817-4f7c-bc64-7fa4dbfc6a84.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588841461626-35402966-4817-4f7c-bc64-7fa4dbfc6a84.png -------------------------------------------------------------------------------- /_v_images/1588846767979-ce72003e-375a-4eea-8d13-eed6b726aa3b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588846767979-ce72003e-375a-4eea-8d13-eed6b726aa3b.png -------------------------------------------------------------------------------- /_v_images/1588848682603-c5da8658-bbda-4c63-9c3f-f9bc80a93299.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588848682603-c5da8658-bbda-4c63-9c3f-f9bc80a93299.png -------------------------------------------------------------------------------- /_v_images/1588850989407-80696883-cc5d-472b-a4de-0d5f5edd4cc4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588850989407-80696883-cc5d-472b-a4de-0d5f5edd4cc4.png -------------------------------------------------------------------------------- /_v_images/1588858153516-9c6b4ce0-aa41-42c4-b4c5-ae14e7faae51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588858153516-9c6b4ce0-aa41-42c4-b4c5-ae14e7faae51.png -------------------------------------------------------------------------------- /_v_images/1588859146567-662ae183-11ae-475d-8d8d-a8549f3d4026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588859146567-662ae183-11ae-475d-8d8d-a8549f3d4026.png -------------------------------------------------------------------------------- /_v_images/1588860191434-2b5ff1d1-06e8-4036-8f95-0adfe7e383c1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588860191434-2b5ff1d1-06e8-4036-8f95-0adfe7e383c1.png -------------------------------------------------------------------------------- /_v_images/1588861529453-aa147daa-653f-4559-b2ee-fdb0a370bf11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588861529453-aa147daa-653f-4559-b2ee-fdb0a370bf11.png -------------------------------------------------------------------------------- /_v_images/1588862264475-f62b4542-a18a-410e-b841-96049a3f2b44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588862264475-f62b4542-a18a-410e-b841-96049a3f2b44.png -------------------------------------------------------------------------------- /_v_images/1588863690354-5649da92-3741-4812-9f63-b5b7d0960238.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1588863690354-5649da92-3741-4812-9f63-b5b7d0960238.png -------------------------------------------------------------------------------- /_v_images/1615897397.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/1615897397.gif -------------------------------------------------------------------------------- /_v_images/20191129101827556_21212.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191129101827556_21212.png -------------------------------------------------------------------------------- /_v_images/20191129112652915_15481.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191129112652915_15481.png -------------------------------------------------------------------------------- /_v_images/20191129145400104_2106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191129145400104_2106.png -------------------------------------------------------------------------------- /_v_images/20191129153624025_28293.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191129153624025_28293.png -------------------------------------------------------------------------------- /_v_images/20191129155345024_11142.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191129155345024_11142.png -------------------------------------------------------------------------------- /_v_images/20191129161026032_32431.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191129161026032_32431.png -------------------------------------------------------------------------------- /_v_images/20191129195451183_16713.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191129195451183_16713.png -------------------------------------------------------------------------------- /_v_images/20191201081919108_30577.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191201081919108_30577.png -------------------------------------------------------------------------------- /_v_images/20191201085151639_2895.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191201085151639_2895.png -------------------------------------------------------------------------------- /_v_images/20191202090217863_1873.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191202090217863_1873.png -------------------------------------------------------------------------------- /_v_images/20191202162008435_14938.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191202162008435_14938.png -------------------------------------------------------------------------------- /_v_images/20191207081711185_20242.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191207081711185_20242.png -------------------------------------------------------------------------------- /_v_images/20191228182659294_7488.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191228182659294_7488.jpg -------------------------------------------------------------------------------- /_v_images/20191228182911371_900.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191228182911371_900.png -------------------------------------------------------------------------------- /_v_images/20191228183019711_10018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191228183019711_10018.png -------------------------------------------------------------------------------- /_v_images/20191229101924303_17994.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191229101924303_17994.png -------------------------------------------------------------------------------- /_v_images/20191229111930083_22798.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191229111930083_22798.png -------------------------------------------------------------------------------- /_v_images/20191229112508482_31766.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191229112508482_31766.png -------------------------------------------------------------------------------- /_v_images/20191229113357178_17374.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191229113357178_17374.png -------------------------------------------------------------------------------- /_v_images/20191229144622659_9248.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20191229144622659_9248.png -------------------------------------------------------------------------------- /_v_images/20200516165618.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20200516165618.png -------------------------------------------------------------------------------- /_v_images/20200516165630.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/20200516165630.png -------------------------------------------------------------------------------- /_v_images/202205271711368.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/202205271711368.png -------------------------------------------------------------------------------- /_v_images/202205271711882.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/202205271711882.png -------------------------------------------------------------------------------- /_v_images/202205271711967.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/202205271711967.png -------------------------------------------------------------------------------- /_v_images/202205271712003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/202205271712003.png -------------------------------------------------------------------------------- /_v_images/202205271712893.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/202205271712893.png -------------------------------------------------------------------------------- /_v_images/202205281423439.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/202205281423439.png -------------------------------------------------------------------------------- /_v_images/202205281424550.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/202205281424550.gif -------------------------------------------------------------------------------- /_v_images/image-20221212004219997.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/image-20221212004219997.png -------------------------------------------------------------------------------- /_v_images/image-20221212004254912.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/image-20221212004254912.png -------------------------------------------------------------------------------- /_v_images/image-20221212012139142.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/image-20221212012139142.png -------------------------------------------------------------------------------- /_v_images/image-20221216124728525.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/image-20221216124728525.png -------------------------------------------------------------------------------- /_v_images/image-20221216124900832.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/image-20221216124900832.png -------------------------------------------------------------------------------- /_v_images/image-20221216125001462.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/image-20221216125001462.png -------------------------------------------------------------------------------- /_v_images/image-20221216125538480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolverinn/Waking-Up/cf692b53e1b3d1b740a97dab0e4e71db801daf33/_v_images/image-20221216125538480.png --------------------------------------------------------------------------------