Loading

对进程以及创建进程的理解

【一】进程和程序

【1】什么是进程?

  • 进程就是正在运行的程序

【2】谁来执行进程?

  • cpu

【3】进程和程序的区别?

  • 程序是存储再硬盘里面的一堆代码和数据
  • 进程是正在运行的程序

【二】进程调度问题

  • 有一个算法叫做任务调度算法
  • 就像是一个非常聪明的调度员,在计算机系统中负责安排和管理各种任务(比如程序或进程)的执行顺序。想象一下,你在一个忙碌的餐厅里,服务员需要决定先给哪个顾客上菜,这个过程就像是任务调度。
  • 在计算机中,有很多任务都想要使用CPU(就像顾客想要吃饭一样),但CPU的能力有限,不能同时处理所有任务。因此,任务调度算法的作用就是决定哪个任务先执行,哪个后执行。这样的安排既要公平,又要高效,确保每个任务都能得到合理的处理时间,同时让整个系统运行得更流畅。
  1. 先来先服务(FCFS, First-Come, First-Served):这个算法很简单,谁先来,就先服务谁。就像排队买票,先来的人先买。
  2. 短作业优先(SJF, Shortest Job First):这个算法会优先处理那些需要时间最短的任务。想象一下,如果你是厨师,你可能会先做那些更快做好的菜。
  3. 时间片轮转(RR, Round Robin):这个算法把时间分成若干小块,每个任务轮流使用一小块时间。就像玩游戏时,每个人轮流玩一会儿。
  4. 优先级调度:在这个算法中,每个任务都有一个优先级,优先级高的任务先执行。这就像是某些VIP顾客可以优先点餐。

【三】串行,并发,并行img

【1】介绍

  • 串行 (Serial):想象一下,你是一位厨师,在厨房里一次只能做一道菜。你得先做完第一道菜,然后再开始做第二道,接着是第三道,依此类推。每道菜都需要等前一道做完才能开始。这就是串行,任务一个接一个地执行,前一个完成后才开始下一个。
  • 并发 (Concurrency):现在假设你仍然是那位厨师,但这次你在做一道菜的同时,可以监控正在炖的汤,并且偶尔还可以和顾客聊天。虽然你仍然一次只能专注于一件事,但你可以在不同任务之间迅速切换,给人一种同时处理多件事的感觉。这就是并发,多个任务交替进行,但在任意时刻实际上只有一个任务在执行。
  • 并行 (Parallelism):最后,想象你现在有一个团队,团队里有几位厨师。这次,当你在准备一道菜时,你的同事可以同时炖汤,另一个同事则可以和顾客聊天。这样,几件事情真正地在同一时间同时进行。这就是并行,多个任务在同一时刻同时发生,通常需要多个处理单元(比如多个厨师)。

【2】总结

  • 串行:一个接一个,按顺序执行。
  • 并发:一次只能做一件事,但可以迅速在多个任务之间切换。
  • 并行:多件事情同时进行。
  • 核心:多道技术就是:cpu切换和保存状态

【四】同步/异步/阻塞/非阻塞(重要)

【1】介绍

  • 同步 (Synchronous):想象你去咖啡店点了一杯咖啡。在咖啡没做好之前,你就站在那里等,什么其他事都不做,直到咖啡做好,你拿到咖啡后再去做其他事情。这就是同步,你的行为(等待咖啡)和咖啡制作过程是一致对应的。
  • 异步 (Asynchronous):这次同样是在咖啡店点咖啡,但是在咖啡制作的同时,你不用站在那里等。你可以去做一些其他的事情,比如看书或者刷手机。当咖啡做好了,店员会叫你来拿。这就是异步,你的行为(做其他事情)和咖啡制作过程是分开的,不用一直等待咖啡制作完成。
  • 阻塞 (Blocking):再想象一下,你在餐馆点了一道菜,然后就坐在桌子旁边等,直到菜做好。在这期间,你不做任何事情,只是等待。这就是阻塞,你的等待阻止了你做其他事情。
  • 非阻塞 (Non-blocking):这次在餐馆点餐后,你不是一直坐在那等,而是去玩手机、看书或跟朋友聊天。尽管你还在等你的菜,但你没有被这个等待过程所阻塞,你可以同时做其他事情。这就是非阻塞,等待某个操作的完成时,你可以同时进行其他操作。

【2】同步 vs 阻塞

  • 关注点不同:同步关注的是操作的执行顺序,而阻塞关注的是程序在等待时的行为。
  • 应用场景:你可以有同步但非阻塞的操作,例如,同步轮询一个状态标志,直到它改变。同样,也可以有异步但阻塞的操作,例如在多线程应用中使用阻塞队列。

【3】总结

  • 同步:在一个操作完成之前,一直等待。
  • 异步:提交操作后可以做其他事情,操作完成后会通知你。
  • 阻塞:等待(比如输入输出操作)时什么也做不了。
  • 非阻塞:等待时还可以做其他事情。

【五】进程的创建和状态

【1】引入

  • 进程是计算机中的一个基本概念,它代表了计算机中正在运行的程序。每个进程都有自己的内存空间、数据和执行的代码。我们可以把进程想象成一个工厂里的工作线:它有自己的任务(程序代码),需要的材料(数据),以及工作的空间(内存)。

【2】进程的创建

  • 加载: 计算机把程序的代码和所需数据加载到内存中。
  • 初始化: 设置进程的初始状态,比如分配一个唯一的标识符(PID)、确定进程优先级、创建进程控制块(PCB)等。
  • 执行: 开始执行程序的代码。
  • 等待: 在某些情况下,比如等待用户输入或文件读写操作,进程会暂时停止执行。
  • 终止: 程序执行完成后,进程会被终止,释放所占用的资源。

【3】进程的三状态

  • 阻塞态(阻塞):等待某个事件的完成;
  • 就绪态(就绪):等待系统分配处理器以便运行;
  • 运行态(运行):占有处理器正在运行;

运行态——>阻塞态:往往是由于等待外设,等待资源分配或等待人工干预而引起的。

阻塞态——>就绪态:则是等待的条件已满足,只需要分配到处理器后就能运行。

就绪态——>运行态:系统按照某种策略选中就绪队列中的一个进程占用处理器,就绪就变成了运行态。

就绪 —操作系统调度—> 运行 —遇到IO操作—> 阻塞 —阻塞状态结束—> 就绪

【六】创建进程的两种方式

  • 方法一
# 创建进程 方法一

from multiprocessing import Process  # 导入模块中类,用于创建新的进程
import time  # 导入time模块,用于在后面的函数中实现等待(休眠)功能。


def func(name):
    print(f'{name}任务开始')
    time.sleep(3)
    print(f'{name}任务结束')


if __name__ == '__main__':
    p = Process(target=func, args=('写作业',))
    p.start()  # 异步提交了一个任务
    print('主进程')
  • 方法二
# 创建进程 方法二
from multiprocessing import Process
import time


class MyProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.task_name = name

    def run(self) -> None:
        print(f'{self.task_name}任务开始')
        time.sleep(3)
        print(f'{self.task_name}任务结束')


if __name__ == '__main__':
    p = MyProcess('打游戏')
    p.start()
    print('主进程')

【七】进程之间的数据是相互隔离的

from multiprocessing import Process

age = 18


def run():
    global age
    age += 2
    print(age)


if __name__ == '__main__':
    p = Process(target=run, args=())
    p.start() # 20
    p.join()  # join会使子进程先运行完再运行主进程
    print(age) # 18
  • 可以看到主进程输出的age依旧是18
  • 而经过修改的子进程的age输出的就是20

【八】查看进程ID的两种方法

【1】multiprocessing模块里的current_process方法

from multiprocessing import Process, current_process
import time


def func():
    print('我是子进程')
    print(f'子进程ID:>>>>{current_process().pid}')
    time.sleep(20)


if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    print(f'主进程ID:>>>>{current_process().pid}')

【2】os模块下的getpid方法

  • 获取进程ID
from multiprocessing import Process, current_process
import time
from os import getpid


def func():
    print('我是子进程')
    print(f'子进程ID:>>>>{getpid()}')
    time.sleep(20)


if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    print(f'主进程ID:>>>>{getpid()}')
  • 获取父ID
from multiprocessing import Process, current_process
import time
from os import getpid, getppid


def func():
    print('我是子进程')
    print(f'子进程ID:>>>>{getpid()}')
    print(f'父进程ID:>>>>{getppid()}')
    time.sleep(20)


if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    print(f'主进程ID:>>>>{getpid()}')
'''
主进程ID:>>>>26316
我是子进程
子进程ID:>>>>20696
父进程ID:>>>>26316

'''

【九】其他进程操作方法补充

【1】杀死进程(Process类里的terminate方法)

from multiprocessing import Process, current_process
import time
def func():
    print('我是子进程')




if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    time.sleep(2)
    p.terminate()
    time.sleep(2)

【2】判断进程是否存货(Process类里面的is_alive方法)

from multiprocessing import Process, current_process
import time

def func():
    print('我是子进程')




if __name__ == '__main__':
    p = Process(target=func)
    p.start()
    print(p.is_alive())
    time.sleep(2)
    p.terminate()
    time.sleep(2)
    print(p.is_alive())

'''
True
我是子进程
False
'''

posted @ 2024-01-16 16:56  HuangQiaoqi  阅读(5)  评论(0编辑  收藏  举报