8-20-进程

上节课的内容:
    01 操作系统
        系统接口
        操作系统内核
    02 多道技术
        空间上的复用:复用内存的空间
              1、多道/个程序的代码都存入内存
              2、内存空间是物理隔离的
        时间上的复用:复用cpu的时间
            cpu的切换
                1、任务的运行遇到IO阻塞=》提升效率
                2、任务占用cpu时间过长=》降低效率

            如果我们的核心目标是想让多个任务并发起来:那么无论是遇到IO还是没有遇到IO都应该让cpu在多个任务之间切换起来
            如果我们的核心目标是想让多个任务的运行效率提升:我们应该只控制一个任务在遇到IO情况下切换到另外一个任务

今日内容:
    01 进程理论
        并发、并行、串行
        进程运行的三种状态:(运行态、就绪态)非阻塞态、阻塞态
        调用任务的两种方式:同步调用、异步调用
    02 进程的使用
        process


=================================> 进程理论 <=====================================

#1、什么是进程
	进程是一个程序运行的过程


#2、什么是程序
	程序就是一堆代码文件


#3、串行、并发、并行
	串行:多个任务依次运行,一个运行完毕再运行下一个
	并行:多个任务是真的在同时运行,只有多个cpu才有并行的概念
	并发:多个任务看起来是在同时运行


#4、进程的创建
	windows:CreateProcess
	linux:fork


#5、进程的终止
	1. 正常退出
	5. 被其他进程杀死(taskill /F /PID 3333)


#6、程序运行的三种状态
	运行态
	就绪态
	阻塞态

	优化程序效率的核心法则:降低IO操作(硬盘IO、网络IO)

	内存》本地硬盘-》网络IO


#7、
	进程运行的三种状态:(运行态、就绪态)非阻塞态、阻塞态
	调用任务的两种方式:同步调用、异步调用


=================================> 进程应用 <=====================================

			import os
			import time

			print(os.getpid())
			time.sleep(1000)


开启进程的方式一:

			import time
			import os
			from multiprocessing import Process


			def task(n, tag):
			    print("%s is running" % tag)
			    time.sleep(3)
			    print("%s is done" % tag)


			if __name__ == '__main__':
			    p1 = Process(target=task, args=(5, "子进程1"))
			    p2 = Process(target=task, args=(3, "子进程2"))
			    p3 = Process(target=task, args=(2, "子进程3"))
			    p1.start()
			    p2.start()
			    p3.start()
			    print("主:%s。。。" % os.getpid())


# 开启进程的方式二:
			
			import time
			import os
			from multiprocessing import Process

			class Myprocess(Process):
			    def __init__(self,tag):
			        super().__init__()
			        self.tag = tag

			    def run(self) -> None:
			        print("%s is running" % self.tag)
			        time.sleep(3)
			        print("%s is done" % self.tag)




			if __name__ == '__main__':
			    p1 = Myprocess("进程1")
			    p2 = Myprocess("进程2")
			    p3 = Myprocess("进程3")
			    p1.start()  # p1.run()
			    p2.start()  # p2.run()
			    p3.start()  # p3.run()
			    print("主:%s。。。" % os.getpid())



=================================> join <=====================================


			import time
			import os
			from multiprocessing import Process


			def task(n, tag):
			    print("%s is running" % tag)
			    time.sleep(n)
			    print("%s is done" % tag)


			if __name__ == '__main__':
			    p1 = Process(target=task, args=(3, "子进程1"))
			    p2 = Process(target=task, args=(4, "子进程2"))
			    p3 = Process(target=task, args=(5, "子进程3"))

			    # start=time.time()
			    p1.start()
			    p2.start()
			    p3.start()

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

			    print(p1.pid)
			    print(p2.pid)
			    print(p3.pid)


			    # print(time.time() - start)
			    print("主线程:%s。。。" % os.getpid())
			    
========================> 知识点整理 <=========================

if __name__  == '__main__' 的功能:

        如果当前文件是作为主文件执行的,他里面的代码才执行。

        如果是作为 模块导入(导入会先执行文件) ,则执行时不执行它里面的代码。




一个文件  <===对应===>  一个程序,
一个程序  <===对应===>  一个进程/线程(子进程)




os.getpid()
    获取当前文件(程序 or 进程)的id

os.getppid()
    获取当前文件(程序 or 进程)的父进程的id
        ppid = parent pid




语句 Process(target = func) 的作用

            def func():
                ...

            Process(target = func)


        <==== 等效于 ===>

            单独开辟一个文件存放:
            
            1、这个函数的定义代码
                def func():
                    ...
            2、执行函数的语句
                func()

                


这样依赖一个程序,开辟出来的这个文件执行时,也是一个进程,叫原程序(进程)的子进程

    对应关系: 父进程 ----> 子进程
    子进程是 依赖于 父进程创建的

        子进程: 依赖一个文件(进程),创建出来的进程

        父进程: 被依赖的是父进程



				# ### 进程
				import os

				# 当前进程id(子进程)
				res = os.getpid()

				# 当前进程的父进程id
				res2 = os.getppid()

				from multiprocessing import Process

				# (1) 进程使用的基本语法
				def func():
				    ...

				# windows 里面下面这句话必须要加;
				if __name__=='__main__':
				    # 创建子进程,返回一个进程对象(用这个进程对象,才能启动子进程),执行func任务
				    p = Process(target = func) 
				    # 调用子进程
				    p.start()



创建带有参数的进程

    Process 创建子进程,返回进程的对象p,
    target 指定要执行的任务
    args 指定传递的参数,args的类型是元组,多个参数之间用 逗号 隔开




cpu只用来进行 运算(算数运算 and 逻辑运算),具体的操作是cpu发号施令 由其他部件来完成的。

所以当程序的一个程序如果涉及到了非运算的操作(即 需要一定的时间才能完成的操作)的时候,则就会立马进入阻塞态,当操作完成的时候,才回到就绪态(等待 cpu轮转执行)




进程核心语句:

    p = Process(......) : 得到一个进程对象, 指定了要执行的任务是什么

    p.start: 为进程分配资源,创建进程,cpu轮转执行进程
    



先看到Process语句后面的语句效果的原因(前面的语句后打印了,后面的语句先打印了):

创建子进程的时候阻塞了,要为它开辟空间、分配空间、 分配内存、分配cpu、分配资源

分配资源的时候,一定会发生阻塞

直到资源分配完的这段时间内,先执行后面的语句 


同步: 必须要等当前语句执行完毕后,才会往下面走
    cpu发出命令,并且所有的命令所要进行的操作,都执行完(cpu得到命令所代表的操作都执行完毕的信号)

异步: 不等当前语句执行完,就往下走
    cpu发出当前语句所具有的所有命令后,不需要等待所有的操作都执行完毕,就开始执行下一条语句


全局变量:
    
    访问: 直接访问


    修改: 在函数内部希望对全局变量进行修改,需要使用关键字global


对于多个阻塞的进程,谁先从阻塞态 变成 就绪态,就先执行谁



# (3)进程之间的数据隔离
        count = 100
        def func():
            global count
            count += 1
            print(f'我是子进程count = {count}')

        if __main__ == '__main__':
            p = Process(target = func )
            p.start()
            time.sleep(1)
            print(count)


# (4) 多个进程可以
    异步(不等你走完,我就继续往下走了,我是额外的另一个主线)
    并发(一个cpu在多个程序之间来回进行切换,由于速度太快,所以看起来多个程序在一起齐头并进,这其实是一种假象,其实都是由一个cpu搞定的)


默认程序在异步并发任务时,因为cpu调度策略问题,不一定先先执行或后执行谁,整体而言,主进程速度快于子进程,cpu遇到阻塞立刻切换到其他任务,等到进程的就绪态再切换回来.

主程序默认等待所有的子进程执行结束之后,再关闭程序,释放资源
若不等待,子进程并不方便管理,容易造成僵尸进程,在后台不停的占用系统的资源(cpu和内存等),不清楚进程的来源




进程对象 和 启动进程  这两条语句可以合并成一句:

    Process(target=func,args = (1,)).start()


下面的程序执行 创建10个子进程语句 没有发生阻塞,
只不过是创建进程的过程中发生了阻塞(因为一旦涉及分配空间,就一定会发生阻塞)
if __name__ == '__main__':
    for i in range(1,11):
        Process(target=func,args =(i,)).start

由于 异步 的原因,打印的结果并不是按照1~10 的顺序,
谁先从 创建进程的阻塞态 编程 就绪态,cpu就先执行谁

主程序 等待 所以的子程序 结束之后,再彻底的去释放资源
这一机制 也 防止了 僵尸进程的出现


主进程  具有管理  子进程的功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值