网络并发编程03--进程
1. UDP代码编写(了解)
# 服务端
import socket
udpsk = socket.socket(type=socket.SOCK_DGRAM)
udpsk.bind(('127.0.0.1',9999))
msg, addr = udpsk.recvfrom(1024)
print(msg)
udpsk.sendto(b'xxxx', addr)
udpsk.close()
# 客户端
import socket
ip_port = ('127.0.0.1',9999)
udpsk = socket.socket(type=socket.SOCK_DGRAM)
udpsk.sendto(b'hello', ip_port)
back_msg, addr = udpsk.recvfrom(1024)
print(back_msg.decode('utf8'),addr)
"""
时间服务器的实现原理
1. 内部小电容供电
2. 远程时间同步
"""
# 简易qq程序
https://www.cnblogs.com/Dominic-Ji/articles/10929376.html#_label6
2. 操作系统的发展史
学习并发编程,其实就是在学习操作系统的发展史,或者是操作系统的底层逻辑。
1. 穿孔卡片时代
cpu等待手工操作,利用不充分
cpu的利用率极低
# 可以先自己想下,如何改善该缺点
2. 联机批处理系统
将多个程序员的程序一次性录入磁带中,
之后交由输入机,输入并由cpu执行
3. 脱机批处理系统
现代计算机的雏形
远程输入,高速磁带,主机(cpu)
3. 多道技术
# 前提,针对单核cpu的情况
# 同一时间计算机只能做一件事情
三个任务a,b,c
输入a->执行a->输出a->输入b->执行b->输出b->输入c->执行c->输出c
# 单道技术(串行)
# ****************多道技术******************
切换 + 保存状态
"""
cpu工作机制(单核)
1.当某个程序进入IO状态的时候,操作系统会自动剥夺该程序的cpu执行权限。
2.当某个程序长时间占用cpu的时候,操作系统也会剥夺该程序的cpu执行权限。
"""
##################
"并行 与 并发"
# 并行
多个程序同时执行
# 并发
多程序只要看起来像同时运行即可
# 问:单核cpu能否实现并行
肯定不能,但是可以实现并发
# 问:12306可以同一时间支持几个亿的用户买票,是并发还是并行
肯定是并发(高并发)
星轨:微博可以支持多少个明星出轨搜索量
20.cnblogs.com/blog/2607829/202201/2607829-20220113155222638-539086168.png)
4. 进程理论
把握打断文字的核心
# 进程 与 程序的区别
程序:一堆代码(死的)
进程:正在运行的程序(活的)
进程的表现形式:
可以看成是内存里的一块独立资源(空间)
# 单核情况下的进程调度
进程调度算法演变
1. FCFS 先来先服务
# 对短作业不友好。。
2. 短作业优先调度算法
# 对长作业不友好
3. 时间片轮转法 + 多级反馈队列
# 也是目前计算机中正在使用的
先分配给新的多个进程相同的时间片
之后根据进程消耗的时间片多少,来分类别
# 面试问的话,可以画图解释,不要用纯文字。
# **************进程三状态图**************
就绪态,运行态,阻塞态
# 进程要想进入运行态,必须先经过就绪态
# **************同步 与 异步***************
"用于描述任务的提交方式"
同步:提交完任务之后原地等待任务的返回结果,期间不做任何事
异步:提交完任务之后不原地等待任务的返回结果,直接去做其他事,结果由反馈机制自动提醒
# **************阻塞 与 非阻塞****************
"用于描述任务的执行状态"
阻塞:阻塞态
非阻塞: 就绪态,运行态
# 以上两种状态以后都是连在一起的
极致状态是异步非阻塞
大部分程序是不需要长时间占用cpu的
游戏服务器是需要一直占用cpu的
# 同步阻塞
# 异步阻塞
# 同步非阻塞
# 异步非阻塞
5. 创建进程
# 代码层面创建进程方式
"创建进程第一种方式"
# 高端模块,面试可以讲,聊
from multiprocessing import Process
import time
import os
def test(name):
print(os.getpid()) # 获取进程号
print(os.getppid()) # 获取父进程id
print('%s is running...' % name)
time.sleep(3)
print('%s is over...' % name)
"""
在Windows种开设进程类似于导入模块
从上往下,再次执行代码
一定需要在__main__判断语句内执行开设进程的代码
在Linux中直接将代码完整的复制一份执行
不需要在__main__判断语句执行
"""
if __name__ == '__main__':
# 生成一个进程对象
p = Process(target=test, args=('jack',))
p.start() # 告诉操作系统开设一个新的进程(异步提交)
print(os.getpid())
print('主进程')
"第二种方式,用类开设进程"
# 使用频率较低
class MyProcess(Process):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print(os.getpid())
print(os.getppid())
print('%s is running...' % self.name)
time.sleep(3)
print('%s is over...' % self.name)
if __name__ == '__main__':
p = MyProcess(target=run)
p.start()
print('主')
6. 进程的join方法
from multiprocessing import Process
import time
def test(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name)
if __name__ == '__main__':
"""
p1 = Process(target=test, args=('jason',))
p2 = Process(target=test, args=('jack',))
p3 = Process(target=test, args=('joshua',))
p1.start() # 只负责通知系统开进程
p2.start()
p3.start()
"""
p_list = []
start_time = time.time()
for i in range(1,4):
p = Process(target=test, args=(i,))
p.start()
p_list.append(p)
# p.join() # 此时是串行 9s+
for p in p_list():
p.join() # 3s+
print(time.time() - start_time)
# 等待子进程代码运行完毕之后再执行主进程代码
print('主进程')
7. 进程之间默认无法交互
# 进程间数据是相互隔离的
from multiprocessing import Process
money = 100
def test():
global money
money = 999
if __name__ == '__main__':
p = Process(target=test)
p.start()
p.join()
print(money) # 100
"IPC机制"
8. 进程对象其他的属性和方法
cls
clear screen
windows 清屏
"""
1. current_process查看进程号
2. os.getpid() 查看进程号
os.getppid() 查看父进程id
3.p.terminate() 杀死子进程
4.p.is_alive() 判断当前进程是否存活
3,4难看出结果,因为系统反应需要时间
p.name 查看进程名称
"""