动物网站建设策划书合肥seo整站优化
多道技术、进程理论
文章目录
- 多道技术、进程理论
- 一、操作系统
- 1.1操作系统
- 1.2操作系统中的常见概念
- 1.3操作系统的发展史
- 二、进程理论
- 2.1同步、异步、阻塞、非阻塞
- 2.2 进程的层次结构
- 2.3 运行态、阻塞态、就绪态
- 三、开启进程的两种方式
- 3.1使用Process创建进程的两种方式
- 3.2 父进程与子进程的关系
- 3.3 Process的属性介绍
一、操作系统
1.1操作系统
如下图所示,操作系统是一个协调、管理和控制计算机硬件资源和软件资源的控制程序,位于应用程序与硬件之间,负责按用户的指令操作硬件。
1.2操作系统中的常见概念
串行:一个任务完完整整地运行完毕后,才能运行下一个任务。
并行:真正意义上多个任务的同时运行,只有多核才实现并行。
并发:看起来多个任务是同时运行的即可,单核也可以实现并发。(伪并行)
cpu的功能:cpu是用来做计算,cpu是无法执行IO操作的。一旦遇到io操作,程序会阻塞在原地,cpu会去执行别的任务。
多道技术(单核cpu情况下):多道技术中的多道指的是多个程序,多道技术的实现是为了解决多个程序竞争同一个cpu的问题,解决方式即多路复用,多路复用分为时间上的复用和空间上的复用。
- 空间上的复用:多个程序共同加载入内存,且程序在内存中是物理隔离的。
- 时间上的复用:程序并发运行时cpu会在多个运行的程序间来回切换。
程序并发运行时cpu会在多个进程间来回切换指的是:
- cpu运行期间遇到I/O操作时会切换处理其他程序。
- cpu运行期间在某程序上运行时间较长时,也会切换处理其他程序。
简单来说就是cpu同时处理多个程序只是看起来的同时处理,本质是cpu在多个程序间来回的切换。
1.3操作系统的发展史
发展阶段 | 时间 | 组成 | 改进 | 缺陷 |
---|---|---|---|---|
第一代 | 1940~1955 | 真空板和穿孔卡片 | 无操作系统,程序设计需直接操作硬件 | |
第二代 | 1955~1965 | 晶体管和批处理系统 | 批处理,节省时间 | 串行操作且无法及时调整程序 |
第三代 | 1965~1980 | 集成电路芯片和多道技术 | 多道技术 | |
第四代 | 1980至今 | 个人pc | 并发 |
二、进程理论
进程指的就是一个正在运行的程序,或者说是程序的运行过程,即进程是一个抽象的概念。进程是起源于操作系统的,是操作系统最核心的概念,操作系统所有其他的概念都是围绕进程展开的。
进程和程序的区别:程序仅仅指一堆代码,而进程则是指程序的运行过程。拿厨师做菜举例,程序相当于菜谱,而进程则是厨师按菜谱做菜这个过程。
2.1同步、异步、阻塞、非阻塞
同步指程序在执行某个任务时,会等待该任务完成,然后才能继续执行后续的代码。在同步操作中,程序的执行流程是线性的,一个任务完成后,才会执行下一个任务。
异步指程序在执行某个任务时,不会等待该任务完成,而是继续执行后续的代码。当该异步功能完成后,通过状态、通知或回调来通知调用者。
阻塞:当一个进程/线程执行一个需要等待的操作时,它会停止执行,直到该操作完成。这意味着进程/线程会被挂起,直到所需的操作完成。
非阻塞:当一个进程/线程执行一个需要等待的操作时,它会继续执行后续的代码,而不是停止等待。这意味着进程/线程可以同时进行其他工作,而不需要等待某个操作完成。
同步与异步针对的是函数/任务的调用而言的,阻塞与非阻塞针对的是进程/线程的。同步就是当一个进程发起一个函数/任务调用的时候,一直等到函数/任务完成,而进程继续处于激活状态;阻塞是当请求不能满足的时候就将进程挂起,也就是进程是非激活的。
2.2 进程的层次结构
在Linux中所有的进程都是以init(或systemd)进程为根,组成树形结构。在windows中没有进程层次的概念,所有的进程都是地位相同的。唯一类似于进程层次的暗示是在创建进程时,父进程得到一个特别的句柄,该句柄可以用来控制子进程,但是父进程有权把该句柄传给其他子进程。
2.3 运行态、阻塞态、就绪态
运行态、阻塞态、就绪态是进程的三种状态,其关系如下:
三、开启进程的两种方式
父进程开启子进程的过程中,操作系统会开辟一个新的内存空间存放子进程代码,并将父进程数据拷贝一份给子进程。
3.1使用Process创建进程的两种方式
方式一:
from multiprocessing import Process
import time#子进程执行的函数
def task(x):print('%s is running' %x)time.sleep(3)print('%s is done' %x)#windows中创建子进程会父进程的文件作为模块导入(复制父进程数据),不写下方代码会引发循环导入问题。
if __name__ == '__main__':#创建子进程,target传入子进程执行的功能,args为task函数的参数,如果传关键字参数用kwargsp=Process(target=task,args=('子进程',))#向操作系统请求开启子进程,p.start本质上是运行了进程中的run方法p.start()print('主进程')#父进程需等待子进程结束以后才会结束
方式二:
from multiprocessing import Process
import time#通过类创建子进程
class Myprocess(Process):def __init__(self,name):#Process类中有个参数name表示子进程的名称super().__init__(name=name)#run函数为子进程执行的功能函数,Myprocess是abc类的子类,必须复写run函数def run(self):print('%s is running' %self.name)time.sleep(3)print('%s is done' %self.name)if __name__ == '__main__':p=Myprocess('子进程1')#执行run方法向操作系统请求开启子进程p.start() print('主')
上述代码的打印结果为:
原因是p.start() 向操作系统请求开启子进程,而p.start函数的执行是异步的,父进程请求完以后会继续执行下面的代码,直到父进程执行完以后操作系统才开启完毕子进程并运行子进程。
如果想让子进程先运行完再打印’主’可以添加p.join()
from multiprocessing import Process
import time#通过类创建子进程
class Myprocess(Process):def __init__(self,name):#Process类中有个参数name表示子进程的名称super().__init__(name=name)#run函数为子进程执行的功能函数,Myprocess是abc类的子类,必须复写run函数def run(self):print('%s is running' %self.name)time.sleep(3)print('%s is done' %self.name)if __name__ == '__main__':p=Myprocess('子进程1')#执行run方法向操作系统请求开启子进程p.start() #父进程在此阻塞等待子进程运行结束后才运行下面的代码p.join()print('主')
注意点:
from multiprocessing import Process
import timedef task(x):print('%s is running' %x)time.sleep(3)print('%s is done' %x)if __name__ == '__main__':p1=Process(target=task,kwargs={'x':'子进程1'})p2 = Process(target=task, kwargs={'x': '子进程2'})p1.start()p1.join()p2.start()p2.join()print('主')
上述代码中
p1.start()
p1.join()
p2.start()
p2.join()
会让子进程p1运行完以后才开启子进程p2,子进程p2运行完后打印’主‘。话句话是就是子进程p1和子进程p2变成同步运行的了。
如果想让子进程p1和子进程p2异步运行并在两子进程运行完后父进程才打印’主’应将程序改为
from multiprocessing import Process
import timedef task(x):print('%s is running' %x)time.sleep(3)print('%s is done' %x)if __name__ == '__main__':p1=Process(target=task,kwargs={'x':'子进程1'})p2 = Process(target=task, kwargs={'x': '子进程2'})p1.start()p2.start()p1.join()p2.join()print('主')
3.2 父进程与子进程的关系
- 各个进程之间是相互隔离的,也就是说某一个进程中数据的变化不会影响其他进程。
- 父进程执行完以后需等待子进程执行完,并回收子进程的pid号。
3.3 Process的属性介绍
from multiprocessing import Process
import timeclass Myprocess(Process):def __init__(self,name):super().__init__(name=name)def run(self):print('%s is running' %self.name)time.sleep(3)print('%s is done' %self.name)if __name__ == '__main__':p=Myprocess('子进程1')
如上方代码所示创建子进程p。
p.terminate()表示向操作系统请求强制终止子进程p。
p.is_alive()表示查看子进程是否存活。
p.pid表示子进程的pid号。如果想查看父进程的pid可以在父进程使用os.getpid()或者在子进程使用os.getppid()
p.name表示子进程的名称。