计算机网络与操作系统
2026-10-16 14:15:12 0 举报计算机网络涉及信息在网络中的传输,包括互联网技术、网络协议、数据交换、网络架构和安全策略等核心内容。操作系统则是计算机系统的核心软件,负责管理硬件资源和软件资源,提供用户交互界面。文件类型在计算机网络中可指网络传输的协议格式如HTTP(超文本传输协议)、TCP/IP(传输控制协议/互联网协议),而在操作系统中通常关联文件系统类型,如NTFS、FAT32等。修饰语可能体现在系统的稳定性、易用性或网络的高效率、安全性等方面。简而言之,计算机网络与操作系统是实现远程通信、资源共享与系统控制的关键领域,它们的协同工作确保了现代数字技术的高效与便捷。
java
模板推荐
作者其他创作
大纲/内容
计算机网络
<br>OSI七层模型/tcp ip五层模型<br>
应用层
文件服务、目录服务、文件传输服务(FTP)、远程登录服务(Telnet)、电子邮件服务(E-mail)、打印服务、安全服务、网络管理服务、数据库服务等
表示层
数据的表示、安全、压缩、JPEG、ASCII、EBCDIC
会话层
对话控制、令牌管理、同步、对应主机进程,指本地主机与远程主机正在进行会话
应用层(包含上三个)
输入url到渲染一次网页的过程,以及用来了什么协议
1.点下回车进行DNS域名解析
首先在浏览器缓存中找
然后在windows DNS缓存中找
然后在操作系统的host文件中找
然后本地的域名服务器去找 一般在你所在城市的某个角落
DNS 根域名服务器去找
顶级域名解析服务器
权威域名解析服务器
解析结果返回后操作系统缓存后 返回ip到浏览器
2.使用三次握手建立tcp连接
3.浏览器发起http请求
4,服务器解析http请求并找到指定资源后返回http响应
5.客户端解析html代码、然后请求代码中的资源
6.渲染展示界面
7.四次挥手关闭tcp连接
协议:DNS TCP IP OSPF ARP HTTP
DNS
组成
分布式服务分三层
1.根域名服务器 管理com\net\cn等顶级域名ip地址
2.顶级域名服务器 管理各自域名下面的全为域名如apple.com域名服务器的ip地址
3.权威域名服务器 管理www.apple.com的ip地址
减轻域名解析的服务器压力
本地DNS缓存
本地host文件
本地的DNS服务器【非权威域名】
大公司、网络运行商自己的 DNS 服务器 比如Google 的“8.8.8.8"
查找过程
<ul><li>客户端-->本地 (递归查询host和本地缓存)</li></ul>
根域名-->顶级域名-->权威域名搜到后-->存在本地DNS缓存
http
定义:http是超文本传输协议传输文字、图片、音频、视频等超文本数据的约定和规范
http和https的区别
1.http明文传输和https密文传输
2.http不需要ca证书、https需要
3.http响应快 https响应慢因为加了ssl
4.http端口80,https为443
https的加密机制
对称加密
相同的公钥加密
适合大数据加密、公钥的安全性需要考虑
非对称加密
最对不用的秘钥 公钥加密私钥加密或者私钥加密公钥解密
适合少数据量
公钥随意分发、私钥自己保存
报文加密
单向散列函数
ssl过程
证书验证阶段
1.浏览器发起https请求 要求和服务器建立ssl连接
2.服务端返回https证书,生成一对公钥和私钥 公钥发回给客户端
3.客户端验证证书是否合法,不合法就提示告警
数据传输阶段
1.服务端拥有非对称加密的公钥A和私钥A
2.浏览器向网站服务器请求,服务器把公钥A明文传给客户端
3.客户端随机生成对称加密的秘钥X,通过公钥A加密后发送给服务端
4,服务度解密后拿到对称秘钥X
5,后续双方使用X秘钥进行加密解密传输
bug
中间人攻击
中间人劫持后换成自己的非对称秘钥B来欺骗客户端然后解密得到客户端的随机秘钥X
预防
公钥由第三方认证机构CA来去报同一个
SSL协议
处于应用层和传输层之间
握手协议
1.建立安全连接
客户端发送支持的SSL版本号、session id、随机数、客户端支持的加密列表
服务端应答
2.服务器鉴别和秘钥交换
3.客户端鉴别和秘钥交换
4.完成
记录协议
客户端和服务端鉴别对方确认安全信息的算法
保密性,使用握手协议定义的秘钥实现
完整性,握手协议定义了消息认证码MAC保证完整性
警报协议
双方发现错误时向对方发送,致命错误立刻关闭ssl连接
会删除相关的会话号秘钥等第一个字节是错误类型,1是waring2是error 第二个字节是实际的错误类型
如果session已经有了执行会话恢复
客户端携带session id发送给服务端
服务端检索session id缓存记录,如果没有检查到缓存过期就按正常的握手过程进行
如果有就返回之前的加密的秘钥
<ul><li>主要任务是提供私密性,信息完整性和身份认证</li></ul>
http报文格式
请求报文
请求行
请求方法+URL+HTTP协议
GET /index.html HTTP/1.1
请求方法GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
get方法显示在?地址栏有字符限制最多1024个字符不适合大数据量传输
post方法不显示封装在http请求数据中
<ul><li><p>GET在浏览器回退时是无害的,而POST会再次提交请求。</p><p> </p></li><li><p>GET产生的URL地址可以被Bookmark,而POST不可以。</p><p> </p></li><li><p>GET请求会被浏览器主动cache,而POST不会,除非手动设置。</p><p> </p></li><li><p>GET请求只能进行url编码,而POST支持多种编码方式。</p><p> </p></li><li><p>GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。</p><p> </p></li><li><p>GET请求在URL中传送的参数是有长度限制的,而POST么有。</p><p> </p></li><li><p>对参数的数据类型,GET只接受ASCII字符,而POST没有限制。</p><p> </p></li><li><p>GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。</p><p> </p></li><li><p>GET参数通过URL传递,POST放在Request body中。</p></li></ul>
GET产生一个TCP数据包;POST产生两个TCP数据包。
GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
<span style="color:rgb(73, 73, 73); font-family:Arial, Helvetica, sans-serif; font-size:14px;">而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。</span>
火狐浏览器post只发一次
请求头部
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:<br><br>User-Agent:产生请求的浏览器类型。<br><br>Accept:客户端可识别的内容类型列表。<br><br>Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
空格
请求数据
响应报文
状态行=协议类型及版本号+状态码+状态码文字描述
状态码
1XX消息接收继续处理
100继续
101转换协议
102由webDAV扩展的状态码,代表处理将被执行
2XX成功
200 OK客户端请求成功
206与200基本相同但是响应头后面没有body数据,服务端区分是有必要的
3XX重定向
301 请求资源永久的更换了URI
308 永久跳转不允许post转向get请求
302 临时性跳转
允许各种重定向
303 任意请求到get重定向
307 不允许post到get重定向
304 重定向到缓存的文件
4XX客户端错误,
400 请求报文有错误
401 未授权需要身份验证
403 收到请求缺拒绝执行
404 没有找到请求的资源
405 采用浏览器不允许的请求方法请求
5XX服务端错误
500错误通用码
501 not implemented 客户端请求的功能还不支持
502 bad gateway 对用户访问请求的响应超时
503 服务器忙、无法响应服务
消息报头
响应正文
http1.0和1.1和1.2对比
主要是带宽和延迟(现在网络基础建设不用愁带宽影响网速了)
延迟
对头阻塞问题
http2.0解决
DNS查询问题
浏览器DNS hosts 本地DNS缓存解决
建立连接三次握手和慢启动
1.1解决
1.0和1.1对比
缓存处理
引入更多的缓存策略
节约带宽
允许只传输头部 206状态码
Host域
可存在多个虚拟主机共享一个ip地址
没有hos头域会报告400错误
新增24个状态码 409请求资源与当前状态冲突 410服务器某个资源被永久删除
长连接
一个tcp可以传送多个http请求和响应
1.x和2.0对比
多路复用
一个连接处理多个请求 对头阻塞的问题
头部压缩
编码压缩,双方维护索引表,记录出现过的head key-value
服务器推送
请求资源时服务器把多个资源传输给你
服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度
二进制协议
以前是文本的形式多样性
现在二进制健壮性
2.0和3.0对比
放弃了tcp协议基于udp的quic协议
<p><strong>HTTP2.0的多路复用和HTTP1.X中的长连接复用有什么区别?</strong></p><ul><li><p>HTTP/1.* 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;</p></li><li><p>HTTP/1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;</p></li><li><p>HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行;</p></li></ul>
短连接的优点是:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段。
长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。不过这里存在一个问题,存活功能的探测周期太长,还有就是它只是探测TCP连接的存活,属于比较斯文的做法,遇到恶意的连接时,保活功能就不够使了。在长连接的应用场景下,client端一般不会主动关闭它们之间的连接,Client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免某个蛋疼的客户端连累后端服务。<br><br>短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。<br><br>长连接和短连接的产生在于client和server采取的关闭策略,具体的应用场景采用具体的策略,没有十全十美的选择,只有合适的选择。
cookie、session和token
Token
服务器生成一串字符,作为客户端请求的令牌
减少服务器和数据库查询的压力
跨服务器使用
无状态可扩展
安全、无法伪造
使用设备号加MAC地址作为token
用session值做token
可以从http头部携带
cookie和session
session服务端保存的数据结构、表示和跟踪用户状态打开和关闭浏览器算作一次会话
cookie客户端的一种机制、存在客户端、不安全可以被用户静止单个容量不能超过4K 一个站点最多保存20个cookie sessionid 在cookie作用域是一次请求
均无法夸域名、token可以跨域名
Keep-Alive模式?
我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP协议为无连接的协议);当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
http 1.0中默认是关闭的,需要在http头加入"Connection: Keep-Alive",才能启用Keep-Alive;http 1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep-Alive连接就看服务器设置情况。
代理
只承担转发的作用,负载均衡的作用
轮训、最快响应时间、最少连接数、哈希和一致性哈希
2的32次幂为节点
增加虚拟节点每个服务器多次hash保证均匀
传输层给应用层提供的接口socket
基于TCP的编程
服务端
1.直接本地的端口创建ServerSocket的实例用来监听指定端口的连接请求
2.通过accept()方法返回socket实例,建立一个和客户端的新连接
3.通过Socket实例获取inputStrenm和outputStream读写数据
4.数据传输结束 close关闭
客户端
1.指定的远程服务器ip地址和端口创建Socket实例
2.通过Socket实例获取InputStream和OutputSteam来进行数据的读写
3.数据传输结束,调用soclet的close方法关闭连接
基于UDP的Socket编程
服务端
指定本地端口创建DatagramSocket实例
通过字节数组创建DatagramPacket实例,调用其receive方法来接受数据
设置实例返回的数据、调用send方法发送
传输完成关闭连接
客户端
创建实例
通过ip和端口调用send方法发送数据包
通过字节数组创建实例 receive方法接受数据包
传输完成关闭连接
传输层
TCP、UDP
TCP
TCP头部20字节
序列号字段Seq 32bits
首字节自己、初始随机
确认号字段Ack 32bits
确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号
窗口字段 16bits
用于流量控制、表示接收方缓存中的剩余空间
ACK 字段
占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效
RST、SYN、FIN字段
连接建立和拆除
RST:表示TCP出现差错,必须释放连接重新建立新的连接
HeaderLength
指明数据在段内的起始位置
三次握手
1.客户端向服务端发送SYN,携带目标ip 端口信息以及自己的序列号seq 然后进入SYN-SEND状态
2.Listen状态的服务端收到后给客户端返回SYN +ACK包、ack=x+1 seq 然后进入SYN-RCVD状态
3.客户端收SYN+ACK后向服务端返回ACK确认包,发送完毕后进入连接状态
问题1:为什么不是两次握手而是三次握手
1.TCP是可靠的通信协议,希望接受的数据是完整有序的。TCP为了实现可靠传输引入序号seq、确认号ack字段以此来判断对方是否收到没有就重发,通信时需要确认对方收到了初始序号。
2.两次握手下的场景及出现的问题
1.客户端不知道服务端的序列号从而认为连接未建立
2.客户端第一次发的请求延时很久导致这次连接结束后服务端又收到了,然后又建立了连接
3.三次握手可以避免两次握手的情况
问题2:如果最后一次握手ACK丢失会出现什么状态
客户端:一般通过connect()函数来连接服务器,第二次握手返回成功值,认为已经建立了连接会发送数据的带服务端的RST包响应感知错误
服务端:SYN-REVD状态会根据tcp超时重传机制,等待3秒6秒12秒后重新发送SYN+ACK包,重发次数在/proc/sys/net/ipv4/tcp_synack_retries修改默认是5,如果超过指定次数任然未收到ACK应答则断开连接。
四次挥手
1.首先客户端向服务端发送FIN序列号seq、然后客户端进入FIN-WAIT -1终止状态表示没有数据要发了
2.服务段收到客户端的FIN后,发出确认报文ACK、然后服务端进入CLOSE-WITE状态并通知应用层,等待数据发送完毕
3.客户端收到ACK后进入FIN-WITE-2状态对方已经同意释放连接了,此时服务度完成所有数据发送、给客户端发送FIN并进入LAST-ACK最后确认状态
4.客户端收到FIN后发出确认ACK,然后进入time-wait状态并经过2MSL(最长报文寿命)的时间后,进入CLOSE状态
MSL:最大分段寿命MSL典型值是30S 1min,表示一个分段在网络中的最大时间
问题3:为什么是四次挥手而不是三次
1.tcp是全双工的面向连接的可靠协议,所以A给B发后表示A没有数据发了,并不代表B没有数据发了,此时A还能收到B的数据,B给A发了ACK以后表示B知道A没数据发了但是B还有数据发。
2.建立连接时可以同时返回SYN-ACK 但是断开时,服务端数据并不一定完全发送完毕,所以要先确任然后等待数据发送完毕后再进行FIN请求
问题4:TIME-WAIT
问题2.1 TIME-WAIT状态的意义
1.保证全双工TCP可以连接正常终止,如果没有当A给B响应ACK后A关闭连接,次时如果ACK丢失,B以为A没有收到自己的关闭请求会重试发送FIN,此时A无法收到这个连接,导致B端异常
2.数据包正常过期防止lost duplicate对后续新建立的连接传输造成破坏
问题2.2 为什么TIME-WAIT状态需要经过2MSL才能CLOSE
正常来说四次挥手就应该断开连接,但是网络是不可靠的,有可能最后一个ACK丢失,2MSL是一个发送和回复的最大时间,如果直到2MSL都没到FIN客户端会以为ACK已经被成功接收断开连接
问题2.3 TIME-WAIT的危害
大量TIME-WAIT会发生什么
会导致高并发下大量端口被占用、多到把可用端口耗尽(65535),一段时间后大量释放、使得服务呈现忽好忽坏的变化
解决方案:优化TCP.IP内核参数(难度和风险很大),及时将time-wait状态的端口清理掉
1.客户端改成长连接 需要客户端改动比较大可以彻底解决问题高并发下性能较好
2.修改linux内核减少MSL时间:可以降低出问题的概率难度很高
问题5:如果已经建立连接,客户端突然故障怎么办
TCP有一个保活计时器,每次请求都会复位,如果两小时都没有收到客户端的信息,服务端会发送探测报文段每隔75秒发一次连续发10次都没有响应,服务器会认为客户端出现问题,接着关闭连接
问题6如何解决大量的close_wait和close_wait
调用netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
linux分配给用户的文件句柄是有限的1024
而TIME_WAIT和CLOSE_WAIT两种状态如果一直被保持,那么意味着对应数目的通道就一直被占着,而且是“占着茅坑不使劲”,一旦达到句柄数上限,新的请求就无法被处理了,接着就是大量Too Many Open Files异常,tomcat崩溃。。。
1.服务器保持了大量TIME_WAIT状态<br><br>2.服务器保持了大量CLOSE_WAIT状态
TIME_WAIT 814<br>CLOSE_WAIT 1<br>FIN_WAIT1 1<br>ESTABLISHED 634<br>SYN_RECV 2<br>LAST_ACK 1<br><br>常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。
Time-wait的解决办法
优化tcp-ip内核参数,及时将time-wait的端口处理掉
改客户端为长连接
修改msl的时间
closewait的解决办法
改改linux参数即可。
检查自己的代码吧,反正close_wait基本就是自己这边的问题了。
服务端接口耗时较长,客户端主动断开了连接,此时,服务端就会出现 close_wait
tcp如何保证可靠传输
1.校验和
TCP将保持首部和数据的校验和。这是个端到端的校验和,检测数据是否在传输过程中发生变化,如果收到的校验和有差错,TCP将丢弃这个报文段和不确认收到
2.流量控制:接收方要求发送方降低速率、tcp利用16位接收窗口字段实现
1.TCP连接都有固定大小的缓冲空间、接收端只允许发送接收端缓冲区能接纳的数据、如果接收方来不及处理数据,能提示发送方降低发送速率,防止丢包。(可变大小的滑动窗口协议)
2.发送窗口大小等于min(拥塞控制窗口),接收方(接受窗口)
3.0窗口探测,解决滑动窗口关闭的死锁问题
3.拥塞控制:网络拥塞时,减少数据的发送
1.慢启动
防止一开始大量传输导致网络拥塞,探测网络能接受的程度
初始cwnd=1 然后每次翻倍直到ssthresh出发拥塞避免
2.拥塞避免
每次cwnd+1 ,到达门限出发拥塞发生算法
3.拥塞发生时的两种算法
1.超时重传、ssthresh减半然后重置慢启动-->开始慢启动
计时器 基于时间的
2.快速重传
门限减半->开始快恢复
快重传
接收方收到失序报文后立即发出确认(让对方早知道),而不是等待自己发送数据再发送,发送方只有连续收到三个重复确认就立刻重传未收到的报文,而不是等待设置的重传计时器时间到期再重传
为什么三次确认?
概率学问题、因为内部顺序也是不一致的两次duuplicated ack可能是乱序造成的,三次也可能是丢包造成的、四次更可能是但是四次效率太低了,这是实践结果
4.快恢复
门限减半、起点减半+3*SMSS-->进入拥塞避免
3表示3个ack已经发送成功了这3个分段已经离开网络了,也就是可以再发3个分段了
如果没有快恢复会用定时器要求传输停止,暂停的时间没有新的数据包发送
4.ARQ自动重传协议:
1.停止等待ARQ
原理:发送完一个分组停止、等待对方确认,对方确认后再发下一个分组,如果发送方发完后一段时间没有收到确认帧,通常会重新发
优点:简单
缺点:信道利用率低,等待时间长
超时重传机制
tcp发出一个段后,启动一个定时器,等待目的段确认没如果不能及时收到就重发
确认丢失机制
A向B发 B给A确认,但是确认丢了A不知道,超时后A继续发 B会做两个事:1丢弃A重发的消息,2重新A发确认消息
确认迟到机制
B给A回的迟到,导致A一次收到两次确认:A丢弃第二次B的消息、B丢弃A第二次的消息
2.连续ARQ
原理:提供信道利用率,发送维持一个窗口,窗口内的分组连续发送出去不需要等对方确认,接收方累计确认对最后一个分组发送确认即可
优点:利用率高、容易实现、丢失也不必重传
缺点:不能及时给发送端反馈
保证可靠传输:数据包校验、失序的数据包重排交给应用层、丢弃重复数据、应答机制、超时重发、流量控制
粘包&拆包
发生原因
1要发送的数据大于TCP发送缓冲区剩余大小、发送拆包
2.待发送的数据大于MSS(最大报文长度),tcp将进行拆包
3.要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入的数据一次发出去,进行粘包
4.接收端应用层没有及时读取接受缓冲区的数据,将发送粘包
解决方案
1.给每个数据包增加首部,包含数据包实际长度,接收端就知道了
2.发送端每个数据包封装为固定长度(不够补0)
3.可以在数据包边界增加特定符号以方便拆包
可靠、面向连接的协议、复制处理流量控制
易受攻击
有确认、三次握手等机制容易实现DOS、DDOS、CC等攻击
场景
数据准确无误传递、HTTP、HTTPS、FTP等传输文件协议
UDP
8个字节头+有效载荷字段
源端口 16bit
目的端口 16bit
长度 16bit
UDP校验和 16bit
不可靠、无连接协议
场景
DNS、视频、聊天室
区别
1.TCP是建立连接 UDP是无连接的
2.TCP是可靠的、无差错、不丢失、不重复、按序到达;UDP不保证
3.TCP是面向字节流、UDP面向报文
4.UDP无拥塞控制适合实时性
5.TCP是点到点;UDP支持一对多,多对一
6.TCP首部20个字节;UDP8个字节
7.TCP全双工可靠信道;UDP不可靠信道
网络层
ICMP IGMP IP(IPV4 IPV6)
IP
1.ARP的作用
ip映射没mac
2.ARP高效运行的关键
每个主机都有ARP缓存
3.ARP报文:以太网首部+以太网地址+帧类型+ARP首部+发送者ip和硬件地址接受者ip和硬件地址
4.ARP的过程
1.在局域网内,主机A向主机B发送IP数据报时,首先会在主机A的ARP缓存表中查询iP--->mac的映射,有则加入MAC帧的首部,并通过局域网将该MAC帧发送到MAC地址所在的主机
2.没找到就广播,B收到消息给A以单播的形式发送一个带有自己MAC地址的相应分组
3.收到后就在ARO缓存表中写入主机B的ip和对应的MAC地址
4.如果不在同一个局域网,就去找吓一跳的路由器的地址,然后一跳一跳找到最终的B然后建立通信链路
ICMP
属于网络层,主要传递差错报文,和其他信息
主机不可达报文什么时候发出
路由器给主机寻路没有找找到路径向源ip发回icmp不可达
分类
差错报文
查询报文
ICMP重定向报文出现在在何种场合
主机发送ip数据报给R1默认下一跳R1 R1收到数据后检查路由表下一跳是R2于是给主机发送重定向报文,R1接受后数据报发送给R2不在给R1
ping是icmp重要的应用
1.向目的主机发送多个icmp回送请求报文
2.通过返回的回送报文的时间和成功相应次数估算数据包往返时间及丢包率
数据链路层
数据帧
物理层
传送比特流
问题汇总
问题1:为什么不是两次握手而是三次握手
1.TCP是可靠的通信协议,希望接受的数据是完整有序的。TCP为了实现可靠传输引入序号seq、确认号ack字段以此来判断对方是否收到没有就重发,通信时需要确认对方收到了初始序号。
2.两次握手下的场景及出现的问题
1.客户端不知道服务端的序列号从而认为连接未建立
2.客户端第一次发的请求延时很久导致这次连接结束后服务端又收到了,然后又建立了连接
3.三次握手可以避免两次握手的情况
问题2:如果最后一次握手ACK丢失会出现什么状态
客户端:一般通过connect()函数来连接服务器,第二次握手返回成功值,认为已经建立了连接会发送数据的带服务端的RST包响应感知错误
服务端:SYN-REVD状态会根据tcp超时重传机制,等待3秒6秒12秒后重新发送SYN+ACK包,重发次数在/proc/sys/net/ipv4/tcp_synack_retries修改默认是5,如果超过指定次数任然未收到ACK应答则断开连接。
问题3:为什么是四次挥手而不是三次
1.tcp是全双工的面向连接的可靠协议,所以A给B发后表示A没有数据发了,并不代表B没有数据发了,此时A还能收到B的数据,B给A发了ACK以后表示B知道A没数据发了但是B还有数据发。
2.建立连接时可以同时返回SYN-ACK 但是断开时,服务端数据并不一定完全发送完毕,所以要先确任然后等待数据发送完毕后再进行FIN请求
问题4:TIME-WAIT
问题2.1 TIME-WAIT状态的意义
1.保证全双工TCP可以连接正常终止,如果没有当A给B响应ACK后A关闭连接,次时如果ACK丢失,B以为A没有收到自己的关闭请求会重试发送FIN,此时A无法收到这个连接,导致B端异常
2.数据包正常过期防止lost duplicate对后续新建立的连接传输造成破坏
问题2.2 为什么TIME-WAIT状态需要经过2MSL才能CLOSE
正常来说四次挥手就应该断开连接,但是网络是不可靠的,有可能最后一个ACK丢失,2MSL是一个发送和回复的最大时间,如果直到2MSL都没到FIN客户端会以为ACK已经被成功接收断开连接
问题2.3 TIME-WAIT的危害
大量TIME-WAIT会发生什么
会导致高并发下大量端口被占用、多到把可用端口耗尽(65535),一段时间后大量释放、使得服务呈现忽好忽坏的变化
解决方案:优化TCP.IP内核参数(难度和风险很大),及时将time-wait状态的端口清理掉
1.客户端改成长连接 需要客户端改动比较大可以彻底解决问题高并发下性能较好
2.修改linux内核减少MSL时间:可以降低出问题的概率难度很高
问题5:如果已经建立连接,客户端突然故障怎么办
TCP有一个保活计时器,每次请求都会复位,如果两小时都没有收到客户端的信息,服务端会发送探测报文段每隔75秒发一次连续发10次都没有响应,服务器会认为客户端出现问题,接着关闭连接
问题6:ping命令是哪一层的协议?
ping命令是应用层协议,直接使用网络层的icmp协议向计算机发生ICMP回应报文
问题7:URL和URI的区别
URI是统一资源标志符,主要作用唯一标识一个资源--->身份证
URL统一资源定位符,提供路径--->通过URL地址找人
问题8:ARP协议
属于网络层协议,主要作用实现ip地址到mac地址的映射,每个主机或者路由器都有一个ARP缓存表,来找MAC地址
1. 基于功能来考虑,ARP是链路层协议<br>2. 基于分层/包封装来考虑,ARP是网络层协议
问题9:有了IP地址,为什么还要MAC地址?
1.ip地址用户可以更改,管理相对困难,MAC地址不可更改所以两者结合使用
2.只用MAC也是不行的,以前只用mac地址但是现在网络越来越多,路由过程越来越复杂,对于目的地址在其他子网的数据包,路由只需要送到子网就行
3.ip和地域关联 ,同一个子网的设备ip前缀都一样,这样路由器通过ip前缀就可以找到子网,如果只用mac,则路由器需要极大的空间来记录mac对应的子网,无法实现
操作系统
进程和线程
进程:操作系统资源分配的最小单位、每个进程包含多个线程同时拥有独立的一片内存
线程:程序执行的最小单位、处理器任务调度的基本单位
区别
1.内存
进程独占内存
同一进程的线程享用本线程的资源和空间
2.资源关系
进程切换消耗大
线程切换消耗小
3.影响关系
进程奔溃后不影响其他进程
线程挂了之后整个进程就挂了
进程的健壮性高
4.通信机制
线程通信不需要系统内核
进程通信需要系统内核
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快
进程
僵尸进程和孤儿进程
一般进程
子进程由父进程创建,子进程再创建新进程,父子进程是异步过程,父进程永远无法预测子进程结束,所有父进程可以调用wait()或waitpid()取得子进程的终止状态,回收掉子进程的资源
僵尸进程
子进程退出了,但是父进程没有用wait或waitpid去获取子进程的状态信息,子进程描述符依然保存在系统中,这种进程称为僵尸进程
waitpid提供了wait所没有的三个特性:<br> 1 waitpid使我们可以等待指定的进程<br> 2 waitpid提供了一个无阻塞的wait<br> 3 waitpid支持工作控制
孤儿进程
父进程结束了,子进程还在运行,那么子进程就称为孤儿进程,子进程资源有init(进程号pid=1)回收
问题危害
前提
unix提供了机制保证父进程知道子进程结束时的状态信息
进程退出后内核会释放所有资源打开的文件,占用的内存等但是保留一部分信息(进程号pid、退出状态、运行时间等)直到wait或者waitpid来取才能释放
如果父进程不调用wait或者waitpid 那么保留的信息就不会被释放,进程号被一直占用,系统提供的进程号有限65535,如果大量产生僵尸进程,将导致没有可用的进程号导致系统无法产生新进程
出init外的子进程exit后留一个僵尸进程的数据结构等待父进程去处理,没有及时处理出现僵尸进程可以用ps名字查询状态是Z
解决方案
1.通过信号机制
不会阻塞,什么时候得到子进程的信息什么时候处理、父进程可以继续处理别的任务
2.杀死父进程 全部交给init进程去回收资源
3.父进程用wait 或者waitpid 等待子进程结束,不好 父进程会一直等待挂起,相当于一个进程在干活
守护进程
运行在后台的特殊进程、独立于控制端,周期性执行某种任务或等待,父进程是init进程
进程的五种状态
1.创建状态
2.就绪状态
除cpu以外的资源都获取成功了
3.执行状态
4.阻塞状态
执行状态由某些事件而暂时无法运行,进程受阻塞。满足请求时进入就绪状态
5.终止状态
常用端口
80 http
22 SSH 远程登录
23 Telnet协议
25 邮件服务
3306 mysql
6379 redis
2181 zookeeper
切换
进程间切换
1.进程地址空间转换
2.处理器状态转换
3.过程 首先切换虚拟地址会需要操作系统内核去操作、寄存器的内容切换 其次TLB中记录的内存都失效了,重新换了虚拟地址后命中低,切换很慢
进程调度算法
非抢占式
最短作业作业优先SJF
从就绪队列选择估计用时最短的
最短剩余时间优先SRTF
剩余的最短
先来先到FCFS 队列实现
抢占式
轮转调度
时间片
优先级调度
优先级高的先进行
产生饥饿现象
多级反馈队列调度算法
优先级 高时间短
执行完后降级
最后一个队列实行轮转调度算法
线程间切换
时间片
系统调度
抢占式
java中的线程切换就是抢占式,时间片和切换都由操作系统来决定,每个线程有自己的时间片,根据优先级决定多少都有执行的时间这样就不会因为一个线程阻塞整个进程
协同式
线程执行完毕通知系统切换,不存在多线程同步问题,一个挂了阻塞整个进程
主动让出
1.放弃cpu不参与下次时间片的执行 yield
2.阻塞状态 i/o阻塞
3.执行完run方法
上下文切换
cpu切换把当前状态保存下来,包括寄存器的值、进程的状态,以及堆栈的内筒方便下次执行,一次保存到再加载的过程是一次上下文切换
1.挂起当前任务 当前任务的状态存在内存某处
2.恢复任务
3.程序计数器指向所在的位置,恢复进程
为什么会引起上下文切换
时间片用完
中断(硬件、软件)
用户态切换
抢占锁资源
开销
时间上创建需要分配内存
切换线程需要内存换页cpu缓存会清空,破坏数据的局部性
空间上一般分配1MB堆栈空间
线程间同步的方式
互斥量
sychronized和各种lock
信号量
Semphares
事件
wait notify 通知操作的方式保持多线程同步
线程切换和进程切换的主要区别
进程切换需要切换虚拟内存地址 线程切换不用,最显著的就是内核完成的寄存区的内容置换
进程的TLB被刷新需要重新进行命中率低
通信
进程间通信
1.无名管道pipe
用于亲缘关系的父子进程或者兄弟进程
| pipe
0读 1写
2.有名管道FIFO
任意进程间通信
半双工
3.消息队列
链表形式
生命周期等于内核
双向通信 多个读写
客服管道只能无符号字节流
4.共享内存
直接操作内存需要信号量保证同步问题
5.信号量
计数器,用来保证互斥和同步
pv操作 p是申请 v是归还
6.信号
ctrl + c 杀死进程
7、socket
不同机器间通信
区别
流管道s_pipe: 去除了第一种限制,为半双工,可以双向传输.管道只存在于内存
消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
消息队列允许任意进程通过共享队列来进行进程间通信。并由系统调用函数来实现消息发送和接收之间的同步。从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题,使用相对方便。
共享内存无须复制,信息量大是其最大的优势。但是需要考虑同步问题。
线程间同步
临界区
创建临界区对象
当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止。具体应用方式:<br>
事件
事件机制
事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。比如在某些网络应用程序中,一个线程如A负责侦听通信端口,另外一个线程B负责更新用户数据,利用事件机制,则线程A可以通知线程B何时更新用户数据。每个Cevent对象可以有两种状态:有信号状态和无信号状态。Cevent类对象有两种类型:人工事件和自动事件。
自动事件对象,在被至少一个线程释放后自动返回到无信号状态;
人工事件对象,获得信号后,释放可利用线程,但直到调用成员函数ReSet()才将其设置为无信号状态。在创建Cevent对象时,默认创建的是自动事件。
互斥量
互斥对象和临界区对象非常相似,只是其允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用,<br>但是更节省资源,更有效率
信号量
信号量(CSemphore)<br> 当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象。
死锁
死锁的条件+解决死锁的办法
1.互斥条件
无法解决,本来就是对临界资源互斥访问
2.不可剥夺
申请不到资源时,主动释放自己所持有的资源
3.请求与保持
1.一次性获取所有的需要的资源
优点简单易实施
缺点:缺少某个资源其他资源被持有是无效的
2.尝试获取资源,获取不到不阻塞
4.循环等待
按照某个顺序申请资源、释放时反序释放
按顺序给与资源会使某些资源空闲却得不到利用
避免死锁的办法
银行家算法
子主题
线程池
可以降低线程的创建、删除的开销
子主题
内存管理
虚拟内存
三大作用
缓存、内存管理、内存保护
32位操作系统 4GB内存、64位 2^64
可以把一部分硬盘空间当内存用,是一段连续的虚拟地址,让每个进程拥有一片完整的内存空间
优点:
提供更大的连续空间
进程隔离进程间的安全问题,这样就不会失误去改变别人的内存地址的数据
读写的安全性问题,不能直接操作物理内存
局部性原理
统一一段时间的程序出现的高度
1.时间局部性原理,for循环等导致一些数据经常被访问一些不会被访问
2.空间局部性
一个存储单元被访问,它附件的也会被访问
保证虚拟内存效率不会太低
分页
每个程序拥有的地址被分成一块一块,每块就是一页
4KB
为什么4kb?大的话进程可能用不完内存利用率降低,小的话内存管理单元的查询能力变差
页面中断
操作系统找一个很少使用的页框读入磁盘,修改映射关系
缺页中断
如果需要执行的指令 或访问的数据尚未在内存中,处理器通知操作系统将相应的页面或者段调入内存,然后继续执行程序
访问的页不在主存 需要操作系统调入主存后进行访问,如果当时没有空闲的页就必须选择一个页面移除内存,为即将调入的页面让出空间
TLB加速缓冲区
有的话直接读没有的话才去查询、查询结果存起来
假设页面大小4kB,32位地址空间将有100万页,那么页表将有100万项,查询很慢。
过程
1.根据虚拟地址中的页号查快表
2.如果命中则直接读取相应的物理地址
3.如果没命中,就访问内存中的页表,再从页表得到物理地址同时将页表中的该映射表项添加到快表中
4.当快表填满后,又要登记新页时按一定的淘汰策略淘汰掉快表中的一个页
页面置换算法
页面中断后如果操作系统内存没有空闲页面,必须选择一个页面移除
OPT无法实现的最佳置换
预测后面的调取次数然后选择
FIFO
LRU
CLOCK LRU+时钟
LFU
内存管理
连续分配 块式内存
有碎片浪费空间
非连续分配
段式管理
页式管理
4KB
大了进程用不完资源浪费
小了不够用,查询费时
段页式管理
先把主存分段、每段分页
段表+页表
段和页的区别
段是逻辑分段大小不固定由程序决定
页是操作系统决定的大小是固定的
段页都是为了提高内存利用率,减少内存碎片
状态切换
用户态——>内核态
1.系统调用(用户主动切换到内核)
2.异常,cpu执行的时候发生了缺页异常,会转换的内核态处理
3.外设设备中断
硬盘读写操作完成等
cpu寻址
逻辑(虚拟)地址和物理地址
java程序中输出数组的地址是虚拟地址 一般由操作系统决定
物理地址指的是真实内存中的地址,内存地址寄存器中的地址
虚拟寻址
使用虚拟寻址 cpu需要将虚拟地址转换为物理地址才能访问到真实的物理内存
什么是操作系统?
1.是管理计算机硬件与软件资源的程序
2,运行在计算机上的软件程序
3.为用户提供操作界面
4.分为内核和外壳
用户态和系统态
用户态运行的进程或程序可以直接读取用户程序的数据
系统态运行的进程或程序可以访问计算机的任何资源
操作系统调用的功能
设备管理
文件管理
进程控制
进程通信
<div><span style="font-size:inherit;">内存管理</span><br></div>
负责内存的分配和回收 malloc申请 free函数释放,以及虚拟内存地址到物理地址的转换
Java中
线程共享堆、方法区(元空间)
线程私有虚拟机栈、本地方法栈、程序计数器
至少包含GC进程和main进程
I/O
socket
linux
Linux把设备当做一种特殊的文件整合到文件系统中,每个I/O设备被分配了一条路径,通常在/dev目录下。例如:一个磁盘的路径可能是/dev/hd1,一个打印机的路径可能是/dev/lp,网络的路径可能是/dev/net
一切都是文件、给每个文件分配一个IDint型 被称为文件描述符 通常0表示输入 对应的硬件键盘 1表示输出对应的是显示器
UNIX/Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。<br><br>请注意,网络连接也是一个文件,它也有文件描述符!
我们可以通过 socket() 函数来创建一个网络连接,或者说打开一个网络文件,socket() 的返回值就是文件描述符。有了文件描述符,我们就可以使用普通的文件操作函数来传输数据了,例如:<br>用 read() 读取从远程计算机传来的数据;<br>用 write() 向远程计算机写入数据。<br><br>你看,只要用 socket() 创建了连接,剩下的就是文件操作了,网络编程原来就是如此简单!
windows
被称为句柄
同步和异步
都是描述用户线程和内核交互的方式
同步:用户线程发起IO请求后需要等待和轮询内核IO操作完成后才能执行
异步:用户线程发起IO请求后仍然可以执行,当内核IO操作完成后通知用户线程,或者调用用户线程注册的回调函数
阻塞和非阻塞
描述的是用户线程调用内核IO操作的方式
阻塞:IO操作需要彻底完成后才返回到用户空间
非阻塞:指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。
同步阻塞IO(BIO)
用户线程通过系统调用read发起IO读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作。用户需要等待read将socket中的数据读取到buffer后,才继续处理接收的数据。整个IO请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够。
简单理解:read操作整个线程阻塞 读取结束后才可以做事
同步非阻塞IO(NIO)
由于socket是非阻塞的方式,因此用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。即用户需要不断地调用read,尝试读取socket中的数据,直到读取成功后,才继续处理接收的数据。整个IO请求的过程中,虽然用户线程每次发起IO请求后可以立即返回,但是为了等到数据,仍需要不断地轮询、重复请求,消耗了大量的CPU的资源。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
简单理解:同步的所有read时不必立马处理,然后通过while不断轮询是否可以
IO多路复用
经典的Reactor设计模式,有时也称为异步阻塞IO
select
用户首先将需要进行IO操作的socket添加到select中,然后阻塞等待select系统调用返回。当数据到达时,socket被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行。<br><br>从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差。但是,使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断地调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的
简单理解:用select监视socket 娜个可以读了就让哪个去读 一个线程同时处理多个io请求
select
O(n)仅仅知道发生了I/0 无差别轮询所有流找出数据
特点:
监控fd标志位来处理,32位默认1024个
64位默认2048个
cat /proc/sys/fs/file-max可以查看
1.不管哪个活跃都会全部轮训一遍浪费cpu时间
2.开销大,存储标志位用户空间和内核空间传递该结构时复制开销比较大
poll
和select差不多O(n)它把用户传入的数组拷贝到内核空间,然后查询每个fd的设备状态,但是它没有最大连接数的限制 是链表存储
特点
遍历一遍把活跃的加入链表
<ul><li><p>poll还有一个特点是<code style="box-sizing: border-box; font-size: 12px; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; padding: 2px 4px; border: none; vertical-align: middle; white-space: pre-wrap; color: rgb(199, 37, 78); background-color: rgb(242, 242, 242);">水平触发</code>,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。</p></li></ul>
epoll
0(1) 会把哪个流发什么IO事件通知我们
所以我们说epoll实际上是事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))
特点
1.没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口);
2.效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数
3.内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。
原理
红黑树+双向链表+回调
1.内核在epoll文件系统建一个file节点
2.内核cache建立红黑树存储epoll传过来的socket文件描述符
3.建立双向链表存储就绪事件
epoll_ctl <span style="color:rgb(64, 72, 91); font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Liberation Sans", "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti", SimHei, SimSun, "WenQuanYi Zen Hei Sharp", sans-serif; font-size:16px;">会往红黑树中增加socket句柄,首先该句柄在红黑树中是否存在,存在就立即返回,不存在就插入红黑树中,然后</span><span style="box-sizing:border-box; font-weight:600; color:rgb(64, 72, 91); font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Liberation Sans", "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti", SimHei, SimSun, "WenQuanYi Zen Hei Sharp", sans-serif; font-size:16px;">给内核中断处理程序注册一个回调函数</span><span style="color:rgb(64, 72, 91); font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Liberation Sans", "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti", SimHei, SimSun, "WenQuanYi Zen Hei Sharp", sans-serif; font-size:16px;">,告诉内核,如果这个句柄的中断到了,就把它放到</span><span style="box-sizing:border-box; font-weight:600; color:rgb(64, 72, 91); font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Liberation Sans", "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti", SimHei, SimSun, "WenQuanYi Zen Hei Sharp", sans-serif; font-size:16px;">就绪链表中,【这就是回调啊】</span>
epoll_wait 检查就绪链表,把准备就绪的socket拷贝到用户态内存(少量的拷贝), 没有数据就sleep,等到timeout时间到后即使就绪链表没数据也返回
水平触发 LT、边沿触发ET
水平触发LT模式:level trigger、当epoll_wait检测到描述符事件发生并将此事件通知应用程序,**应用程序可以不立即处理该事件。**下次调用epoll_wait时,会再次响应应用程序并通知此事件
边沿触发ET模式:edge trigger、当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。
select、poll、epoll的优势在于可以以较少的代价来同时监听处理多个IO
问题1:
select一定比epoll差??
在并发量很低,连接都比较活跃的情况下,select的性能 可能 比epoll还好<br><br>因为:epoll的机制本身比较复杂,需要建立文件系统、红黑树、链表,还要回调机制来通知,所以是有一定开销的,效率反而不高;<br><br>但是在并发量高情况下,epoll是一个比较好的选择。
IO多路复用模型中,事件循环将文件句柄的状态事件通知给用户线程,由用户线程自行读取数据、处理数据
reactor管理select
异步IO
即经典的Proactor设计模式,也称为异步非阻塞IO
当用户线程收到通知时,数据已经被内核读取完毕,并放在了用户线程指定的缓冲区内,内核在IO完成后通知用户线程直接使用即可
零拷贝
优点
1.可以减少数据在内核缓冲区和用户进程缓冲区之间反复的 I/O 拷贝操作。
2.可以减少用户态和内核态之间的上下文切换而带来的 CPU 开销。
DMA技术称为 直接内存存取,是一种允许外围设备直接访问系统主内存的机制。
方式
1.用户态直接IO
应用程序直接访问硬件
操作系统内核辅助数据传输
依然存在用户空间和内核空间的上下文切换
<span style="color:rgb(64, 72, 91); font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Liberation Sans", "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti", SimHei, SimSun, "WenQuanYi Zen Hei Sharp", sans-serif; font-size:16px;">硬件上的数据直接拷贝至了用户空间,不经过内核空间</span>
不经过内核缓冲区和用户缓冲区直接的数据拷贝
2.减少数据拷贝次数
mmap + write
mmap 的目的是将内核中读缓冲区(read buffer)的地址与用户空间的缓冲区(user buffer)进行映射,从而实现内核缓冲区与应用程序内存的共享,省去了将数据从内核读缓冲区(read buffer)拷贝到用户缓冲区(user buffer)的过程
3.写时复制技术
<p>在某些情况下,内核缓冲区可能被多个进程所共享,如果某个进程想要这个共享区进行 write 操作,由于 write 不提供任何的锁操作,那么就会对共享区中的数据造成破坏,写时复制的引入就是 Linux 用来<span style="box-sizing:border-box; font-weight:600;">保护数据</span>的。</p><p>写时复制指的是当多个进程共享同一块数据时,如果其中一个进程需要对这份数据进行修改,那么就需要将其拷贝到自己的进程地址空间中。这样做并不影响其他进程对这块数据的操作,每个进程要修改的时候才会进行拷贝,所以叫写时拷贝。这种方法在某种程度上能够降低系统开销,如果某个进程永远不会对所访问的数据进行更改,那么也就永远不需要拷贝。</p>
BIO、NIO、AIO
BIO
同步阻塞IO
可以采取多线程的方式,让BIO能够处理多个请求,那么在服务器端就需要为每一个请求建立一个线程进行处理<br><br>BIO模式下,客户端和服务端的通信是阻塞式的,一应一答,在等待对方响应返回期间,线程被阻塞,什么也做不了。<br><br>所以,大量客户请求的时候,服务端的线程数量会剧增。<br><br>当然可以配合线程池的机制,减少线程创建销毁的代价。<br><br>所以BIO在连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的
NIO
同步非阻塞
引入selector buffer(缓冲区)、Channel(通道)
数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中<br><br>一个Selector可以监听多个Channel,所以单线程可以监听多个数据通道。<br><br>IO是面向流的,NIO是面向缓冲区的。
AIO
异步非阻塞
AIO的读和写都是异步的,<br><br>当线程调用read方法后,可以立即返回,做其他的事情,等到操作系统将数据拷贝到用户缓冲区后,会通知进程<br><br>当线程调用write方法后,可以立即返回,做其他的事情,当操作系统将需要写入的流
linux命令
文件 touch rm[-rf] vi/vim/cat
目录 mkdir mv cp cd ls
查看tcp连接的 netstat -napt
查看进程的 ps aux|grep redis ps所有进程 aux运行中的,grep xxx搜索结果
kill -9 进程pid -9:强制
sed -n '3,9' filename 查看第3到9行
压缩tar -zcvf
top Linux查看进程资源状态 windows的资源管理器
chmod -R 777* 给当前目录改变777权限 -R该目录下所有问题
查看端口被占用
netstat -tunle|grep 端口调用
netstat -an 查看网络状态
netstat -an|grep 80查看端口连接情况
linux学习
一切都是文件
读或者写
/bin
经常使用的命令
/boot
核心文件
/dev
/etc
配置文件
/home
自己的目录
命令
-a 查看隐藏文件
-l 查看文件
绝对路径/
相对路径 ../
pwd当前用户所在的目录
mkdir 创建目录
rmdir + 目录名字
删除目录
rmdir -p强制删除
rm -f 忽略不存在的文件,不会出现警告 强制删除
rm - r 递归删除
rm -rf、、、
删库跑路。。。一定不能执行
boot文件属性
第一个字母是d
目录文件
第一个字母是【-】
文件
第一个字母是[l]
链接
第一个字母是[b]
第一个字母是[c]
每三个一组
r可读,w写,x执行
常用数组r - 4 w --2 x -1
可读可写不可执行 rw- 6
chomd 777
赋予可读可写可执行
属主
属组
其他权限
三个都有rwx
ifconfig
看当前ip
more==cat
分页看
回车下一行
退出q
硬链接软连接
硬链接
A--B防止误删 一个文件拥有多个路径
ln创建
软连接
类似windows下的快捷方式
ln - s
du
查看磁盘管理
挂在 卸载
挂在 mount
umount -f
ps查看正在执行的各种进程信息
ps -a
显示终端运行的所有进程信息
ps -u
以用户的信息显示进程
ps -x
显示后台进程的参数
ps -aux|grep
|管道
查看指定字符串的命令
aux所有进程
评论
0 条评论
下一页