Python Day 32 进程和程序的区别、阻塞 非阻塞 并行 并发、进程的三种状态、进程的建立和销毁、python中两种方式实现多进程、进程间内存相互隔离、join函数孤儿进程与僵尸进程

  ##内容回顾python

# UDP协议  

​    用户数据报协议,是OSI模型中属于传输层的协议 

​    提供,不可靠的,不要求顺序的,数据量小的,速度快的传输服务 

​    不可靠:

​        发送完成后不须要确认信息 而且当即删除缓存中的数据 

​    不要求顺序:

​        当一个数据较大时 会分为多个数据报来传输,对方没法获知数据的顺序,以及是否完整

​    数据量较小的:

​        数据越大丢包的可能性越高 ,建议的数据量不要超过1472

​    速度快:

​        相对于TCP而言快不少 不须要确认信息 ,也不须要创建连接 

# 通信流程

​    若是TCP比喻为手机打电话的过程 那么UDP能够看作是对讲机   

​    1.买机器    建立UDP的socket 

​    2.固定频道    bind一个ip和端口

​    3.收发数据      recvfrom   sendto 

​    

​    接收

​    1.买机器    建立UDP的socket 

​    2.收发数据      recvfrom   sendto 

​        注意 不能先收    要收数据 必须明确端口号  没有端口号是不可能使用网络服务的 



​    

###TCP  与 UDP 的其余区别

1.没有链接  

2.不会粘包     每次发送都是一个独立的数据包    



TCP 对数据完整性要求较高 : 在线支付  ,文字信息 

 UDP: 对数据不要求完整性 可是要快 :  视频 语音 游戏  

# DNS 

域名解析服务器  

域名 就是一串有规律的字符串  ,用于绑定IP,目的是为了方便记忆 

域名解析服务器    就是帮你将域名转换为ip地址  

本质就是一个数据库  里面存的就是域名和ip对应关系   

一台机器性能有限

分为 

​    根域名服务器        只存储定义域名服务器的信息  

​    顶级域名服务器 只存储二级域名服务器的信息  

​    二级域名服务器    二级存三级 

​    三级域名   三级能够存四级  一般直接存储具体的ip信息  

​    .....................

​    本地DNS  用于加速解析    



###本身搭建DNS 的做用
1.CDN     内容分发网络       就是在你的周围创建更多镜像服务    

​    2.集群   

# 操做系统

也是一个软件, 

​    受保护的不能随意修改  

​    代码量巨大  内核在500万以上 

​    长寿 ,一旦完成通常不改 

​    linux是脱袜子  将(shell 保留解释权!)  移植到minux上 结合产生的 

###操做系统的做用:

1.将复杂丑陋的硬件细节隐藏起来,提供了简单的调用接口 

2.将应用程序对于硬件的竞争变的有序  



###操做系统发展史  
1.第一带计算机   真空管和穿孔卡片  没有进程 没有操做系统   

​    2.第二代计算机  7094 1401    晶体管  批处理系统 

​        输入输出  以及计算设备 不能互联  须要人参与    一批一批的处理   开发效率慢  而且串行执行

​    3.第三代计算机    集成电路 与多道技术 

​        多终端联机  spooling      同一台机器既能进行科学计算  又能作字符处理       通用计算机

​        多道技术   解决串行致使的效率低下问题

​        多用户终端    能够同时为多个用户提供服务  每一个用户觉得本身独享一台计算机   

​    4.第四代   我的电脑

​        大规模使用了集成电路,大多都提供了GUI界面  

# 多道技术   

​    产生背景 ,全部程序串行 致使资源浪费   

​    目的是让多个程序能够并发执行  , 同时处理多个任务   

## 关键技术

### 空间复用

指的是 同一时间 内存中加载多个不一样程序数据,

每一个进程间内存区域相互隔离,物理层面的隔离  

### 时间复用       切换 + 保存

    # 切换条件:

    1.一个进程执行过程当中遇到了IO操做  切换到其余进程

    2.运行时间过长,会被操做系统强行剥夺执行权力   

单纯的切换不够,必须在切换前保存当前的状态,以便于恢复执行  



# 进程

一个正在被运行的程序就称之为进程,是程序具体执行过程,一种抽象概念

进程来自于操做系统  

  ##多进程linux

# 进程和程序的区别  
“”“

程序就是一堆计算机能够识别文件,程序在没有被运行就是躺在硬盘上的一堆二进制

运行程序时,要从硬盘读取数据到内存中,CPU从内存读取指令并执行 ,

一旦运行就产生了进程    

一个程序能够屡次执行 产生多个进程,可是进程之间相互独立

当咱们右键运行了一个py文件时 ,其实启动的是python解释器,你的py文件实际上是看成参数传给了解释器   

”“”

# 阻塞  非阻塞   并行  并发   (重点)
“”“
#一、阻塞与非阻塞指的是程序的两种运行状态
# 阻塞:遇到IO就发生阻塞,程序一旦遇到阻塞操做就会停在原地,而且马上释放CPU资源
  本地IO input      print     sleep    read  write      

​    网络IO recv  send

# 非阻塞(就绪态或运行态):没有遇到IO操做,或者经过某种手段让程序即使是遇到IO操做也不会停在原地,执行其余操做,力求尽量多
并发: 多个任务看起来同时在处理 ,本质上是切换执行 速度很是快 并行: 多个任务真正的同时执行 必须具有多核CPU 才可能并行 并发 并行 说的是 任务的处理方式 ”“”

  ##进程的三种状态nginx

#就绪态,运行态,和阻塞态

多道技术会在进程执行时间过长或遇到IO时自动切换其余进程,意味着IO操做与进程被剥夺CPU执行权都会形成进程没法继续执行

 

  ##程序员的永恒话题程序员

提升效率

根本方法就是让程序尽量处于运行状态

减小IO  尽量多占用CPU时间     

缓冲区就是用于减小IO操做的

  ##进程的建立和销毁(了解)web

### 进程的建立

但凡是硬件,都须要有操做系统去管理,只要有操做系统,就有进程的概念,就须要有建立进程的方式,一些操做系统只为一个应用程序设计,好比微波炉中的控制器,一旦启动微波炉,进程就已经存在。

  而对于通用系统(跑不少应用程序),须要有系统运行过程当中建立或撤销进程的能力,主要分为4中形式建立新的进程

1. 系统初始化(查看进程linux中用ps命令,windows中用任务管理器,前台进程负责与用户交互,后台运行的进程与用户无关,运行在后台而且只在须要时才唤醒的进程,称为守护进程,如电子邮件、web页面、新闻、打印)
2. 一个进程在运行过程当中开启了子进程(如nginx开启多进程,os.fork,subprocess.Popen等)
3. 用户的交互式请求,而建立一个新进程(如用户双击暴风影音)
4. 一个批处理做业的初始化(只在大型机的批处理系统中应用)

### 进程的销毁

1. 正常退出(自愿,如用户点击交互式页面的叉号,或程序执行完毕调用发起系统调用正常退出,在linux中用exit,在windows中用ExitProcess)
2. 出错退出(自愿,python a.py中a.py不存在)
3. 严重错误(非自愿,执行非法指令,如引用不存在的内存,1/0等,能够捕捉异常,try...except...)
4. 被其余进程杀死(非自愿,如kill -9### 进程的层次结构

不管UNIX仍是windows,进程只有一个父进程,不一样的是:

1. 在UNIX中全部的进程,都是以init进程为根,组成树形结构。父子进程共同组成一个进程组,这样,当从键盘发出一个信号时,该信号被送给当前与键盘相关的进程组中的全部成员。
2. 在windows中,没有进程层次的概念,全部的进程都是地位相同的,惟一相似于进程层次的暗示,是在建立进程时,父进程获得一个特别的令牌(**称为句柄**),该句柄能够用来控制子进程,可是父进程有权把该句柄传给其余子进程,这样就没有层次了。

  ##python中实现多进程shell

“”“
在一个应用程序中可能会有多个任务须要并发执行,可是对于操做系统而言,一个进程就是一个任务,CPU会从上往下依次执行代码,当代码中遇到IO操做时,操做系统就会剥夺CPU执行权给其余应用程序,这样对于当前应用程序而言,效率就下降了,如何使得程序既能完成任务又不下降效率呢?答案就是让把当前程序中的耗时操做交給子进程来完成,如此当前应用程序能够继续执行其余任务!
”“”

#python中开启子进程的两种方式

#方式一:直接实例化Process  ,将要执行任务用target传入
from multiprocessing import Process
import os
import time
# 为何要子进程   当出现一些耗时较长的操做时 会致使程序进入阻塞状态  二没法执行其余代码
# 这时候就能够开启子进程把任务交给他

def task(name):
    print(" name %s 子进程run!" % name)
    # print("son is :%s" % os.getpid())
    # print("father is :%s" % os.getppid())
    time.sleep(3)
    print("子进程 over!")


if __name__ == '__main__':
    print("father :%s" % os.getpid())
    p = Process(target=task,args=("rose",))
    p.start() # 开启子进程   本质是向操做系统发送请求 让它启动进程    一般不可能当即开启
    print("任务结束!")

"""
windows  和  linux 开启进程的方式不一样 
首先相同之处都是 须要将数据copy一份给子进程   这样子进程才知道要干什么  
linux 会将父进程的全部数据 彻底copy    
windows  会copy 一部分数据   同时会导入py文件来执行   这样一来递归开进程    
linux 拿到父进程知道代码位置 继续执行   
建议都加上判断  能够保证两个平台都能用  

记住:
开启进程的代码 都把它放到  if __name__ == "__main__": 中便可


"""


#方式二:继承Process类 ,覆盖run方法  将任务放入run方法中 (重点掌握) 
import os
from multiprocessing import  Process
class MyProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name = name
    # 继承Procee覆盖run方法将要执行任务发到run中
    def run(self):
        print(self.name)
        print("子进程 %s running!" % os.getpid())
        print("子进程 %s over!" % os.getpid())

if __name__ == '__main__':
    # 建立时 不用再指定target参数了
    p = MyProcess("rose")
    p.start()
    print("父进程over!")

  ##进程间内存相互隔离数据库

from multiprocessing import Process
import time
name = "青椒"
def task():
    global name
    name = "rose"
    print("改完了!")
    print("子进程的%s" % name)


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    time.sleep(2)
    print(name)

  ##join函数windows

“”“
调用start函数后的操做就由操做系统来玩了,至于什么时候开启进程,进程什么时候执行,什么时候结束都与应用程序无关,因此当前进程会继续往下执行,join函数就能够是父进程等待子进程结束后继续执行,即用于提升子进程优先级 ,使得父进程等待子进程结束  
”“”

#案例
"""
    当你开启了一个子进程 而且给他一个任务  若是你但愿知道这个任务何时完成 那就须要等待

"""
import time,os
from multiprocessing import Process
# def task(i):
#     # print(" %s 买烟去了" % i)
#     time.sleep(3)
#     print("%s 买完了!" % i)
#
# if __name__ == '__main__':
#     # p = Process(target=task)
#     # p.start()
#     # # time.sleep(5)
#     # p.join() # 等待子进程执行完毕   将子进程的优先级提升
#     #
#
#
#
#     for i in range(10):
#         p = Process(target=task,args=(i,))
#         p.start()  # 进程启动顺序  与start无关   主要看操做系统先切换谁
#         # p.join()
#
#     p.join()  # 最后一个
#
#
#     print("over!")


def task(i):
    # print(" %s 买烟去了" % i)
    time.sleep(i)
    print("%s 买完了!" % i)

if __name__ == '__main__':
    strat_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()

    p3.join() #3
    p2.join()
    p1.join()


    end_time = time.time()
    print(end_time - strat_time)
    print("over!")


#案例2
from multiprocessing import Process
import time,random
x=1000
def task(n):
    print('%s is runing' %n)
    time.sleep(n)
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()
    p3.join() #3s
    p1.join()
    p2.join()
    print('主',(time.time() - start_time))
    start_time=time.time()
    p_l=[]
    for i in range(1,4):
        p=Process(target=task,args=(i,))
        p_l.append(p)
        p.start()
    for p in p_l:
        p.join()
   
    print('主',(time.time() - start_time))

  ##Process对象经常使用属性浏览器

from multiprocessing import  Process
import time,os
def task():
    print("121121")
    # time.sleep(10)
    # print("over")
    # print(os.getppid())
    exit(1000)

if __name__ == '__main__':
    p = Process(target=task,name="rose")
    p.start() # 懒加载优化机制  若是没有调用start 那么该对象将不会被建立
    time.sleep(1)
    # p.join() # 等待子进程结束
    # p.terminate()  # 终止进程
    # print(p.name)  # 进程的名称
    # print(p.is_alive()) #是否存活
    # p.terminate() # 与start同样 都是给操做系统发送指令 因此会有延迟
    # print(p.is_alive())
    # print(p.pid)
    # print(p.exitcode) # 获取退出码

  ##孤儿进程与僵尸进程缓存

## 孤儿进程

指的是,父进程先结束 ,而子进程还在运行着, 

孤儿进程无害,有 其存在的必要性 

例如:qq开启了浏览器,qq先退出了  浏览器应该继续运行  

孤儿进程会被操做系统接管    



## 僵尸进程

值得是,子进程已经结束了,可是操做系统会保存一些进程信息,如PID,运行时间等,此时这个进程就称之为僵尸进程  

僵尸进程若是太多将会占用大量的资源,形成系统没法开启新新进程 

linux 中有一个wai/waitpid 用于父进程回收子进程资源

python会自动回收僵尸进程  
相关文章
相关标签/搜索