• Day9 进程理论 开启进程的两种方式 多进程实现并发套接字 join方法 Process对象的其他属性或者方法 守护进程 操作系统介绍


    操作系统简介(转自林海峰老师博客介绍)


    #一 操作系统的作用:
        1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口
        2:管理、调度进程,并且将多个进程对硬件的竞争变得有序
    
    #二 多道技术:
        1.产生背景:针对单核,实现并发
        ps:
        现在的主机一般是多核,那么每个核都会利用多道技术
        有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个
        cpu中的任意一个,具体由操作系统调度算法决定。
        
        2.空间上的复用:如内存中同时有多道程序
        3.时间上的复用:复用一个cpu的时间片
           强调:遇到io切,占用cpu时间过长也切,核心在于切之前将进程的状态保存下来,这样
                才能保证下次切换回来时,能基于上次切走的位置继续运行
    

    进程与程序的区别:

    程序仅仅是一堆代码而已,而进程指的是程序的运行过程。

    需要强调的是,同一个程序执行两次,那也是两个进程。

    进程的创建都是操作系统完成的。


    开启进程的两种方式:

    第一种方法:

     1 from multiprocessing import Process    #引用这个函数
     2 import time
     3 def work(name):
     4     print('task <%s> is runing' %name)
     5     time.sleep(2)
     6     print('task <%s> is done' % name)
     7 
     8 if __name__ == '__main__':
     9     # Process(target=work,kwargs={'name':'egon'})    #target后边跟的是你的函数名,传值的方式有两种:一种是args(单个参数),一种是kwargs(多个参数)
    10     p1=Process(target=work,args=('egon',))
    11     p2=Process(target=work,args=('alex',))
    12     p1.start()
    13     p2.start()
    14     print('')
    15  #
      #task <egon> is runing
      #task <alex> is runing
      #task <egon> is done
      #task <alex> is done

    打印的结果如15所示:
    为什么会先打印"主"这个字段????

    是因为主程序在执行的过程中,会告诉操作系统开一个进程,但是开完进程以后,操作系统不会在这等着(相当于只是发了一个开启进程的信号),然后会继续向后边执行。

     等到所有的子进程执行完后,主进程才会执行完成。(如果在执行过程中,主进程挂掉,子进程就会成为僵尸进程)

    开启进程的方式二:

    from multiprocessing import Process
    import time
    class MyProcess(Process):     #自己定义了一个类继承一下进程的类
        def __init__(self,name):
            super().__init__()     #先重用父类的功能,然后再去定义自己的,要不然会出错。
            self.name=name
    
        def run(self):
            print('task <%s> is runing' % self.name)
            time.sleep(2)
            print('task <%s> is done' % self.name)
    
    
    
    if __name__ == '__main__':
        p=MyProcess('egon')
        p.start()
    
        print('')

    UDP并发的套接字通信:

     1 from multiprocessing import Process
     2 from socket import *
     3 s=socket(AF_INET,SOCK_STREAM)
     4 s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
     5 s.bind(('127.0.0.1',8080))
     6 s.listen(5)
     7 def talK(conn,addr):
     8     while True:       #通信循环
     9         try:
    10             data=conn.recv(1024)
    11             if not data:break
    12             conn.send(data.upper())
    13         except Exception:
    14             break
    15     conn.close()
    16 
    17 if __name__ == '__main__':
    18     while True:
    19         conn,addr=s.accept()        #链接循环
    20         p=Process(target=talK,args=(conn,addr))
    21         p.start()
    22 
    23     s.close()

    #将获取地址,和链接循环放在程序主体,通信循环定义成一个模块,这样可以实现并发。

    #客户端
    from socket import *
    c=socket(AF_INET,SOCK_STREAM)
    c.connect(('127.0.0.1',8080))
    
    while True:    #通信循环
        msg=input('>>: ').strip()
        if not msg:continue
        c.send(msg.encode('utf-8'))
        data=c.recv(1024)
        print(data.decode('utf-8'))
    
    c.close()

    客户端只是个程序,当他启动了就是一个进程。
    启动多个,就是多个进程。


    join方法(主进程等待子进程结果):

    主程序的运行过程中需要子进程的执行结果,但正常的是不等的,这时候我们需要用到join方法。

    from multiprocessing import Process
    import time
    def work(name):
        print('task <%s> is runing' %name)
        time.sleep(3)
        print('task <%s> is done' % name)
    
    if __name__ == '__main__':
        p1=Process(target=work,args=('egon',))
        p2=Process(target=work,args=('alex',))
        p3=Process(target=work,args=('yuanhao',))
    
        # p1.start()
        # p2.start()
        # p3.start()
        #
        # p1.join() #主进程等,等待p1运行结束
        # p2.join() #主进程等,等待p2运行结束
        # p3.join() #主进程等,等待p3运行结束
    
        p_l = [p1, p2, p3]
        for p in p_l:
            p.start()
    
        for p in p_l:
            p.join()
    
        print('')

    这里边所有的进程都加入了join方法,但是其实是主进程把所有的进程都打开了,所有的子进程都在并发,其实主进程等待的是运行时间最长的子进程,运行时间最长的子进程结束,主进程等待结束。

    #注意的一点:不能将这个开进程和join方法放到一个循环里边,这样的话,相当于是串行运行程序。等待时间是所有时间的总和。

    错误的用法:

     p_l = [p1, p2, p3]
        for p in p_l:
             p.start()
        #     p.join()
        # p1.start()
        # p1.join()
        # p2.start()
        # p2.join()
        # p3.start()
        # p3.join()
    

    Process对象的其他方法或属性:

    p=Process(target=work,args=("egon",),name="123")
    p1.start()
    
    #p1.terminnate() zijinchengzaikai zijincheng 
    #热别注意,容易产生僵尸进程
    
    #p1.is_alive()   判断这个进程是否是活着的
    
    #p1.name()    打印p1的进程名
    
    #p1.pid()    
    
    #print("zhu",os.getpid())  #打印进程pid
    #print("zhu",os.getppid())  #打印父进程pid

     


    守护进程:

    主进程创建守护进程,

    其一:守护进程会在主进程代码执行结束后就终止

    其二:守护进程无法在开启子进程,否则抛出异常。

    注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止。

    主进程结束后,子进程也完蛋了。

    应用场景:监控(比如说子进程监控主进程的状态,主进程一旦挂掉,子进程也要随之挂掉)

    from multiprocessing import Process
    import time
    def work(name):
        print('task <%s> is runing' %name)
        time.sleep(2)
        print('task <%s> is done' % name)
    
    if __name__ == '__main__':
        p1=Process(target=work,args=('egon',))
        p1.daemon = True
        p1.start()
    
        print('')

    小例子:

     1 #主进程代码运行完毕,守护进程就会结束
     2 from multiprocessing import Process
     3 import time
     4 def foo():
     5     print(123)
     6     time.sleep(1)
     7     print("end123")
     8 
     9 def bar():
    10     print(456)
    11     time.sleep(3)
    12     print("end456")
    13 if __name__ == '__main__':
    14 
    15     p1=Process(target=foo)
    16     p2=Process(target=bar)
    17 
    18     p1.daemon=True
    19     p1.start()
    20     p2.start()
    21     print("main-------") #打印该行则主进程代码结束,则守护进程p1应该被终止,可能会有p1任务执行的打印信息123,因为主进程打印main----时,p1也执行了,但是随即被终止
  • 相关阅读:
    简单的远程控制软件
    VS集成环境中的JavaScript脚本语法检查
    vs2022安装
    有关httpContext.Current.Session[值] 取值的问题
    【python3.7】文件操作
    148. 排序链表
    11. 盛最多水的容器
    23. 合并K个升序链表
    147. 对链表进行插入排序
    146. LRU 缓存机制
  • 原文地址:https://www.cnblogs.com/sexiaoshuai/p/7447628.html
Copyright © 2020-2023  润新知