Cpython的进程,线程,协程,io模型
Posted 临江尘
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cpython的进程,线程,协程,io模型相关的知识,希望对你有一定的参考价值。
一、进程:
一 基础概念:
1、进程的定义: 进程本身是一个抽象的概念,进程是操作系统资源分配的基本单位,是正在进行的一个过程或者说一个任务,负责执行任务的是cpu。
2、并行与并发: 假设计算机只有一个cpu,由于一个cpu在同一时间只能执行一个任务,那么当有多个任务想同时运行按道理那么需要多个cpu执行
这个时候如果有多个cpu同时运行这些任务就是并行,如果是一个cpu运行多个任务(其实就是cpu在多个任务之间来回切换则为并发)
那么由此定义如下:
并行:多个任务同时运行,只有具备多个cpu才能实现并行。
并发:伪并行,看起来是同时运行多个任务,实际上是单个CPU在多个程序之间来回切换。
3、同步与异步: 当一个进程在执行多个任务时,如果要等待到该任务执行完成才会继续执行下个任务,那么就属于同步。
如果该进程在执行某个任务是,不等待该任务是否完成而继续执行下个任务,那么就是异步。
举个例子:
打电话就是同步,你必须跟这个人通话完成(排除呼叫等待)才能接另外一个人的电话,不能同时接两个人的电话
发短信就是异步,QQ聊天也是异步,你可以不用等待收件人是否有回复信息而继续和其他人聊天。
4、阻塞与非阻塞: 阻塞:调用结果返回之前,该执行程序会被挂起,不释放CPU执行权,线程不能做其它事情,只能等待,只有等到调用结果返回了,才能接着往下执行;
非阻塞:就是在没有获取调用结果时,不是一直等待,线程可以往下执行,如果是同步的,通过轮询的方式检查有没有调用结果返回,如果是异步的,会通知回调。
5、同步、异步、阻塞、非阻塞区别:(参考知乎的回答)
同步与异步关注的是:消息的通信机制,阻塞与非阻塞关注的是:程序在等待调用结果时的状态,
举个例子:
比如你打电话问书店老板有没有《gold瓶梅》这本书:
如果是同步通信机制,老板说你稍等我查下,(可能等待一天或者几秒)然后告诉你返回结果。
异步通信机制,老板会直接告诉你我查下,查好了打电话给你,然后直接挂电话(不返回结果),查好了老板会打电话给你。
阻塞机制:你会把自己一直挂起,等待老板给你打电话告知这本书的查询结果,知道有返回结果。
非阻塞机制:你不管老板有没有告诉你,你自己先一边去干别的了,然后根据你自己设定的时间检查老板有没有返回结果给你。
二 进程的创建和终止:
创建:
1. 系统初始化(查看进程linux中用ps命令,windows中用任务管理器)
2. 一个进程在运行过程中开启了子进程
3. 用户的交互式请求,而创建一个新进程(如用户双击暴风影音)
终止:
1. 正常退出
2. 出错退出
3. 被其他进程杀死
三 进程间的通信方式:
1、管道:管道可用于具有亲缘关系的父子进程间的通信
2、信号:用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。
3、消息队列:消息队列是消息的链接表。
4、共享内存:使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。
5、信号量:主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段。
6、套接字:它可用于网络中不同机器之间的进程间通信。
二、线程:
一基础概念:
1、线程的定义:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位多线程是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间。
2、线程的特点:
-
-
首先易于调度。其次提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一程序的不同部分。还有就是开销少。
-
二进程与线程的关系以及区别:
关系:
-
-
一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
-
同一进程的所有线程共享该进程的所有资源。
-
线程在执行过程中,需要协作同步。
-
区别:
-
-
调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
-
并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
-
拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
-
系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
-
三、协程:
一基础概念:
1、协程的定义:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的
二协程的特点:
1、协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
2、必须在只有一个单线程里实现并发
3、修改共享数据不需加锁
四、IO模型:
由于进程是不可直接访问外部设备的,所以只能调用内核去调用外部的设备(上下文切换),然后外部设备比如磁盘,读出存储在设备自身的数据传送给内核缓冲区,内核缓冲区在copy数据到用户进程的缓冲区。在外部设备响应的给到用户进程过程中,包含了两个阶段;由于数据响应方式的不同,所以就有了不同的I/O模型。
IO模型的区别主要在以下两个阶段上:
1)等待数据准备。
2)将数据从内核拷贝到进程中。
一、阻塞IO:
如下
当用户调用了recvfrom进程,内核第一个阶段:准备数据。网络 io来说,很多时候数据在一开始还没有到达,这个时候内核就要等待足够的数据到来。
而在用户进程这边,整个进程会被阻塞。当内核收到数据,它就会将数据拷贝到用户内存,用户进程才解除block的状态,重新运行起来。
二、非阻塞IO:
如下:
非阻塞的recvform系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error。进程在返回之后,可以干点别的事情,然后再发起recvform系统调用。重复上面的过程,循环往复的进行recvform系统调用。这个过程通常被称之为轮询。轮询检查内核数据,直到数据准备好,再拷贝数据到进程,进行数据处理。需要注意,拷贝数据整个过程,进程仍然是属于阻塞的状态,在非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有。相当于上面的例子你自己设定个时间轮询询问老板有没有找到你要的书
三、多路复用IO:
有些地方也称这种IO方式为事件驱动IO(event driven IO),
在内核请求IO设备响应指令发出后,数据就开始准备,在此期间用户进程是阻塞的。数据从kernel buffer复制到用户进程的过程也是阻塞的。但是和阻塞I/O所不同的是,它可以同时阻塞多个I/O操作,而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数,也就是说一个线程可以响应多个请求。
四、异步IO:
用户进程发起read操作之后,立刻就可以开始去做其它的事。从内核的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。
五、IO模型对比:
non-blocking IO和asynchronous IO的区别还是很明显的。在non-blocking IO中,虽然进程大部分时间都不会被block,但是它仍然要求进程去主动的check,并且当数据准备完成以后,也需要进程主动的再次调用recvfrom来将数据拷贝到用户内存。而asynchronous IO则完全不同。它就像是用户进程将整个IO操作交给了他人(kernel)完成,然后他人做完后发信号通知。在此期间,用户进程不需要去检查IO操作的状态,也不需要主动的去拷贝数据。
参考博客:https://www.cnblogs.com/microfan/p/5294250.html
https://blog.csdn.net/linhuaiyang/article/details/68483222
以上是关于Cpython的进程,线程,协程,io模型的主要内容,如果未能解决你的问题,请参考以下文章