Day9 进程理论 开启进程的两种方式 多进程实现并发套接字 join方法 Process ...

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:31   1794   0

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


#一 操作系统的作用:
    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也执行了,但是随即被终止

转载于:https://www.cnblogs.com/sexiaoshuai/p/7447628.html

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP