python学习笔记 day35 操作系统 进程

1. 操作系统

操作系统是协调,管理和控制计算机软件资源和硬件资源的控制程序;

操作系统封装了对硬件的操作过程,给应用程序提供了好用的接口;

对多个作业进调度管理来分配硬件资源;

 

2. 进程

 1. 进程的概念: 正在运行的程序才可以称之为进程;

2. 操作系统和进程的关系: 操作系统调度任务,任务其实就是正在执行的进程,所以操作系统调度的其实是一个进程;

3. 为什么要引入进程:隔离资源(不同进程之间是需要隔离开的)

4. 进程是操作系统资源分配的最小单位;

5. 进程是如何被调度的呢:

   1. 先来先服务原则(FCFS)

   2. 短作业优先算法(小的进程执行时间短,优先被执行)

   3. 时间片轮流算法(多个进程轮流着来,从宏观上看好像是同一时间多个进程同时进行,但是微观上其实是多个进程轮流着使用CPU资源)

   4. 多级反馈算法(先来的进程会优先放在第一层的队列,某一个进程在本次时间片结束之后如果还没有被执行完,就一次降级放入下一级队列,然后再下一个时间片优先从新的队列开始执行)

 

 

3. 进程的并行与并发

并行: 同一时间多个进程同时被执行,比如赛跑,两个人都在不停的往前跑,三个进程 四核CPU

并发:在资源有限的情况下,多个进程轮流使用资源,比如一个独木桥(单核CPU)同时只能过一个人,A在本次时间片结束后,让给B来执行,交替使用来提高效率;

区别:

并行:从微观上,在一个精准的时间片刻,有两个进程同时来执行(真正意义上的同时,不是轮流)这需要与多个处理器CPU;

并发:从宏观上,在一个时间段上可以看出两个进程是同时执行的(但从微观上其实是两个进程轮流交替使用处理器资源),比如一个服务器同时处理多个session;

 

4. 同步 异步 阻塞 非阻塞(例子来讲)

例子:老张,烧水壶,会发出响声的烧水壶

同步阻塞:  老张用静音水壶烧开水,期间一致在等着水壶烧开(是老张自己来看水壶)----同步, 老张不做任何其他的事----阻塞(其他的事都干不了,只是主动等水开)

同步非阻塞: 老张拿着静音水壶烧开水,期间老张去干别的事,比如去客厅看电视(除了烧开水,还做了其他事)---非阻塞,然后会时不时的往厨房去看烧水壶有没有把水烧开(自己主动去看水壶有没烧开水)---同步;

异步阻塞:老张使用带有声音的水壶烧开水,不用主动去看水壶有没有烧开(异步) 但是在等待水烧开的这段时间也没有做其他的事,就只是单纯等待有声音的水壶发出声音来告诉老张水烧开了,老张是被动的接收这个消息的---异步,但是在等待水烧开的这段时间并没有做其他的事(阻塞);

异步非阻塞:老张使用带有声音的水壶烧水,不用自己主动留意水壶有没有烧开,由水壶发出声音来告诉老张水烧开了(异步),老张在等待水烧开的这段时间去做了其他的事---非阻塞;

 

 

5. 进程三态状态转换图

 

 

执行过程:

1. 首先创建一个进程,然后进入就绪状态(就是有可能虽然你准备好了,但是操作系统在该时间片在执行其他的进程,所以该进程需要等待--也就是就绪状态,等待时间片);

2. 然后进程调度,就是本进程占用CPU的过程,也就是该进程被执行,如果被执行过程中遇到了阻塞(事件请求)比如input,sleep,recv,accept(等待连接),该进程就会让出CPU,让其他进程来占用CPU;

   如果这个阻塞的事件(比如input  sleep等事件已经被执行完了)发生阻塞的进程也不会立刻被排到,虽然本进程的阻塞已经完成了,但是有可能该时间片CPU正在调度其他的进程,所以该程序又处于就绪状态啦;

3. 如果该进程没有遇到阻塞,等执行完之后就会释放该进程;

 

解释一下三个状态名词:

 1. 就绪(Ready)状态:

当进程一分配到CPU以外的所有必要的资源,只要活得处理机便可立即执行,这时的进程状态被称为就绪状态;

2. 执行(运行Running)状态:

当进程已获得处理机时,其程序正在处理机上执行,这时的进程状态称为就绪状态;

3. 阻塞(Blocked)状态:

当正在执行的进程由于等待某个事件发生而无法执行时,就会放弃处理机而处于阻塞状态,引起进程阻塞的事件可以有多种,比如等待I/O完成,申请缓冲区,不能满足等待信件(信号)等;

 

 

 6. 程序实现异步/同步 阻塞/非阻塞

# 异步非阻塞
from multiprocessing import Process  # 可以借助Process来创建一个子进程
import os
def func(money):
    print("取钱%s"%money)
    print("子进程:%s,父进程:%s"%(os.getpid(),os.getppid())) # os.getpid()获得当前进程,os.getppid()获得父进程
if __name__=="__main__":
    p=Process(target=func,args=(100,))   # target后面写开启的新进程需要执行的程序,args后面一定要跟一个元组(表示func函数的参数)
    print("主进程:%s"%(os.getpid()))  # 在主进程中打印当前进程的pid号
    p.start()   # 交给操作系统开启一个新进程,但是具体操作系统什么时候调度,不好控制的~
    print("取完钱了")   # 其实主进程的这句是独立于子进程的,所以是异步,就是func函数的执行交给子进程来执行,并不是由主进程来执行)
                        # 同时这里也是非阻塞,因为主进程开启一个子进程,自己又干了别的事

 

 运行结果:

 

 

 

# 同步非阻塞
import os
from multiprocessing import Process
def func():
    print("子进程%s"%os.getpid())  # 其实这里的os.getpid()也是主进程的id因为当前的进程就是主进程~

if __name__=="__main__":
    print("这里是同步非阻塞")  # 因为func函数是由主进程来执行的,并没有开一个新的进程来让新的进程来执行
    func()  # 主进程执行完func函数之后才会执行下面的代码(所以是同步)
    print("主进程%s"%(os.getpid()))

 

运行结果:

 

 

 

# 异步
import os 
import time
from multiprocessing import Process

def func(money):
    print("子进程%s,父进程%s"%(os.getpid(),os.getppid()))   # 打印子进程(当前进程是主进程开的一个子进程),父进程(主进程)
    print("取了%s钱"%money)
    time.sleep(3)   # 子进程中延时三秒,父进程会等待子进程执行完毕

if __name__=="__main__":
    p=Process(target=func,args=(100,))  # 创建一个进程,target=新的子进程需要执行的函数,args是该函数的参数
    print("主进程%s"%os.getpid())
    p.start()  # 交给操作系统开启一个新进程
    print("取完钱了")
    

 

 运行结果:

子进程虽然睡了三秒,主进程执行完自己的内容,还会等待子进程执行完毕才会结束~(我觉得这个是异步,因为开启新的子进程去执行func但是并不算阻塞,因为主进程的执行完了,只是等待子进程执行完而已把,,,)

 

 

# 使用join()方法----变为同步阻塞(主进程会等待子进程执行完之后在继续执行主进程剩下的代码)
from multiprocessing import Process
import os
import time
def func(money):
    print("2. 子进程%s,父进程:%s"%(os.getpid(),os.getppid()))
    print("3. 取了%s钱"%money)

if __name__=="__main__":
    print("1. 主进程:%s" % os.getpid())
    p=Process(target=func,args=(100,))
    p.start()
    p.join()    # 会等待子进程执行完之后才会执行主进程下面的语句,这又变为同步了(原本是主进程的会先被执行完,主进程跟子进程是异步的,主进程执行自己的)
    print("4.子进程执行完func函数啦")

 

 运行结果:

 

 

# 同时开多个进程
from multiprocessing import Process
import os
import time
def func(money):
    print("2. 子进程%s,父进程:%s"%(os.getpid(),os.getppid()))
    print("3. 取了%s钱"%money)

if __name__=="__main__":
    print("1. 主进程:%s" % os.getpid())
    p1=Process(target=func,args=(100,))
    p1.start()
    p2 = Process(target=func, args=(100,))
    p2.start()
    p3 = Process(target=func, args=(100,))
    p3.start()
    p1.join()    # 可以明确一点是,第四句话一定是在p1进程执行完之后才会被执行,但是开了两个进程p1,p2 谁先被执行不一定,是由操作系统决定的
    print("4.子进程执行完func函数啦")

运行结果:

 

 

# 使用for循环同时开多个进程,但是在for循环的外面放一个p.join() 主进程后面的代码会在最后一个被创建的进程执行完之后才会被执行,但是被创建的多个进程谁先被执行是不确定的
from multiprocessing import Process
import os
import time
def func(money):
    print("2. 子进程%s,父进程:%s"%(os.getpid(),os.getppid()))
    print("3. 取了%s钱"%money)

if __name__=="__main__":
    print("1. 主进程:%s" % os.getpid())
    for i in range(10):
        p=Process(target=func,args=(i,))
        p.start()
    p.join()   # 由于最后一个是第九个开启的进程,所以可以确定的是第四句话一定是在被第九个创建的进程执行完之后才会执行,但是这九个进程谁先被执行不一定,有操作系统决定
    print("4.子进程执行完func函数啦")

 

 运行结果:

 

 那我们如何在执行完所有的进程之后才能执行主进程后面的代码呢?

from multiprocessing import Process
import os
import time
def func(money):
    print("2. 子进程%s,父进程:%s"%(os.getpid(),os.getppid()))
    print("3. 取了%s钱"%money)

if __name__=="__main__":
    print("1. 主进程:%s" % os.getpid())
    for i in range(10):
        p=Process(target=func,args=(i,))
        p.start()
        p.join()   # 每执行完一个进程才会创建下一个进程,再执行,再创建,,,这样就变为同步的了
    print("4.子进程执行完func函数啦")

运行结果

 

 很显然这不是我们想要的结果,因为这样创建一个进程,执行一个进程,再创建,再执行。。。。就变为同步了,,

所以其实我们可以这样做:

# 创建多个进程,随机被开启,但是等所有的进程都执行完之后才会执行主进程后面的代码
from multiprocessing import Process
import os
import time
def func(money):
    print("2. 子进程%s,父进程:%s"%(os.getpid(),os.getppid()))
    print("3. 取了%s钱"%money)

if __name__=="__main__":
    print("1. 主进程:%s" % os.getpid())
    p_lst=[]  # 存放创建的进程
    for i in range(10):
        p=Process(target=func,args=(i,))
        p.start()  # 创建了10个进程,但是操作系统先执行哪个进程不确定,顺序是随机的
        p_lst.append(p)
    for p in p_lst:
        p.join()   # 把随机创建的进程每一个都执行,所有的进程都执行完之后才会执行主进程后面的代码
    print("4.子进程执行完func函数啦")

 

运行结果:

 

posted @ 2018-10-09 22:27  写的BUG代码少  阅读(205)  评论(0编辑  收藏  举报