zoukankan      html  css  js  c++  java
  • 进程.

    操作系统的背景知识:
    操作系统的作用:
    1.封装了丑陋复杂的接口,提供了良好的抽象接口
    2.管理.调度程序,并将多个进程或者程序对硬件资源的竞态请求变的有序化
    多道技术:
    产生背景:针对于单核,实现并发
    空间上的复用:内存中存在多道程序
    时间上的复用:
    1.遇到io口就切换
    2.一个进程长时间被CPU处理的时,操作系统会强硬的将cpu调出去处理下一个进程
    进程:是计算机中关于数据集合上的一次运行活动,是系统资源分配和调度的基本单位
    是操作系统结构的基础
    也是正在运行程序的实例

    进程的调度: 先来先服务调度算法,
    短作业优先调度算法,
    时间片轮转法,
    多级反馈队列

    进程的并行并发:
    并行:指的是两个或者多个cpu同时分别执行两个或者多个进程
    并发:指的一个cpu对多个进程轮流交替使用
    区别:虽然给人的感觉是同时执行的,但是并发是在多个进程之间交替执行

    进程的同步异步:
    同步:一个任务的完成需要依赖另一个任务的完成
    异步:任务的完成不需要被等待的任务完成

    进程的三态状态:就绪,阻塞,运行

    进程的创建和结束:
    创建:UNIX中调用的是fork
    Windows是CreateProcess
    创建子进程:UNIX和Windows
    相同点:都会将父进程复制一份,存放到另一个地址空间,也就是子进程,但是两个进程之间在地址空间的操作没有关系
    不同点:NUIX中子进程的地址空间是父进程的一个副本,存在只读的共享内存区的
    windows的子进程空间跟父进程的进程空间多一些东西

    在python程序中的进程操作:
    multiprocess模块:是python中的一个操作,管理进程的包.包中几乎包含了跟进程有关的所有子模块
    大致分为四类:
    创建进程部分
    进程同步部分
    进程池部分
    进程之间数据共享


    1.创建进程部分(multiprocess.process模块)
      process模块是一个创建进程的模块,借助这个模块就可以完成进程的创建
      创建进程的时候windows必须要用if __name__=__main__():
      在进程中,main之上的代码都是子进程的代码,主进程只有在子进程结束后才算真正意义上结束
    import time
    from multiprocessing import Process #导入Process模块
    def func(name):
        time.sleep(0.1)
        print('hello',name)
        print('我是子进程')
    if __name__ == '__main__':
        p = Process(target=func,args=('智障',))
        #由Process实例化出的一个对象,表示一个子进程中的任务(尚未启动)
        p.start()#启动进程
        time.sleep(1)
        print('我是主进程')
      通过类的方式创建一个进程:
    from multiprocessing import Process
    class MyProcess(Process):
        def __init__(self,name):
            super().__init__()
            self.name = name
        def run(self):
            print('%s正在吃饭'%self.name)
    if __name__ == '__main__':
        p = MyProcess('alex')
        p.start()
        p.join()
    
    
      p.jion()的用法:是主进程等待p进程(子进程)的结束后再结束
    import time
    from multiprocessing import Process
    def func():
        print('子进程开始')
        time.sleep(1)
        print('子进程结束')
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()
        p.join()
        print('主进程')
    # 结果:
        子进程开始
        子进程结束
        主进程
      多个进程运行时,join的用法: 多个进程执行的时候,join的个数和进程个数一样且必须连续放置
    from multiprocessing import Process
    def func(name):
        print('hello',name)
    if __name__ == '__main__':
        p_l = []
        for i in range(5):
            p = Process(target=func,args=('智障',))
            p.start()
            p_l.append(p)
        for p in p_l:
            p.join()
        print('主程序')

      查看进程属性:
    查看进程的id:需要调用带os模块 (os.getpid , os.getppid)
    import os
    from multiprocessing import Process
    def func():
        print('子进程',os.getpid())
        # print('主进程',os.getppid())
    if __name__ == '__main__':
        print('主进程', os.getpid())
        for i in range(5):
            p = Process(target=func)
            p.start()
    在子程序中os.getpid()可以查看子进程id
    在主程序中os.getpid()可以查看本进程id

    验证进程之间的数据隔离:
    进程之间的数据是隔离的,
    from multiprocessing import Process
    n = 100
    def func():
        global n
        n = 2
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()
        print(n)




    守护进程:会随着主程序的结束而结束
      1.守护进程会在主进程代码运行结束后就终止

      2.守护进程内无法再开启子程序,否则抛出异常
    # 主进程必须在子进程结束后回收子进程的代码后才算真正的结束
    # 必须在p.start()前设置守护进程
    # 守护进程若是主进程结束后,就不会再执行
    import time
    from multiprocessing import Process
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    if __name__ == '__main__':
        p1 = Process(target=foo)
        p2 = Process(target=bar)
        p1.daemon = True
        p1.start()
        p2.start()
        time.sleep(2)
        print('主进程')
    # 结果:
    123
    456
    end123
    主进程
    end456
    进程的其他用法:
    p.teminate()关闭进程,但是不会立即关闭 ,所以is_live立刻查看的结果还可能是True
    2.进程同步(multiprocess.Lock):为了维护数据的安全,牺牲了效率利用互斥锁
    from multiprocessing import Process,Lock
    import time
    import os
    def func(name,lock):
        lock.acquire()
        print('%s: %s 正在跑'%(name,os.getpid()))
        time.sleep(1)
        print('%s: %s已经跑完了'%(name,os.getpid()))
        lock.release()
    if __name__ == '__main__':
        lock = Lock()
        p1 = Process(target=func,args=('小明',lock))
        p2 = Process(target=func,args=('小红',lock))
        p1.start()
        p2.start()
    加锁可以保证多个进程修改同一个数据的时候,只能在同一时间一个程序进行修改,就是串行修改

    加锁的方式使代码的效率变低,还要自己进行加锁处理,所以大部分都是采用管道和队列的方式
    (基于消息的ipc机制,进程之间的通信)



    3.进程间的通信 队列 multiprocess.Queue:
    import  time
    from multiprocessing import Process,Queue
    def func(q):
        q.put([time.asctime(),'form alex','hello'])
    if __name__ == '__main__':
        q = Queue()#参数为显示队列的里的元素个数
        p =Process(target=func,args=(q,))
        p.start()
        print(q.get())
        p.join()
    JionableQueue()跟Queue的方法一样,但是多了几个
    q.task_done()#使用此方法发出信号,表示q.get()返回的项目已经被处理;
    如果调用的此方法次数大于从队列中删除的项目数量,将引发ValueError异常
    q.join()生产者将使用此方法进行阻塞
    # 生产者和消费者模型(欠着)
    3.进程之间的数据共享(Manager模块)
      Manager提供可共享的数据类型但是不加锁操作的共享数据肯定会出错
    from multiprocessing import Manager,Process,Lock
    def work(dic,lock):
        with lock:#必须加锁才能保证数据的安全
            dic['count'] -=1
    if __name__ == '__main__':
        lock = Lock()
        m = Manager()
        dic = m.dict({'count':100})#设置可共享数据
        p_L= []
        for i in range(100):
            p = Process(target=work,args=(dic,lock))
            p_L.append(p)
            p.start()
        for p in  p_L:
            p.join()
        print(dic)

    4.进程池(Pool):方便了系统调用,节省了时间,实现并发效果

    from multiprocessing import Process,Pool
    import time
    def func(i):
        i * i
        return 'i'*i
    if __name__ == '__main__':
        start = time.time()
        p = Pool(4)#设置要开启进程数 默认为cpu的个数
        for i in range(50):
            p.apply_async(func,(i,))#异步提交 apply提交 async异步
        p.close()#关闭进程池 不允许再继续向这个池子添加任务了
        p.join()#阻塞,直到已经被提交的进程池中的任务全部结束
        print(time.time()-start)

    返回值的获得

    from multiprocessing import Pool
    def func(i):
        i * i
        return 'i'*i
    if __name__ == '__main__':
        p = Pool()
        ret_l = []
        for i in range(20):
            ret = p.apply_async(func,(i,))
            ret_l.append(ret)
            print(ret.get())
        # for ret in ret_l:
            print(ret.get())#获取返回值的时候必须是ret.get()
    将返回值加入列表中循环打印

    同步调用:

    import os
    import time
    import random
    from multiprocessing import Pool
    def func(i):
        time.sleep(random.random())
        print(i,os.getpid())
    if __name__ == '__main__':
        p = Pool()
        for i in range(20):
            ret = p.apply(func,(i,))
    同步调用的时候 第一个进程执行完结束后才能执行,遇到io阻塞后,后面的程序都会被阻塞

    Pool使用map的方法:
    import time
    from multiprocessing import Pool
    def func(i):
        return 'i' * i
    if __name__ == '__main__':
        p = Pool()
        ret_l = p.map(func,range(20))#第二个为可迭代的对象 得到结果是一个列表
        #map就是简单的appli_async的方式,并内置了close和join的功能
        for ret in ret_l:
            print(ret)
    回调函数callback
    
    
  • 相关阅读:
    蓝牙的发展史及版本演进
    linux下tar.bz2文件的 解压缩方法
    一个简单的C语言题背后的故事
    thinkpad的E480安装ubuntu后wifi无法使用问题解决
    Linux 上的常用文件传输方式介绍与比较
    一个linux内核编译时遇到的perl语法导致的编译问题解决
    自省是最好的导师
    ....................................thinkpad E480 用户初体验..............................
    使用diskpart命令格式化U盘
    了解甚少的GNU C的__attribute__ 机制
  • 原文地址:https://www.cnblogs.com/shicongcong0910/p/10462331.html
Copyright © 2011-2022 走看看