正文前面有一个破碎的念头,放在后面可能没人看233。
我本科非科班,秋季招聘找非技术岗位失败(不能通过群体),所以春季招聘转码。谁能想到春季招聘的形势比秋季招聘更严峻?….
我太难了,我太难了!
2月底开始投简历,3月份开始见面。tplink、字节、美团、广立微电子四家公司,最近春季招聘结束,得到了鳄梨的很多帮助!谢谢你!所以发送一些知识点来回馈鳄梨,也许明年有人会使用它?
我的春季招聘岗位都是测试/测试,测试涉及的东西太多了,反正你最好什么都懂,面试常见题和我问过的题都加了,和部分比较详细,还有也比较重点,然后加了一些小姐妹理出来。和常用操作!、、一点也没来得及理,先上岸了2333。
大部分内容来自牛客和谷歌。有些口语是我写的,但我觉得主要是整理(东抄西抄),不应该涉及版权问题。
我写了字节和美团的面试。面经很有趣。你可以去看看。tp我觉得这次面试没有参考价值,主要靠学校和成绩单保命,所以没发。
整个内容2万多字,背下来面试抱佛脚没问题。
但骗到offer之后还是要补一下学得更全面,不能光说2333。
祝大家都满意offer呀!!
Python
Python为什么是解释性语言?
顺序执行的 没有静态检查 没有编译链接过程 可交互操作
c错误的语言类型是编译和抛的错误,python错误的类型是错误的操作抛
也就是python一个一个操作,c需要整个编译才能运行
面向对象与面向过程的区别
面向对象是将构成问题的事务分解为每个对象,并在解决问题的步骤中建立对象来描述事务的行为;
面向过程是分析解决问题所需的步骤,然后用一些函数逐步实现这些步骤,使用时依次调用函数。
Python有什么优势
语法简单易懂,可读性强
有很多图书馆可以使用,可以让我们站在巨人的肩膀上,简单地实现我们想要的功能
与其他编程语言或编程语言或其他软件连接
免费开源,可移植
自动内存管理使程序员能够专注于代码的实现
缺点:
他的可解释特性使其运行速度变慢
动态语言的特点可能会增加运行时错误。
装饰器
装饰本质上是一个Python函数,它允许其他函数在不做任何代码变化的情况下添加额外的功能,它接受函数作为参数,并返回函数使用python的@语法来放置
功能:1。引入日志;2.函数执行时间统计;3.执行函数前的准备;4.执行函数后的清理功能;5.权限验证;6.缓存;
python 装饰器@staticmethod和@classmethod区别和使用
@classmethod:类方法,类方法是给类用的,类本身作为参数传递给类方法的第一个参数,python为我们内置函数classmethod将类中的函数定义为成类方法。
@staticmethod:静态方法
在实用类之前,使用使用上述两个装饰器对类进行实例化,
@property:将实例方法升级为属性,便于访问
写一个装饰器
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
functools.warp方法是把被wrapped的函数的属性传递给wrapper如果不写,不支持参数
深拷贝、浅拷贝和等号赋值
深度复制:建立一个新的对象,完全复制原始对象的内存,改变复制对象,不会改变原始内存的内容。(复制后两个对象完全独立)
等号赋值:相当于给原对象贴上新的标签。两个引用指向同一个对象,其中一个修改,另一个修改
浅拷贝:两种情况,1. 浅拷贝值是不可变对象(数值、字符、元组),与赋值相同id值与原始值相同;2. 若为可变对象(列表、字典等),a. 没有嵌套的简单对象,复制前后的对象不会相互影响,b. 对象中有复杂的子对象,如列表嵌套,如果原对象中复杂子对象的值发生变化,浅拷贝的值也会受到影响,因为会受到影响。
在python如何实现多线程?
Thread,然后可以使用新的线程GIL实现线程通信
GIL
GIL(全局解释锁)可以保证一次执行一个线程,轮流保存线程GIL并在将他传输到下一个线程之前执行一些操作,以实现多个过程CPU最后轮流运行,但转换速度很快,让我们觉得他并行。
类
类(Class): 用于描述具有相同属性和方法的对象的集合。它定义了集合中每个对象的共同属性和方法。对象是类别的例子。
继承/h>
当一个类继承自另一个类,它就被称为一个子类/派生类,继承自父类/基类/超类。它会继承/获取所有类成员(属性和方法)。
Python如何内存管理
1. 引用计数:python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收。
2. 垃圾回收:python会检查引用计数为0的对象,清除其在内存占的空间;循环引用对象则用一个循环垃圾回收器来回收
3. 内存池机制:在Python中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。这就意味着Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
a) Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
b) Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的 malloc。另外Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
Python垃圾回收机制
(自动处理分配回收内存的问题,没用了内存泄漏的隐患),以引用计数机制为主,标记-清楚和分代收集两种机制为辅
计数机制就是python中的每一个对象都有一个引用计数的值,当有引用的时候,这个值会增加,引用他的对象被删除时,这个值减小,引用计数的值为0时,该对象生命结束,python会把这段内存自动回收。(缺点,循环引用,如果l1和l2相互引用,没用其他的对象引用他们,这两段内存永远无法被回收)
猴子补丁
在运行期间动态修改一个类或模块,比较灵活?
引用通用库里的模块,又想丰富模块的功能,就可以用猴子补丁。
参数,传参
位置参数和关键字参数的区别
*args一定要在**kwargs前面
*args和**kwargs的含义
不知道向函数传递多少参数时,比如传递一个列表或元组,就使用*args
def func(*args):…
Func(1,2,3,4,5)
不知道该传递多少关键字参数时,使用**kwargs来收集关键字参数(keyword argument)
def func(**kwargs):…
Func(a=1,b=2,c=3)
全局变量和局部变量
常用方法
join()和split()
join(),把指定的字符串添加到字符串中,也可以把join后面带的一个含字符串的列表用指定的字符串连接起来
split(),把字符串用指定字符分割,结果是一个列表
strip(), lstrip(), rstrip()
移除字符串两边的空格
is家族 检查字符串…..
islower(), isupper(), istitle()…
isalnum(), isdigit(), isnumeric(), isdecimal()…
pass
比如函数没想好怎么写的时候可以用来在函数中占位,保证语法正确
continue直接跳到下一个循环,pass则是占位,虽然什么都不会发生,但是如果后面语句的话这些语句会继续运行
yield
1.保存当前运行状态(断点),然后暂停执行,即将函数挂起
2.将yeild关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用,当使用next()、send()函数让函数从断点处继续执行,即唤醒函数。
match()和search()
match()检测RE是不是在字符串开始位置匹配,只有在0匹配成功才返回True,search()会扫描整个字符串查找有无匹配
模块和包
模块:python中包含并有组织的代码片段,xxx.py的xxx就是模块名
包:模块之上的有层次的目录结构,定义了由很多模块或很多子包组成的应用程序执行环境。包是一个包含__init__.py文件和若干模块文件的文件夹。
库:具有相关功能模块的集合,python有很多标准库、第三方库…
闭包
闭包使得局部变量在函数外被访问成为可能。
python运算符(7)
算术、关系、赋值、逻辑、位、成员、身份运算符
多进制数字
0b二进制(bin),0o八进制,0x十六进制
Python标准数据类型(5)
Numbers数字,Strings字符串,Lists列表,Tuples元组,Dictionary字典
他们的一些特点:
元组解封装
Namedtuple:(从collections模块中导入)能够用标签获取一个元组的元素。
集合:无序且元素不重复
PYTHONPATH变量是什么
Python中的环境变量,用于在导入模块的时候搜索路径。因此它必须包含Python源库目录以及含有Python源代码的目录。
生成器generator和迭代器iterator
生成器
生成器是一种特殊迭代器。生成一系列的值用于迭代,在for循环的过程中不断计算出下一个元素并在恰当的条件结束循环
使用了yield的函数,返回迭代器
迭代器
迭代器是访问集合元素的一种方式,他的对象从集合的第一个元素开始访问,直到所有元素被访问完结束,用iter()创建迭代器,调用next()函数获取对象(迭代只能往前不能后退)。
两者区别:
1. 创建/生成,生成器创建一个函数,用关键字yield生成/返回对象;迭代器用内置函数iter()和next()
2. 生成器中yield语句的数目可以自己在使用时定义,迭代器不能超过对象数目
3. 生成器yield暂停循环时,生成器会保存本地变量的状态;迭代器不会使用局部变量,更节省内存
生成器和函数:
生成器和函数的主要区别在于函数 return a value,生成器 yield a value同时标记或记忆 point of the yield 以便于在下次调用时从标记点恢复执行。 yield 使函数转换成生成器,而生成器反过来又返回迭代器。
参数传递机制
如果实际参数的数据类型是可变对象(列表、字典),则函数参数的传递方式将采用引用传递方式。如果是不可变的,比如字符串、数值、元组,他们就是按值传递。
Python对象基本要素(3),id,type和value
==比较value,即值,is比较id
__new__和__init__的区别?
__new__:创建对象时调用,会返回当前对象的一个实例
__init__:创建完对象后调用,对当前对象的一些实例初始化,无返回值
调用顺序:先调用__new__生成一个实例再调用__init__方法对实例进行初始化,比如添加属性。
全局变量和局部变量
主(main)函数的作用
作为整个程序文件的入口。
调试代码的时候,在if __name__ == ‘__main__’中加入一些我们的调试代码,我们可以让外部模块调用的时候不执行我们的调试代码,但是如果我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!
cookie和session的关系和区别
cookie保存在浏览器端,session保存在服务器端,但是为了区分不同的客户端,服务器会在浏览器中发送一个对应的sessionid保存到cookies中,下次浏览器请求服务器的时候会将sessionid一并发送给服务器。所以session机制依赖于cookie机制
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
什么是Python的命名空间?
在Python中,所有的名字都存在于一个空间中,它们在该空间中存在和被操作——这就是命名空间。它就好像一个盒子,每一个变量名字都对应装着一个对象。当查询变量的时候,会从该盒子里面寻找相应的对象。
计算机网络
连不上网可能哪里有问题
网络模型
七层网络模型
1. 物理层:利用传输介质为数据链路层提供物理连接,实现比特流的透明传输。
2. 数据链路层
3. 网络层 IP
4. 传输层 TCP、UDP
5. 会话层
6. 表示层 对底层命令和数据进行解释,
7. 应用层 应用层协议:DNS、HTTP、SMTP等,用户在这一层与网络进行交互
TCP/IP四层
1. 网络接口层
2. 网际层 IP
3. 运输层 TCP、UDP
4. 应用层 HTTP、SMTP、FTP等
五层协议
1. 物理层 实现相邻计算机之间比特流的透明传递
2. 数据链路层 将IP数据报组装成帧,控制信息在相邻两节点的链路上进行传输
3. 网络层 IP,为不同主机分组交换信息服务
5. 运输层 TCP、UDP,为两台主机之间的通信提供通用的数据传输服务
4. 应用层 HTTP、SMTP、FTP等
HTTP
HTTP和HTTPS的区别
https需要到ca申请证书,因而需要一定费用
http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议,成本较高
http的连接很简单,是无状态的,https协议是由ssl+http协议构建的可进行加密串苏,身份验证的网络协议
http用的端口是80,https用的端口是443
HTTP请求报文的内容
请求行包括请求方法(GET、POST…),URL,HTTP协议版本
请求头。格式为,头部字段:值。常见头部字段有…
请求正文
HTTP头部有哪些主要字段
Host:接受请求的服务器地址,可以是IP或者是域名
User-Agent:发送请求的应用名称
Connection:指定与连接相关的属性,例如(Keep_Alive,长连接)
Accept-Charset:通知服务器端可以发送的编码格式
Accept-Encoding:通知服务器端可以发送的数据压缩格式
Accept-Language:通知服务器端可以发送的语言
HTTP响应报文
状态行:协议版本,状态码,状态码描述
响应头
响应正文
HTTP响应头主要字段
Server:服务器应用软件的名称和版本
Content-Type:响应正文的类型
Content-Length:响应正文的长度
Content-Charset:响应正文所使用的编码
Content-Encoding:响应正文使用的数据压缩格式
Content-Language:响应正文使用的语言
HTTP状态码
1xx 服务器收到请求,需要请求者继续执行操作
2xx ok,请求成功
3xx 重定向,资源已经重新分配
4xx 客户端请求错误,403 forbidden请求资源被拒绝,404 not found找不到请求资源
5xx 服务器错误,500 服务器故障,503 服务器超载或停机维护
200,请求成功
301,资源(网页等)被永久转移到其它URL
302,资源临时移动
403,forbidden,服务器理解请求客户端的请求,但是拒绝执行此请求。请求资源被拒绝,通常原因是服务器上某些文件或目录设置了权限,客户端权限不够
404,not found,用户输入错误的链接,该链接指向的网页不存在。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。
500,internal server error 服务器内部错误(比如浏览器代理除了问题,ip,端口不对等)该状态码表明服务器端在执行请求时发生了错误。也有可能是Web应用存在的bug或某些临时的故障。
502,Bad Gateway,作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503,服务器超载或停机维护
504,Gateway Timeout网关超时 服务器作为网关或代理,未及时从上游服务器接收请求。
HTTP劫持
在正常的数据流中插入特定的网络数据报文,让客户端解释错误的数据,并以弹出新窗口的形式向使用者展示小广告或网页内容
步骤:
在TCP连接中标识HTTP协议链接;
改HTTP响应体;
将篡改后的数据包抢先回发到用户,这样后面的数据包在到达后会被直接丢弃。而客户端显示改后的网页
防范:
事前加密:HTTPS,防止明文传输被挟持,(但防不了DNS挟持)
事中加密:拆分HTTP请求数据包,运营商的旁路设备没有完整的TCP/IP协议栈,不能标记,web服务器有完整的TCP/IP协议栈,能把接收到的数据包拼成完整的HTTP请求,不影响服务
事后屏蔽:前端显示HTTP时对内容进行检测,在DOM结构发生变化时触发回调
DNS劫持:通过劫持DNS服务器,获得某域名的解析记录控制权,修改此域名的解析结果。把原来对A域名的访问转入B域名,返回错误的查询结果。可能是一些产品的持续的推广
区别:DNS劫持倾向于持续性,访问一个界面时强行推送广告,HTTP劫持频率多变,劫持过程也非常快,一般多出现于网站小尾巴
HTTPS挟持:伪造证书来进行挟持….
跨域
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。
同源:域名,协议,端口均相同
即浏览器只能执行相同协议、相同域名、相同端口下的网站脚本,执行的时候如果网站的脚本不属于现在这个界面,就不会执行
HTTP请求响应中断原因
网断了,网络阻塞,请求超时,浏览器出问题,服务器出问题
如何检查
检查网络,检查本地…
HTTP有几种请求方式
HTTP1.0 定义了三种请求方法: GET, POST 和HEAD方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和CONNECT 方法。
GET和POST的区别
GET的参数放在url中,返回服务器拿数据;POST在request body里自带一个参数去服务器拿指定的数据;
因为GET的参数暴露在url上,所以安全性不能保证,也有长度的限制
应用场景
GET用来查询数据,POST用来修改数据,以及其他更需要安全性的场景如密码
DNS的查找过程(应用层)
用于将用户提供的主机名解析为ip地址
0. 浏览器从接收到的url中抽取出域名地址,将域名传给DNS应用的客户端
1. 检查浏览器缓存、本地hosts文件是否有这个网址的映射,如果有,就调用这个IP地址映射
2. 如果没有,则查找本地DNS解析器缓存是否有这个网址的映射,如果有,返回映射
3. 如果没有,则向DNS服务器提出查询请求
4. 服务器接收到查询时,查询本地配置区域资源,查到就返回结果
5. 如果查不到,但服务器缓存了此网址映射关系,返回查找结果
6. 如果没有缓存,就继续间请求转发至上一级DNS服务器进行查询。最终将解析结果依次返回本地DNS服务器,本地DNS服务器在返回给客户端,并把这个映射存到服务器的缓存中
IP
IP地址分类
A类:1字节(8位)网络号,3字节(24位)主机号。网络号第一位固定为0,剩下7位随便用。保留地址0(00000000)表示“本文网络”,127(01111111)表示本地环回软件测试
B类:2字节(16位)网络号,2字节(16位)主机号。网络号前两位固定为10,剩下16位随便用。保留地址
C类:3字节(24位)网络号,1字节(8位)主机号。前三位固定为110,剩下21位可用。
D类:
E类:
主机号全是0的IP地址表示是“本主机”所连接到的单个网络。
主机号全是1的IP地址表示是该网络上的所有主机。
A类地址的表示范围是:0.0.0.0-126.255.255.255,默认网络掩码为:255.0.0.0,A类地址分配给规模特别大的网络使用,
B类地址表示范围是:128.0.0.0-191.255.255.255,默认网络掩码为:255.255.0.0,B类地址分配给一般的中型网络
C类地址的表示范围是192.0.0.0-223.255.255.255,默认网络掩码是:255.255.255.0,C类地址分配给小型网络,如局域网
D类地址称为广播地址,共特殊协议向选定的节点发送信息使用。
ipv4和ipv6的转换。ipv4到ipv6的过渡手段
ipv4和ipv6的过渡是一个循序渐进的过程,在用户体验IPv6带来的好处的同时仍能与网络中其余的IPv4用户通信。
主流技术:1. 双栈策略:(最直接方式)在IPv6结点中加入IPv4协议栈。这种具有双协议栈的结点称作“IPv6/v4结点”,这些结点可以使用IPv4与IPv4结点互通,也可以直接使用IPv6与IPv6结点互通。
2. 隧道技术:(为解决局部纯IPv6网络与IPv4骨干隔离形成的孤岛问题,用隧道技术的方式解决)利用穿越现存IPv4互联网的隧道技术将孤岛连接起来,逐步扩大IPv6的实现范围。在隧道的入口处,路由器将IPv6的数组分组封装进入IPv4中,IPV4分组的源地址和目的地址分别是隧道入口和出口的IPV4地址。在隧道的出口处再将IPV6分组取出转发给目的节点。
隧道技术在实践中有四种具体形式:构造隧道、自动配置隧道、组播隧道以及6to4。
3. 隧道代理TB,Tunnel Broker。(目的是简化隧道的配置,提供自动的配置手段),TB可以看作是一个虚拟的IPv6 ISP,它为已经连接到IPv4网络上的用户提供连接到IPv6网络的手段,而连接到IPv4网络上的用户就是TB的客户。
4. 协议转换技术。其主要思想是在V6节点与V4节点的通信时需借助于中间的协议转换服务器,此协议转换服务器的主要功能是把网络层协议头进行V6/V4间的转换,以适应对端的协议类型。
5. SOCKS64。
在客户端里引入SOCKS库,它处于应用层和socket之间,对应用层的socket API和DNS域名解析API进行替换。
另一种是SOCKS网关。
6. 传输层中继
与SOCKS64的工作机理相似,只不过是在传输层中继器进行传输层的“协议翻译”
7. 应用层代理网关(ALG)
类似。在应用层进行协议翻译。
ARP协议
Address Resolution Protocol,即地址解析协议, 用于实现从 IP 地址到 MAC 地址的映射,即询问目标IP对应的MAC地址
1. 查主机缓存里(的ARP列表里)有没有记录这个IP和MAC地址的对应
2. 有就直接发送,没有就向本网段所有主机发送广播,发送自己的IP地址和MAC地址,询问谁是这个IP地址,这个地址的MAC地址是什么
3. 网络中的其他主机收到之后对照被询问的地址和自己能不能对上,是的话就从数据包中提取源主机的IP和mac地址写入自己的ARP列表,并将自己的MAC地址写入响应包,回复源主机
4. 源主机收到ARP响应包之后,就可以用这些信息发送数据
:OSI把网络分成7层,每层之间不直接交流,只有特定接口有交流。IP在第三层网络层,MAC地址工作在第二层数据链路层。协议发包时需要封装IP地址和MAC地址,但只知道IP,又不能跨层直接找,所以得用ARP协议的服务帮助获取目的节点的MAC地址
浏览器中输入一个URL后,按下回车后发生了什么
URL,统一资源定位符,l简单点就是网址=ip或域名 + 端口号 + 资源位置 + 参数 + 锚点
1.输入一个网址之后,首先浏览器通过查询DNS,查找这个URL的IP地址,(通过层层向上级DNS服务器查找直到找到对应URL的IP地址)
2.得到目标服务器的IP地址及端口号(http 80端口,https 443端口),会调用系统库函数socket,请求一个TCP流套接字。客户端向服务器发送HTTP请求报文
(1)应用层:客户端发送HTTP请求报文。
(2)传输层:(加入源端口、目的端口)建立连接。实际发送数据之前,三次握手客户端和服务器建立起一个TCP连接。
(3)网络层:(加入IP头)路由寻址。
(4)数据链路层:(加入frame头)传输数据。
(5)物理层:物理传输bit。
3.服务器端经过物理层→数据链路层→网络层→传输层→应用层,解析请求报文,发送HTTP响应报文。
4.关闭连接,TCP四次挥手。
5.客户端解析HTTP响应报文,浏览器开始显示HTML
网页卡顿原因
网速慢、带宽不足、硬件配置低、内存被占满。
JS脚本过大,阻塞了页面的加载。
网页资源过多、接受数据时间长、加载某个资源慢。
DNS解析速度。
一般怎么检查
硬件问题:检查网线或者无限网卡有没有插好,有没有连上路由器,就是底层是不是联通状态;
软件问题:查看是否有对应的驱动,服务器好不好,DNS对不对,或者可能是代理没关
当网页加载很慢的时候,应如何分析其原因并解决问题?
http请求次数太多
资源过大,资源过多
JS脚本过大
网速慢
…
给一个网址先解析什么后解析什么(域名解析顺序)?
域名分层:从右到左分别为顶级域名、二级域名…最左为主机名(服务器名)。比如www.baidu.com的com为顶级域名,email.tsinghua.edu.cn中cn为顶级域名,为中国国家域名,edu为教育科研部门域名,email为服务器名。
域名解析时,优先查找匹配的子域名,如果子域名存在,则从子域名的配置文件查询解析结果,如果子域名不存在,就从上一级的配置文件查询结果
高并发
响应时间、吞吐量、并发用户数…
测试多用户同时访问,访问量的缓慢增加/迅速增加…
大量相同类型访问,大量不同类型的访问
服务器角度,能够承受多大的压力(?),客户端角度,数据能否成功得到需要的信息,响应时间怎么样
实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息
一方面保证数据不丢失、一方面保证性能
TCP、UDP
TCP连接三次握手的过程
初始状态客户端CLOSED,服务器LISTEN
1. 客户端A向服务器B发送SYN数据包(SYN, x:0)请求连接。此时状态为SYN_SENT,表示客户端已发送SYN报文。
2. 服务器B收到,发送SYN/ACK数据包(SYN/ACK, y:x+1)回应。此时服务器状态由LISTEN(服务器socket处于监听状态,可以接受连接)变为SYN_RECV,表示收到SYN报文
3. 客户端A收到并发出确认ACK(ACK, x+1:y+1),连接成功。双方状态ESTABLISHED
TCP四次挥手的过程
初始状态双方ESTABLISHED
1. 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。客户端FIN_WAIT_1。表示主动关闭连接,向对方发送了FIN,进入FIN_WAIT_1,等待对方的确认
2. 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。客户端FIN_WAIT_2,表示半连接,而服务器可能还有数据要发,这边稍后关闭。服务器CLOSE_WAIT。
3. 服务器B关闭与客户端A的连接,发送一个FIN给客户端A。服务器LAST_ACK,等待对面的ACK报文
4. 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。客户端进入TIME_WAIT,表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。
为何TIME_WAIT:
防止服务器在处于LAST_ACK状态下未收到ACK报文而重发FIN报文,这个TIME_WAIT 状态的作用就是用来重发可能丢失的ACK报文。
TCP和UDP的特点
TCP面向连接,UDP无连接
TCP可靠,保证安全,UDP尽最大努力交付,不保证安全
TCP是点对点的,UDP可以一对一 一对多 多对多 多对一
TCP面向字节流,UDP无拥塞控制
TCP开销较大,UDP开销小
TCP、UDP的应用场景
UDP使用场景 DNS协议(因为用UDP快),看视频、发语音、QQ聊天、多媒体教室屏幕广播
TCP使用场景 HTTP协议,QQ传文件,邮件,登陆
TCP怎么实现可靠传输
确认和重传机制:建立连接、发送包时的确认,运输过程中校验失败、丢包或延时发送端重传
数据排序:把数据分成很多包,按顺序进行传输
流量控制:滑动窗口和计时器
拥塞控制:慢启动、拥塞避免、快速重传、快速恢复
流量控制
作用于接收方,控制发送者的发送速度从而使接收者来得及接收,防止分组丢失的。
由滑动窗口实现
滑动窗口
TCP进行流量控制的方式,接收方通过告诉对方自己的窗口大小,从而控制发送方的发送速度,以防止由于发送方发送速度过快而导致自己被淹没的现象
计时器
发送端收到为0的窗口后开启一个计时器,时间到了之后发包询问现在的滑动窗口,防止死锁(接收端发回的不为0的窗口的包丢失,双方相互等待)
拥塞控制
作用于网络,防止过多的数据注入到网络中,避免出现网络负载过大的情况。
拥塞:对网络中某一资源的需求超过了该资源所能提供的可用部分,影响到网络性能
拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。
拥塞窗口
发送方使用的流量控制,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。
慢启动和拥塞避免
慢启动:不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。
拥塞窗口一开始设为1 ,每收到一次确认,就让拥塞窗口变为原来的两倍,当窗口值为16时(慢启动门限),改为加法增大,每次+1,直到网络拥塞。拥塞时让新的慢启动门限设为拥塞时的一半,并把拥塞窗口置为1,再让他重复,这时一瞬间会将网络数据量大量降低。
拥塞避免:拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。
快重传和快恢复
快重传:接收方每收到一个失序的报文段(收完2后就收到了4说明3丢了)就立即发出包2的重复确认,这样可以让发送方尽早知道丢包了。
发送端连续收到三个重复确认就立即重传3
快恢复:发送方收到3个连续确认时,把慢开始门限减半,把拥塞窗口的值置为慢开始门限的一半,实行拥塞避免算法,每次确认收到后+1
操作系统
操作系统(Operating System,OS):
控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境的程序集合。
为用户提供服务,使用户能在计算机上使用各种应用程序来操作计算机资源
是用户和计算机硬件系统之间的接口
处理机:
计算机系统中存储程序和数据,并按照程序规定的步骤执行指令的部件。包括中央处理器、主存储器、I/O接口,处理器+外围设备(鼠标键盘之类)构成完整的操作系统
程序是描述处理机完成某项任务的指令序列。
指令则是处理机能直接解释、执行的信息单位。
中央处理器(CPU,Central Processing Unit):
是一块超大规模的集成电路,是一台计算机的运算核心和控制核心。它的功能主要是解释计算机指令以及处理计算机软件中的数据。
内核:
操作系统的最基本部分、核心,决定一个程序在什么时候对某部分硬件操作多长时间
提供操作系统的最基本的功能,是操作系统工作的基础,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性
操作系统的四个特性
并发:同一段时间内多个程序执行(与并行区分,并行指的是同一时刻有多个事件,多处理器系统可以使程序并行执行)
共享:系统中的资源可以被内存中多个并发执行的进线程共同使用
虚拟:通过分时复用(如分时系统)以及空分复用(如虚拟内存)技术把一个物理实体虚拟为多个
异步:系统进程用一种走走停停的方式执行,(并不是一下子走完),进程什么时候以怎样的速度向前推进是不可预知的
操作系统的目标和功能
处理机管理:
处理机的运行以进程(或线程)为基本单位,对处理机的管理可归结为对进程的管理。
管理进程的资源共享:进程控制、进程同步、进程通信、死锁处理、处理机调度
存储器管理:
给多道程序的运行提供良好环境,方便用户使用+提高内存利用率
内存分配、地址映射、内存保护与共享、内存扩充
文件管理:
计算机中的信息以文件形式存在。
文件存储空间管理、目录管理、文件读写管理和保护
设备管理:
完成用户的I/O请求,方便用户使用各种设备,并提高设备利用率
缓冲管理、设备分配、设备处理、虚拟设备
线程和进程
进程是操作系统进行资源分配和调度的最小单位,多个进程之间相互独立,如果一个进程崩溃,不会影响其他进程;
线程是CPU进行分配和调度的最小单位(或者说是进程的最小单位,进程的一部分),一个进程下可以有很多个线程共享该进程的所有资源,如果一个线程崩溃,整个进程就会崩溃。
进程和线程的区别
进程是操作系统进行资源分配和调度的最小单位,每个进程有自己的一部分独立的资源,如果一个进程崩溃,不会影响其他进程;线程是CPU进行分配和调度的最小单位,一个进程下可以有很多个线程共享该进程的所有资源,如果一个线程崩溃,整个进程就会崩溃。
线程一般是共享资源,在创建、或是进行调度的时候开销比进程小很多,通信同步也比较方便
通信方面进程间通讯需要同步或互斥手段的辅助,来保证数据的一致性,线程间可以直接读/写进程数据段(如全局变量)来进行通信。
简述多进程和多线程
线程间通讯和进程间通讯的方法
互斥量(全局变量):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
临界区:是一个访问共用资源的程序片段,而这些共用资源又无法同时被多个线程访问的特性。当有线程进入临界区段时,其他线程或是进程必须等待,有一些同步的机制必须在临界区段的进入点与离开点实现,以确保这些共用资源是被互斥获得使用。
共享内存就是映射一段能被其它进程访问的内存,这段共享内存由一个进程创建,但是多个进程可以访问。读写操作时需要用同步互斥的工具,保证在一个进程对这段内存进行访问的时候其他进程不能同时来
信号量是一个计数器,用来控制多个进程对资源的访问,它通常作为一种锁机制。
管道是一种半双工的通信方式,数据只能单项流动,并且只能在具有亲缘关系的进程间流动,进程的亲缘关系通常是父子进程。Pipe(管道),FIFO(有名管道)。调用管道,在内核里开辟一块缓冲区(一个共享文件)来进行进程间通信,有一个读端和一个写端(单向通信)
消息队列是消息的链表,存放在内核中并由消息队列标识符标识。
进程同步
目的:对多个相关进程在执行顺序上进行协调,使并发执行的进程可以有效的共享资源和相互合作,保证程序执行的可再现性。
进程死锁
多个并发的进程中,如果每个进程都持有某种资源由等待其他进程释放它现在保持的资源,这些资源都只允许一个进程占用,结果两个进程都不能继续执行,也不会释放自己占有的资源,所以这种双方循环等待的现象回无限期持续,发生死锁。
互斥条件:资源不能共享,只能一个进程用
请求与保持条件:已经得到资源的进程可以再次申请新的资源
非剥夺条件:已经分配的资源不能从相应进程中强制剥夺
循环等待条件:系统中若干进程形成环路,环路中的每个进程都在等待相邻进程正占用的资源
预防:破环四个原因中的一个或多个,但会影响到资源利用率及吞吐量
避免:在资源的动态分配中防止系统进入不安全状态
检测:死锁发生后,用一定的算法进行检测,并确定相关死锁相关的资源和进程,采取方法清楚死锁。
解除:对死锁相关进程,通过撤销或挂起的方式,释放一些资源
处理机调度
常用的调度算法
先来先服务调度:按进程到达的先后顺序依次调度
短作业优先调度:选择队列中估计时间较短的先进行处理
优先权调度:为不同队列设不同的优先级,等待时间长的适当提高优先级
时间片轮转:按进程到达的先后顺序放入队列,给队首进程分配CPU时间片,用完后计时器发出中断,暂停当前进程并将其放到队伍尾部,循环。
线程状态(5)
创建:new Thread(r)创建,有了相应的内存空间和其他资源,但还未开始执行
就绪:start()方法启动,进入线程队列排队,等待CPU服务
运行:获得处理器资源
阻塞:需要进行耗时的输入输出操作时,要等阻塞清除才能进入队列排队
终止:stop()、destory()或run()结束后,不在具有继续运行的能力
进程三态的转化(也有说5态的,和线程差不多)
运行状态:进程正在处理机上运行。在单处理机环境下,每一时刻最多只有一个进程处于运行状态。
就绪状态:进程已处于准备运行的状态,即进程获得了除处理机之外的一切所需资源,一旦得到处理机即可运行。(只缺处理机这个资源)
阻塞状态,又称等待状态:进程正在等待某一事件而暂停运行,如等待某资源为可用(不包括处理机)或等待输入/输出完成。即使处理机空闲,该进程也不能运行。(缺除了处理机之外的其他资源)
四个转换的过程
僵尸进程
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。
孤儿进程
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
内存
内存分区
(高地址)
栈区:编译器自动分配,存放函数的参数值、局部变量的值,系统自动回收用完的内存
堆区:一般由程序员分配(malloc申请内存和free释放内存),如果不释放内存容易因引起内存泄漏
全局区(静态区):静态变量和全局变量,内存被分配后直到程序结束之后才释放
常量区:(只读)存一些字符串常量、数组名等
代码区:(只读)存一些CPU执行的一些机器指令
(低地址)
堆和栈的区别
栈:先进后出,生长方向向下,系统自动分配回收,高效快速;但有限制,数据不灵活。申请内存时,只要栈的剩余空间大于所申请的空间,系统将为程序员提供内存,否则报栈溢出。
堆:向上生长,需要程序员自己申请并指明大小。堆里分布的内存是不连续的。操作系统应该有记录空闲内存地址的链表,申请内存时遍历链表,找第一个空间大于申请空间的堆节点,分配内存…
把数据存到栈里比堆更快,因为系统会自动分配内存,堆需要自己分配和释放内存;另外访问堆的一个具体单元需要两次访问内存,一次获得指针,第二次才是真正的数据,而栈只要一次。
缓冲区
又称缓存。在内存空间中预留一定的存储空间,用来缓冲输入输出的数据。
原因:CPU直接从磁盘读数据速度慢,增加读写次数对磁盘性能会有影响;使用缓冲区减小读写次数,CPU对缓冲区的操作速度也远大于磁盘的操作速度,增加计算机的运行速度。
缓冲区溢出
计算机向缓冲区填充数据的时候超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。导致程序崩溃、趁这个机会获取程序乃至系统的控制权。
虚拟内存
相当于从逻辑上扩充内存容量,在程序装入的时候,只把程序的一部分装入内存,就启动程序执行,执行过程中,访问的信息不在内存里时,操作系统将需要的部分调入内存,并把暂时不适用的内容换到外存上,腾出内存空间。让应用程序认为他用了一个比实际内存大得多的存储器。
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
多次性、对换性、虚拟性
内存泄漏
程序没有释放已经不再使用的内存,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,因此这段内存一直被占用,无法释放,造成空间的浪费。
怎么查
1. 用封装的malloc函数,写代码时在malloc外封装一层,封装函数内打印一下malloc地址,free也是,然后运行时收集打印信息,可以用另外的脚本来分析内存的申请和释放是否一一对应。
2. dmalloc库,第三个方案是valgrind工具 提一下常用的用法就行。
内存溢出
要求分配的内存超过了系统能给我的,系统不能满足需求。内存泄漏的堆积如果不及时处理最终会导致内存溢出
基本分页储存管理方式
把主存空间划分为大小相等且固定的块,作为主存的基本单位,每个进程也以块为单位进行划分,进程执行时,以块为单位逐个申请主存中的块空间。用页表记录分散的内存分布情况。
:
用来记录逻辑地址和实际存储地址之间的映射关系,以实现从页号到物理块号的映射。
访问分页系统中内存数据需要两次内存访问,一次从内存中访问页表,找到实际物理地址,第二次根据得到的物理地址访问内存
页表储存在内存中。
逻辑空间->页表->物理空间
访问内存数据的时候先在快表里查询,如果查到了就可以直接读取相应的物理块号,如果每找到再访问页表,得到物理地址并访问,同时把该页表中的该映射项添加到块表中
基本分段储存管理方式
分段管理:每个段内部连续内存分配,但段与段之间是离散的,因此会用到段表,记录每段在内存中的起始地址和该段长度。
段表可以放在内存或寄存器中。
分页和分段的比较
页是信息的物理单位,是出于系统内存利用率的角度提出的离散分配机制;
段是信息的逻辑单位,每个段含有一组意义完整的信息,是出于用户角度提出的内存管理机制
页的大小是固定的,由系统决定;
段的大小是不确定的,由用户决定
页面置换算法
为什么:
地址映射的过程中,如果页面中发现要访问的页面不在内存中,会产生缺页中断。此时操作系统必须在内存里选择一个页面把他移出内存,为即将调入的页面让出空间。选择淘汰哪一页的规则就是页面置换算法
分类:
:将当前页面中在未来最长时间内不会被访问的页置换出去
:淘汰最早调入的页面
每个页面有一个t来记录上次页面被访问直到现在,每次置换时置换t值最大的页面(用寄存器或栈实现)
(也被称为最近未使用算法NRU):页面设置访问为,将页面链接为一个环形列表,页面被访问的时候访问位设为1。页面置换的时候,如果当前指针的访问位为0,置换,否则将这个值置为0,循环直到遇到访问位为0的页面。
:在clock算法的基础上添加一个修改位,优先替换访问位和修改位都是0的页面,其次替换访问位为0修改位为1的页面。
:设置寄存器记录页面被访问次数,每次置换当前访问次数最少的
用户态 内核态
内核态:cpu可以访问内存的所有数据,包括外围设备,例如硬盘,网卡,cpu也可以将自己从一个程序切换到另一个程序。
用户态:只能受限的访问内存,且不允许访问外围设备,占用cpu的能力被剥夺,cpu资源可以被其他程序获取。
最大的区别就是权限不同,在运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。
为什么要有这两态:
需要限制不同的程序之间的访问能力,防止他们获取别的程序的内存数据,或者获取外围设备的数据,并发送到网络,CPU划分出 -- 用户态和内核态。
什么时候转换
:
用户进程主动发起的。用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如fork()就是执行一个创建新进程的系统调用
用户程序使用系统调用,系统调用会转换为内核态并调用操作系统
:
会从当前运行进程切换到处理次此异常的内核相关程序中
:
所有程序都运行在用户态,但在从硬盘读取数据、或从键盘输入时,这些事情只有操作系统能做,程序需要向操作系统请求以程序的名义来执行这些操作。这个时候用户态程序切换到内核态。
用户接口程序(GUI或shell)
GUI,Graphical User Interface,图形用户界面,带有图形界面的操作系统;基于文本、命令行的叫shell
处于用户态中,位于用户态的最底层,允许用户运行其他程序
(而操作系统运行在内核态中
Linux
Linux常用命令
| 系统管理命令 |
::su |
切换账户 |
| Ifconfig |
查看IP地址 |
|
| Ping |
检查网络是否连接 |
|
| Kill |
杀死进程 |
|
| Kill -9 |
强制杀死 |
|
| 系统资源查询命令 |
ps |
查看进程 |
| Ps -ef |
查看所有的进程 |
|
| Netstat |
查看网络状况 |
|
| Netstat -apn |
查看所有的端口 |
|
| df |
显示磁盘空间使用情况 |
|
| top |
查看进程资源占用 |
|
| 管道命令(同时执行) |
Ps -ef | grep |
查看所有进程,通过管道找到相应的进程包名 |
| Chmod |
赋权命令 |
|
| 目录操作命令 |
cd |
进入目录里面 |
| cd / |
根目录 |
|
| pwd |
当前目录 |
|
| mkdir |
创建目录 |
|
| rmdir |
删除目录 |
|
| ls |
查看现有的目录 |
|
| 文件编辑就命令 |
vi + 文件 |
编辑文件 |
| Cat a.txt |
查看文件,显示内容 |
|
| rm -rf |
强制删除 |
|
| find / -name .txt |
在根目录下面查找txt文件 |
|
| cp -ai a.txt test |
复制a.txt到test目录下 |
|
| tail -f pin.log |
显示pin.log文件末尾内容 |
|
| Find |
查找 |
|
| grep |
文本搜索 |
|
| touch |
如果没有就创建,有就不理它 |
|
| 文件解压压缩命令 |
tar -czvf test.tar.gz.test |
压缩 将文件压缩成.test.tar.gz |
| tar -xzvf te |