一, 什么是进程
进程: 正在进行的一个过程或者说一个任务. 而负责执行任务的则是 CPU.
二, 进程与程序的区别
程序仅仅只是一堆代码而已, 而进程指的是程序的运行过程.
需要强调的是: 同一个程序执行两次, 那也是两个进程, 比如打开暴风影音, 虽然都是同一个软件, 但是一个可以播放苍进空, 一个可以播放饭岛爱.
三, 并发与并行
无论是并行还是并发, 在用户看来都是 "同时" 运行的, 不管是进程还是线程, 都只是一个任务而已, 真正干活的是 CPU,CPU 来做这些任务, 而一个 CPU 同一时刻只能执行一个任务.
1, 并发: 是伪并行, 即看起来是同时运行. 单个 CPU 加上多道技术就可以实现并发.
举例(单核 + 多道, 实现多个进程的并发执行):
egon 在一个时间段内有很多任务要做: python 备课的任务, 写书的任务, 交女朋友的任务, 王者荣耀上分的任务, 但 egon 同一时刻只能做一个任务(CPU 同一时间只能干一个活), 如何才能玩出多个任务并发执行的效果? egon 备一会课, 再去跟李杰的女朋友聊聊天, 再去打一会王者荣耀.... 这就保证了每个任务都在进行中.
2, 并行: 同时运行, 只有具备多个 CPU 才能实现并行
单核下, 可以利用多道技术, 那么多个核, 每个核也都可以利用多道技术(多道技术是针对单核而言的)
有四个核, 六个任务, 这样同一时间有四个任务被执行, 假设分别被分配给了 cpu1,cpu2,cpu3,cpu4, 一旦任务 1 遇到 I/O 就被迫中断执行, 此时任务 5 就拿到 cpu1 的时间片去执行, 这就是单核下的多道技术. 而一旦任务 1 的 I/O 结束了, 操作系统会重新调用它(需知进程的调度, 分配给哪个 CPU 运行, 由操作系统说了算), 可能被分配给四个 CPU 中的任意一个去执行.
四, 进程的创建(了解)
但凡是硬件, 都需要有操作系统去管理, 只要有操作系统, 就有进程的概念, 就需要有创建进程的方式, 一些操作系统只为一个应用程序设计, 比如微波炉中的控制器, 一旦启动微波炉, 所有的进程都已经存在. 而对于通用系统(跑很多应用程序), 需要有系统运行过程中创建或撤销进程的能力, 主要分为 4 种形式创建新的进程.
1, 系统初始化(查看进程在 Linux 中用 ps 命令, Windows 中用任务管理器, 前台进程负责与用户交互, 后台运行的程序与用户无关, 运行在后台并且只在需要时才唤醒的进程, 称为守护进程, 如电子邮件, web 页面, 新闻, 打印)
2, 一个进程在运行过程中开启了子进程(如 nginx 开启多进程, os.fork,subprocess.Popen 等)
3, 用户的交互式请求, 而创建一个新进程(如用户双击暴风影音)
4, 一个批处理作业的初始化(只在大型机的批处理系统中应用)
无论哪一种, 新进程的创建都是由一个已经存在的进程执行了一个用于创建进程的系统调用而创建的:
1, 在 UNIX 中, 该系统调用的是: fork,fork 会创建一个与父进程一模一样的副本, 二者由相同的存储映像, 同样的环境字符串和同样的打开文件(在 shell 解释器进程中, 执行一个命令就会创建一个子进程).
2, 在 Windows 中该系统调用是: CreateProcess,CreateProcess 既处理进程的创建, 也负责把正确的程序装入新进程.
关于创建的子进程, UNIX 和 Windows:
1, 相同的是: 进程创建后, 父进程和子进程有各自不同的地址空间(多道技术要求物理层面实现进程之间内存的隔离), 任何一个进程的在其地址空间中的修改都不会影响到另外一个进程.
2, 不同的是: UNIX 中, 子进程的初始地址空间是父进程的一个副本(提示: 子进程和父进程是可以有只读的共享内存区的. 但是对于 Windows 系统来说, 从一开始父进程与子进程的地址空间就是不同的.)
五, 进程的终止(了解)
1, 正常退出(自愿, 如用户点击交互式页面的叉号, 或程序执行完毕调用发起系统调用正常退出, 在 Linux 中 eixt, 在 Windows 中用 ExitProcess).
2, 出错推出(自愿, python a.py 中 a.py 不存在).
3, 严重错误(非自愿, 执行非法指令, 如引用不存在的内存, 1/0 等, 可以捕捉异常, try...except...).
4, 被其它进程杀死(非自愿, 如 kill -9).
六, 进程的层次结构
无论 UNIX 还是 Windows, 进程只有一个父进程, 不同的是:
1, 在 UNIX 中所有的进程, 都是以 init 进程为根, 组成树形结构. 父子进程共同组成一个进程组, 这样, 当从键盘发出一个信号时, 该信号被送给当前与键盘相关的进程组中的所有成员.
2, 在 Windows 中, 没有进程层次的概念, 所有的进程都是地位相同的, 唯一类似于进程层次的暗示, 是在创建进程时, 父进程得到一个特别的令牌(称为句柄), 该句柄可以用来控制子进程, 但是父进程有权把该句柄传给其它子进程, 这样就没有层次了.
七, 进程的状态
tail -f access.log |grep '404'
执行程序 tail, 开启一个子进程, 执行程序 grep, 开启另外一个子进程, 两个进程之间基于管道 | 通讯, 将 tail 的结果作为 grep 的输入.
进程 grep 在等待输入 (即 I/O) 时的状态称为阻塞, 此时 grep 命令都无法运行.
其实在两种情况下会导致一个进程在逻辑上不能运行,
1, 进程挂起是自身原因, 遇到 I/O 阻塞, 便要让出 CPU 让其它进程去执行, 这样保证 CPU 一直在工作.
2, 与进程无关, 是操作系统层面, 可能会因为一个进程占用时间过多, 或者优先级等原因, 而调用其它的进程去使用 CPU.
因而一个进程由三种状态:
八, 进程并发的实现(了解)
进程并发的是现在在于, 硬件中断一个正在运行的进程, 把此时进程运行的所有状态保存下来, 为此, 操作系统维护一张表格, 即进程表(process table), 每个进程占用一个进程表项(这些表项也称为进程控制块)
该表存放了进程状态的重要信息: 程序计数器, 堆栈指针, 内存分配状况, 所有打开文件的状态, 账号和调度信息, 以及其它在进程由运行态转为就绪态或阻塞态时, 必须保存的信息, 从而保证该进程在再次启动时, 就像从未被中断过一样.
来源: https://www.cnblogs.com/Kwan-C/p/11567584.html