复习:
1.UDP协议
2.通讯流程
3.DNS---域名解析服务器
4.操作系统
5.多道技术
6.进程.
详解:
1.UDP协议----用户数据报协议,是OSI模型中属于传输层的协议
提供:不可靠的, 不要求顺序的, 数据量小的, 速度快的 传输服务
不可靠:------发送完成后不需要确认信息 并且立即删除缓存中的数据
不要求顺序:-------当一个数据较大时 会分为多个数据报来传输,对方无法获知数据的顺序,以及是否完整
数据量较小的:--------数据越大丢包的可能性越高 ,建议的数据量不要超过1472
速度快:-----相对于TCP而言快很多 不需要确认信息 ,也不需要建立链接
2.通讯流程-----UDP协议
2.1 如果TCP比喻为手机打电话的过程 那么UDP可以看做是对讲机
服务器
0 1.买机器 创建UDP的socket
2.固定频道bind一个ip和端口
3.收发数据 recvfrom sendto
接收
1.买机器 创建UDP的socket
2.收发数据 recvfrom sendto
注意 不能先收 要收数据 必须明确端口号 没有端口号是不可能使用网络服务的
2.2.TCP 与 UDP 的其他区别
1.没有连接
2.不会粘包 每次发送都是一个独立的数据包
TCP 对数据完整性要求较高 : 在线支付 ,文字信息
UDP: 对数据不要求完整性 但是要快 : 视频 语音 游戏
、
3.DNS---域名解析服务器
域名解析服务器
域名 就是一串有规律的字符串 ,用于绑定IP,目的是为了方便记忆
域名解析服务器 就是帮你将域名转换为ip地址
本质就是一个数据库 里面存的就是域名和ip对应关系
一台机器性能有限
分为
根域名服务器 只存储定义域名服务器的信息
顶级域名服务器 只存储二级域名服务器的信息
二级域名服务器 二级存三级
三级域名 三级可以存四级 通常直接存储具体的ip信息
.....................
本地DNS 用于加速解析
自己搭建DNS 的作用
1.CDN(CDN加速) 即: 内容分发网络 就是在你的周围建立更多镜像服务 (方便就近访问)
2.集群 :在使用dns时,为了缓解服务器的压力,会使用多个辅助dns服务器来分担主dns的工作,这些dns就叫做dns集群
4.操作系统---------也是一个软件,
4.1特点:
受保护的不能随意修改
代码量巨大 内核在500万以上
长寿 ,一旦完成一般不改
linux是脱袜子 将(shell 保留解释权!) 移植到minux上 结合产生的
4.2操作系统的作用:
1.将复杂丑陋的硬件细节隐藏起来,提供了简单的调用接口
2.将应用程序对于硬件的竞争变的有序
4.3操作系统发展史
1.第一带计算机 真空管和穿孔卡片 没有进程 没有操作系统
2.第二代计算机 7094 1401 晶体管 批处理系统
输入输出 以及计算设备 不能互联 需要人参与 一批一批的处理 开发效率慢 并且串行执行
3.第三代计算机 集成电路 与多道技术
多终端联机 spooling 同一台机器既能进行科学计算 又能做字符处理 通用计算机
多道技术 解决串行导致的效率低下问题
多用户终端 可以同时为多个用户提供服务 每个用户以为自己独享一台计算机
4.第四代 个人电脑
大规模使用了集成电路,大多都提供了GUI界面
5.多道技术
5.1产生背景 : 所有程序串行 导致资源浪费
目的:是让多个程序可以并发执行 , 同时处理多个任务
5.3关键技术
1.空间复用
指的是 同一时间 内存中加载多个不同程序数据,
每个进程间内存区域相互隔离,物理层面的隔离
切换 + 保存
切换条件:
1.一个进程执行过程中遇到了IO操作 切换到其他进程
2.运行时间过长,会被操作系统强行剥夺执行权力
注:单纯的切换不够,必须在切换前保存当前的状态,以便于恢复执行
6.进程.:
一个正在被运行的程序就称之为进程,是程序具体执行过程,一种抽象概念
进程来自于操作系统
今日内容:
多进程:
1.进程与程序的区别
2.阻塞 非阻塞 并行 并发(重点)
3.进程三种状态以及切换
4.程序员永恒的话题
5.进程的创建以及销毁
6.进程的两种使用方式(重点)
7.join函数(重点)
8.process常用属性
9僵尸与孤儿进程(了解)
详解:
多进程:在一个操作系统中通常都会应用多个应用程序,即多个进程,简称多进程
1.进程与程序的区别
进程:一个正在被运行的程序就称之为进程,是程序具体执行过程中的一种抽象概念
程序:就是一堆计算机可以识别的文件,程序在没有被运行就是躺在硬盘上的一堆二进制
运行程序时,要从硬盘读取数据到内存 ,CPU从内存读取指令并执行
一旦运行就产生了进程
一个程序可以多次执行,产生多个进程,但是进程之间是相互独立的,当我们右键运行了一个Python文件其实就是当做参数传给解释器
2.阻塞 非阻塞 并行 并发(重点)
阻塞:程序遇到 io 操作 时就进入 阻塞状态
本地:IO input print sleep read write
网络:IO recv send
非阻塞:程序正常运行中 没有任何 IO操作 就处于非阻塞状态
阻塞 非阻塞 说的是程序的运行状态
并发:多个任务看起来在同时处理,本质上是切换执行 速度非常快
并行:多个任务真正的同时执行 必须具备多核CPU 才可能并行
并发 并行 说的是任务的处理方式
3.进程的三种状态以及切换
三种状态:
就绪态 运行态 阻塞态
切换关系
3.1就绪===>>>>>(进程调度)>>>>=====执行===>>>>(I/O请求)>>>>=====阻塞===>>>>(IO完成)>>>>=====就绪
3.2执行===>>>>>(时间片用完)>>>>=====就绪
4.程序员永恒的话题
提高效率
根本方法就是让程序尽可能处于运行状态
减少IO 尽可能多占用CPU时间
缓冲区就是用于减少IO操作的
5.进程的创建以及销毁
5.1进程的创建
5.1.1原因:
凡是硬件,都需要有操作系统去管理,只要有操作系统,就有进程的概念,就需要有创建进程的方式,
两种不同类型操作系统案例:
1.一些操作系统只为一个应用程序设计,比如微波炉中的控制器,一旦启动微波炉,进程就已经存在。
2.而对于通用系统(跑很多应用程序),需要有系统运行过程中创建或撤销进程的能力,
主要分为4中形式创建新的进程:
系统初始化(查看进程linux中用ps命令,windows中用任务管理器,前台进程负责与用户交互,后台运行的进程与用户无关,运行 在后台并且只在需要时才唤醒的进程,称为守护进程,如电子邮件、web页面、新闻、打印)
2.一个进程在运行过程中开启了子进程(如nginx开启多进程,os.fork,subprocess.Popen等)
3.用户的交互式请求,而创建一个新进程(如用户双击暴风影音)
4.一个批处理作业的初始化(只在大型机的批处理系统中应用)
5.1.2本质:
无论哪一种,新进程的创建都是由一个已经存在的进程执行了一个用于创建进程的系统调用而创建的:
1.在UNIX中该系统调用是:fork,fork会创建一个与父进程一模一样的副本,
二者有相同的存储映像、同样的环境字符串和同样的打开文件(在shell解释器进程中,执行一个命令就会创建一个子进程)
2.在windows中该系统调用是:CreateProcess,CreateProcess既处理进程的创建,也负责把正确的程序装入新进程。
5.1.3关于创建的子进程,UNIX和windows
1.相同的是:进程创建后,父进程和子进程有各自不同的地址空间(多道技术要求物理层面实现进程之间内存的隔离),
任何一个进程的在其地址空间中的修改都不会影响到另外一个进程。
2.不同的是:在UNIX中,子进程的初始地址空间是父进程的一个副本,提示:子进程和父进程是可以有只读的共享内存区的。
但是对于windows系统来说,会重新加载程序代码
5.2进程的销毁
- 正常退出(自愿,如用户点击交互式页面的叉号,或程序执行完毕调用发起系统调用正常退出,在linux中用exit,在windows中用ExitProcess)
- 出错退出(自愿,python a.py中a.py不存在)
- 严重错误(非自愿,执行非法指令,如引用不存在的内存,1/0等,可以捕捉异常,try...except...)
- 被其他进程杀死(非自愿,如kill -9)
6.进程的两种使用方式(重点)
案例说明:
# 为什么要子进程 当出现一些耗时较长的操作时 会导致程序进入阻塞状态 二无法执行其他代码
# 这时候就可以开启子进程把任务交给他
windows 和 linux 开启进程的方式不同
首先相同之处都是 需要将数据copy一份给子进程 这样子进程才知道要干什么
linux 会将父进程的所有数据 完全copy
windows 会copy 一部分数据 同时会导入py文件来执行 这样一来递归开进程
linux 拿到父进程知道代码位置 继续执行
建议都加上判断 可以保证两个平台都能用
记住:
开启进程的代码 都把它放到 if __name__ == "__main__": 中即可
"""
方法一:.直接实例化Process ,将要执行任务用target传入
from multiprocessing import Process
#multiprocessing多进程
import os
def task():
print("son run!")
print("son:%s"%os.getpid())
print("father:%s"%os.getppid())
print("son over!")
if __name__=="__main__":
p=Process(target=task)
print(os.getpid())
p.start()
值:
24920
son run!
son:27404
father:24920
son over!
方法二。继承Process类 ,覆盖run方法 将任务放入run方法中
import os
#继承Process类 ,覆盖run方法 将任务放入run方法中
from multiprocessing import Process
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print(self.name)
print("son:%s running!" % os.getpid())
print("son:%s over!" % os.getpid())
if __name__=="__main__":
#创建时不用在指定target
p=MyProcess("Tom")
p.start()
print("父进程over!")
注意:进程间相互间隔
from multiprocessing import Process
import time
name="laba"
def task():
global name
name="llx"
print("改完了")
print("son:%s"%name)
if __name__=="__main__":
p=Process(target=task)
p.start()
time.sleep(5)
print("father:%s" % name)
#值:
'''
改完了
son:llx
father:laba
'''
7.join函数(重点)-------------连接
Process的对象具备一个join函数
用于提高子进程优先级 ,使得父进程等待子进程结束
案例说明:
from multiprocessing import Process
def task(i):
time.sleep(i)
print("%s 买完了"%i)
if __name__=="__main__":
start_time=time.time()
p1= Process(target=task, args=(1,))
p2 = Process(target=task, args=(2,))
p3 = Process(target=task, args=(3,))
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
end_time=time.time()
print(end_time-start_time)
print("over!")
值:
1 买完了
2 买完了
3 买完了
3.132598876953125
over!
8.process常用属性
from multiprocessing import Process
def task(n):
print('%s is runing' %n)
time.sleep(n)
if __name__ == '__main__':
start_time=time.time()
p=Process(target=task,args=(1,),name='任务1')
print('主')
# p.join() # 等待子进程结束(# 提高优先级)
# p.terminate() # 终止进程
# print(p.name) # 进程的名称
# print(p.is_alive()) #是否存活
#p.start() # 启动进程
# p.terminate() # 与start一样 都是给操作系统发送指令 所以会有延迟
# print(p.pid)# 获取进程pid
# print(p.exitcode) # 获取退出码
9僵尸与孤儿进程(了解)
9.1孤儿进程
指的是,父进程先结束 ,而子进程还在运行着,
孤儿进程无害,有 其存在的必要性
例如:qq开启了浏览器,qq先退出了 浏览器应该继续运行
孤儿进程会被操作系统接管
9.2僵尸进程
值得是,子进程已经结束了,但是操作系统会保存一些进程信息,如PID,运行时间等,此时这个进程就称之为僵尸进程
僵尸进程如果太多将会占用大量的资源,造成系统无法开启新新进程
linux 中有一个wai/waitpid 用于父进程回收子进程资源
python会自动回收僵尸进程