一:什么是进程?
进程指的是一个正在进行/运行的程序,进程是来用描述程序执行过程的虚拟概念。
二:操作系统理论:
1.什么是操作系统?
操作系统是一个协调/管理/控制计算机硬件资源与应用软件资源的一段控制程序。
2.操作系统两大功能:
1.将复杂的硬件操作封装成简单的接口,给应用程序或者用户去使用。
2.将多个进程对硬件的竞争变得有序。
3.操作系统发展史
第一代计算机:程序是固定的,无法修改,某种计算机只能敢某种特定的工作
第二代计算机:批处理系统,需要人工参与,将程序集中到一起,给计算机统一执行。
第三代计算机:为了更好的利用计算机资源,产生了多道技术。
并发:在统一个时间段内,发生多个事情,多个任务看起来像是同时运行的
串行:一个任务完完整整的运行完毕,才能运行下一个任务
多道技术:
1.空间复用:多个任务复用内存空间,将内存分为多个区域,每个区域存储不同的程序
2.时间复用:多个任务复用CPU的时间
1.一个任务占用CPU时间过长会被操作系统强行剥夺走CPU的权限:比起串行执
行反而会降低效率
2.一个任务遇到i/o操作也会被操作系统强行剥夺走cpu的权限,但是切换前需要
保存当前的运行状态,以便恢复执行,提高效率。比起串行执行可以提升效率
三:同步/异步&阻塞/非阻塞
同步
# 所谓同步就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回。如果按照这个定
# 义,那么绝大多数函数都是同步调用。但是一般而言,我们在说同步,异步的时候,特指那血需要# 其他部件协作或者需要一定时间完成的任务。
# 发起同步调用后,就在原地等着任务结束,根本不考虑任务时在计算还是在I/O阻塞,就是简单的
# 等待任务结束。
异步
# 异步的概念和同步是相对的。当一个异步功能调用发出后,调用者不能立刻得到结果。当异步功能# 完成后,通过状态/通知或者调用来通知调用者,如果异步功能用状态来通知,那么调用者就需要
# 每隔一定时间检查一次,效率就很低。如果是使用通知的方式,效率则高很多,因为异步功能几乎# 不需要做额外的操作。至于回调函数,其实和通知没什么区别。
阻塞
# 阻塞调用时指调用结果返回之前,当前线程回被挂起(如i/o操作)。函数只有在得到结果之后才
# 会将阻塞的线程激活。有人也会把阻塞调用和和同步调用等同起来,实际上它是不同的。对于同步
# 调用者来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。
非阻塞
# 非阻塞和阻塞的概念是像对应,指在不能立刻得到结果之前也回立刻返回,同时该函数不会阻塞当 # 前线程
小结:
1.同步与异步针对的是函数/任务的调用方式:同步就是当一个进程发起了一个函数(任务)调
用的时候,一直等到函数(任务)完成,而进程继续处于激活状态。而异步情况是当一个发
起一个函数(任务)调用的时候,不会等函数返回,而是继续往下执行,当函数返回的时候
通过状态/通知/事件等方式通知进程任务完成。
2.阻塞和非阻塞针对的是进程或线程:阻塞是当请求不能满足的时候就将进程挂起,而非阻塞
则不会则是当前进程
注意:串行中阻塞和等待的区别,阻塞是指在进行I/O操作时,cpu被分配给其他进程而等待是cpu
还在该程序中,执行权没有发生改变。
四:进程
1.进程和程序的区别
程序:一堆代码
进程:程序执行的过程
进程的概念起源于操作系统,进程是操作系统最核心的概念,操作系统其他所有的概念都是围
绕进程来的。
注意:同一个程序执行两次,那也是两个进程,比如打开QQ,登录两个不同的QQ号。
2.启动进程的方式
1.系统初始化,回产生一个根进程
2.用户的交互请求,鼠标双击某个程序
3.在一个进程中,发起了系统调用启动了另个进程
4.批处理作业开始,某些专用计算机可能还是使用(了解一下就可以了)
方式一
# 导入模块Process
from multiprocess import Process
import time
# 需要子进程执行的任务
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is stop' %name)
if __name__ == '__main__': # if 下面所有的内容都是父进程
# 告诉系统创建一个进程对象
p = Process( target = task,args = ('aaa',))
# 开始执行子进程
p.start()
print('hello')
print('see you')
方式二
# 导入模块Process
from multiprocessing import Process
# 定义一个类,继承Process
class Myprocess(Process):
# 当子进程被执行的时候就执行run函数
def run(self):
# 需要子进程做的事情
print('need to do sth for run')
if __name__ == '__main__':
Myprocess().start()
print('hello')
3.父进程和子进程的执行顺序
from multiprocessing import Process
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is stop' %name)
if __name__ == '__main__':
p = Process(target = task,args = ('aaa',))
p.start()
print('hello')
time.sleep(4)
print('see u')
# 打印结果
# hello
# aaa is running
# aaa is stop
# see u
# 所以,子进程和父进程的执行顺序就是,从上往下正常执行父进程,如果父进程的某一行code开# 始p.start()调用了子进程,那么子进程的内容和父进程下面的代码会并发执行。
4.子进程对象p.join()的用法
from multiprocessing import Process
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is stop' %name)
if __name__ == '__main__':
p = Process(target = task,args = ('aaa',))
p.start()
print('hello')
p.join()
print('see u')
# join() 的用法就是父进程要等待子进程的时间,如果超过该时间,不管子进程中的代码有没
# 有执行完成,父进程都执行下面的代码。 如果不传入参数,则是一定要等待子进程执行完成后才# 执行后面的代码
5.进程对象常用的属性
from multiprocessing import Process
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is stop' %name)
if __name__ == '__main__':
p = Process(target = task,args = ('aaa',))
p.start()
print('hello')
p.join() ## 1.join 等待时间
p.terminate() ## 2.terminate() 结束子进程
print(p.is_alive()) ## 3.is_alive() 判断进程是否还存活
print('see u')
import os
print(os.getpid()) ## 4.getpid() 获取当前进程的id
print(os.getppid()) ## 5.getppid() 获取父进程的id
# 总结:进程主要相关属性
# 1.join()
# 2.terminate()
# 3.is_alive()
# 4.getpid()/getppid()
6.僵尸进程和孤儿进程
#僵尸进程:
#一个进程任务一旦执行完成了就死亡了,但是操作系统不会立即清理,这样可以让父进程访问到子进程的信息。我们把这样的任务完成的,但是没有被操作系统清理的进程成为僵尸进程,越少越好,因为会占用内存空间。
#孤儿进程:
#顾名思义,就是一个父进程已经死亡了,但是它的子孙进程还在执行这,这个时候,操作系统会扮演孤儿院的角色,接管这些孤儿进程。