多道技术、进程

一、计算机发展史

https://www.cnblogs.com/Dominic-Ji/articles/10929381.html

二、多道技术

理解多道技术首先需要知道并行于并发的概念

并发:

看起来像是同时运行的就可以称之为并发,是指在资源优先的情况下,两者交替轮流使用资源。比方来说:只有一支笔(单核CPU资源),有两个学生(进程),学生A写完作业看书的时候,将笔让给学生B写作业,学生B写完作业看书的时候又将笔交给学生A写作业,这样这支笔就得到了充分的利用。

并行:

并行是指两者同时执行,用上面的例子来说的话就是学生A和学生B可以同时写作业,但是这样需要一个前提,就是需要两只笔(资源够用,比如三个线程,四核的CPU,所以单核的CPU不能实现并发)。

两者区别:

并行是从微观上,也就是在一个精确的时间片刻,有不同的程序在执行,这就要求必须有多个处理器。

并发是从宏观上,在一个时间断上可以看出是同时执行的,比如一个服务器同时处理多个session,并行可以看成是并发的一种。

多道技术:

所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行。即同时把多个程序放入内存,并允许它们交替在CPU中运行,它们共享系统中的各种硬、软件资源。当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序。

img

在A程序计算时,I/O空闲, A程序I/O操作时,CPU空闲(B程序也是同样);必须A工作完成后,B才能进入内存中开始工作,两者是串行的,全部完成共需时间=T1+T2。

img

将A、B两道程序同时存放在内存中,它们在系统的控制下,可相互穿插、交替地在CPU上运行:当A程序因请求I/O操作而放弃CPU时,B程序就可占用CPU运行,这样 CPU不再空闲,而正进行A I/O操作的I/O设备也不空闲,显然,CPU和I/O设备都处于“忙”状态,大大提高了资源的利用率,从而也提高了系统的效率,A、B全部完成所需时间<<T1+T2。

多道程序设计技术不仅使CPU得到充分利用,同时改善I/O设备和内存的利用率,从而提高了整个系统的资源利用率和系统吞吐量(单位时间内处理作业(程序)的个数),最终提高了整个系统的效率。

  单处理机系统中多道程序运行时的特点:

  (1)多道:计算机内存中同时存放几道相互独立的程序;

  (2)宏观上并行:同时进入系统的几道程序都处于运行过程中,即它们先后开始了各自的运行,但都未运行完毕;

  (3)微观上串行:实际上,各道程序轮流地用CPU,并交替运行。

多道程序系统的出现,标志着操作系统渐趋成熟的阶段,先后出现了作业调度管理、处理机管理、存储器管理、外部设备管理、文件系统管理等功能。

由于多个程序同时在计算机中运行,开始有了空间隔离的概念,只有内存空间的隔离,才能让数据更加安全、稳定。

出了空间隔离之外,多道技术还第一次体现了时空复用的特点,遇到IO操作就切换程序,使得cpu的利用率提高了,计算机的工作效率也随之提高。

多道技术在进程间的切换需要先保存状态,切换可分为两种:

1)当程序遇到IO操作的时候,操作系统会剥夺该程序的CPU执行权限。

作用:提高了CUP的利用率,并且不影响程序的执行

2)当一个程序长时间占用CPU的时候,操作系统也会剥夺程序的CPU执行权限,这样有一个弊端,就是讲道理程序的执行效率(原本时间+切换时间)

三、进程

程序与进程的区别:

程序是硬盘上躺着的一堆代码,是”死“的,而进程则表示的是程序的执行的过程,是”活“的

进程的具体含义:

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。

广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。

进程调度:

  • 先来先服务调度算法

    """对长作业有利,对短作业无益"""
    
  • 短作业优先调度算法

    """对短作业有利,多长作业无益"""
    
  • 时间片轮转法+多级反馈队列

进程运行的三状态图:

两对重要的概率:

同步异步:描述的是任务的提交方式

同步:

任务提交后,原地等待任务的返回结果,等待的过程不做任何事(干等)

而在程序的层面上表现出来的感觉就是被卡住了

异步:

任务提交之后,不原地等待任务的返回结果,直接去做其他事情,任务的返回结果会有一个异步回调机制自动处理

例子:

你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

出处:https://www.zhihu.com/question/19732473/answer/20851256 作者:严肃

阻塞与非阻塞:描述的程序的运行状态

阻塞:

程序处于阻塞态,阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

非阻塞:

程序处于就绪态、运行态,非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

例子:

还是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。

出处:https://www.zhihu.com/question/19732473/answer/20851256 作者:严肃

上述概念的组合:最高效的一种组合就是异步非阻塞

开启进程的两种方式:

#一:定义进程函数

from multiprocessing import Process
import time


def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is over')


if __name__ == '__main__':
    # 1 创建一个对象
    p = Process(target=task, args=('qq',))
    # 开启进程
    p.start()  # 告诉操作系统让其创建一个进程,这个进程是异步的
    # time.sleep(1)
    print('主')
from multiprocessing import Process
import time



# 二:类的继承

from multiprocessing import Process
import time


class MyProcess(Process):
    def run(self):
        print('hello')
        time.sleep(2)
        print('bye')


if __name__ == '__main__':
    p = MyProcess()
    p.start()
    # time.sleep(1)
    print('主')

总结:

  • 创建进程就是在内存中申请一块内存空间将需要运行的代码丢进去

  • 一个进程对应在内存中就是一块独立的内存空间

  • 多个进程对应在内存中就是多块独立的内存空间

  • 进程与进程之间数据默认情况下是无法直接交互,如果想交互可以借助于第三方工具、模块

join方法

join是让主进程等待子进程代码运行结束之后,再继续运行。不影响其他子进程的执行

from multiprocessing import Process
import time


def task(name, n):
    print('%s is running'%name)
    time.sleep(n)
    print('%s is over'%name)


if __name__ == '__main__':
    # p1 = Process(target=task, args=('jason', 1))
    # p2 = Process(target=task, args=('egon', 2))
    # p3 = Process(target=task, args=('tank', 3))
    # start_time = time.time()
    # p1.start()
    # p2.start()
    # p3.start()  # 仅仅是告诉操作系统要创建进程
    # # time.sleep(50000000000000000000)
    # # p.join()  # 主进程等待子进程p运行结束之后再继续往后执行
    # p1.join()
    # p2.join()
    # p3.join()
    start_time = time.time()
    p_list = []
    for i in range(1, 4):
        p = Process(target=task, args=('子进程%s'%i, i))
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()
    print('主', time.time() - start_time)

进程之间数据相互隔离

from multiprocessing import Process


money = 100


def task():
    global money  # 局部修改全局
    money = 666
    print('子',money)


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()
    print(money)
原文地址:https://www.cnblogs.com/zhangtieshan/p/12757414.html