1. 进程概念

1. 进程概念

  1. 内核功用:进程管理、文件系统、网络功能、内存管理、驱动程序、 安全功能等
  2. Process: 运行中的程序的一个副本,是被载入内存的一个指令集合 进程ID(Process ID,PID)号码被用来标记各个进程 UID、 GID、和SELinux语境决定对文件系统的存取和访问权限 通常从执行进程的用户来继承 它存在生命周期
  • task struct:Linux内核存储进程信息的数据结构格式
  • task list:多个任务的的task struct组成的链表
  1. 进程创建: init:第一个进程 进程:都由其父进程创建,父子关系,CoW,fork(), clone()

1.1. 注意:

  1. 进程和不是程序,它是程序加载到内存中之后进行运行的各种指令操作的集合
  2. 程序运行时先将它加载到内核空间内存中,然后再将它分配到用户空间内存中中,此时相当于系统分配给它一个独立的内存空间。这时候它便成为了进程,并且和其他的进程相互隔离。它认为自己独占了整个内存空间(虚拟出来的内存,并非真实的内存空间),并在此基础上进行操作。实际上它占用的只是系统给它分配的一小块内存空间而已。
  3. 进程运行时会随机分配一个进程编号,运行结束之后会被会被回收。它运行时就相当于一个资源的集合,有自己的独立的内存,能读取数据进去,有自己的二进制执行程序命令,包括很多县城等等。
  4. 进程内部真正执行操作计算的是线程,一个线程就是各种指令的集合。一个进程内至少有一个线程,可以有多个。
  5. 进程的生命周期有长期的(后台进程),有一次性短期运行的(前台进程)。比如说开机就开始运行的init进程,还有cat ls等程序的进程。
  6. task struct : 一个数据结构,包含了进程的各种元数据。
  7. 创建子进程如果用clone()函数,就会产生CoW(写时复制)方式,类似逻辑卷中的快照:只有子进程中对数据进行修改了,才会重新创建一个不同的数据存放于子进程中。而数据并未更改时它和父进程指向同一个数据,共用此数据。(最开始学习中的小括号开启子进程,小括号内局部变量如果不赋值,仍然和父进程的变量内容一样就是这个原因)
  8. 协程就是多个命令的集合代码块(类似函数),多个协程组成一个线程。进程中线程的执行顺序的优先级是由操作系统内核来调度的,而CPU在同一时间只能运行一个线程。我们人看到进程的执行感觉它是同时执行的,其实它只是利用CPU的时间频率分成了多个时间段,然后一个时间段执行一个线程,由内核调度,不论是否完成这个线程,只要时间段一到,它就会切换到另一个线程进行运行,保存当前线程的状态,这也就是所谓的上下文切换(注意,线程切换可以是不同进程的线程,也就相当于切换了不同的进程)。因为CPU频率极快,因此我们看起来它貌似是同步执行了多个进程。
  9. 上下文切换会造成CPU内的当前线程(或进程)缓存数据(L1,L2,L3)失效,相比于CPU的运算时间,这个代价非常巨大,因此要尽量避免上下文切换进行优化。

1.2. 进程,线程和协程

系统进程基础插图

1.3. 进程相关概念

  • Page Frame: 页框,用存储页面数据,存储Page 4k (也就是进程使用的内存空间,类似磁盘的块block)

  • 物理地址空间和线性地址空间:物理上的实际内存和应用程序使用时认为的虚拟内存(相当于偏移地址)

  • MMU:Memory Management Unit 负责转换线性和物理地址,CPU内的内存管理单元

  • TLB:Translation Lookaside Buffer 翻译后备缓冲器,用于保存虚拟地址和物理地址映射关系的缓存

  • LRU:Least Recently Used :内存保存数据的算法,被叫做近期最少使用算法,用于释放内存,它的工作原理就是把最新使用的数据存放到内存空间靠前的位置。

    比如说一个数据存入内存,如果内存中已经存在此数据,则把它的位置提前到内存空间起始位置,如果没有,则存入,并把内存空间终止位置保存的的数据给丢弃(类似堆栈)。

1.4. 用户和内核空间

系统进程基础插图1

1.5. 进程的基本状态和转换

系统进程基础插图2

1.6. 进程的基本状态

  1. 创建状态:进程在创建时需要申请一个空白PCB(process control block进程控制块),向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把此时进程所处状态称为创建状态
  2. 就绪状态:进程已准备好,已分配到所需资源,只要分配到CPU就能够立即运行
  3. 执行状态:进程处于就绪状态被调度后,进程进入执行状态
  4. 阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用
  5. 终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行

1.7. 状态之间转换情况

  1. 运行——>就绪:1,主要是进程占用CPU的时间过长,而系统分配给该进程占用CPU的时间是有限的;2,在采用抢先式优先级调度算法的系统中,当有更高优先级的进程要运行时,该进程就被迫让出CPU,该进程便由执行状态转变为就绪状态
  2. 就绪——>运行:运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配CPU
  3. 运行——>阻塞:正在执行的进程因发生某等待事件而无法执行,则进程由执行状态变为阻塞状态,如发生了I/O请求
  4. 阻塞——>就绪:进程所等待的事件已经发生,就进入就绪队列
  • 以下两种状态是不可能发生的:
  1. 阻塞——>运行:即使给阻塞进程分配CPU,也无法执行,操作系统在进行调 度时不会从阻塞队列进行挑选,而是从就绪队列中选取
  2. 就绪——>阻塞:就绪态根本就没有执行,谈不上进入阻塞态

2. IPC进程间通信

IPC: Inter Process Communication

2.1. 同一主机:

pipe 管道
socket 套接字文件
signal 信号
shm shared memory
semaphore 信号量,一种计数器

2.2. 不同主机:

socket IP和端口号
RPC remote procedure call
MQ 消息队列,如:Kafka,RabbitM Q,ActiveMQ

  • 单一主机通讯用socket文件,全双工;跨网络通讯用socket套接字协议。

2.3. 进程优先级

系统进程基础插图3 系统进程基础插图4

  • 系统优先级:数字越小,优先级越高
    0-139:各有140个运行队列和过期队列
    • 实时优先级: 99-0 值最大优先级最高
    • nice值:-20到19,对应系统优先级100-139
  • Big O:时间复杂度,用时和规模的关系
    O(1), O(logn), O(n)线性, O(n^2)抛物线, O(2^n)

O(1)比较优先级大小的方式:

  1. 通过140个编号的优先级队列以及140个过时优先级队列,将优先级编号相同的进程放在对应的优先级栈中(一个优先级栈可以放多个进程,从左往右执行),然后从最小值(最高优先级)的队列开始执行。
  2. 当时间片到而此运行队列中的正在执行的进程没有执行完毕时,便会保存当前进程状态并将此进程放入相同优先级编号过期队列中,然后继续执行当前优先级队列中的剩余进程(一个进程在时间片内执行完了就释放,没有执行完同样放入过期优先级队列中),直到此队列的所有进程全部执行一遍,将此队列清空
  3. 此时查看此队列相同编号的过时优先级队列,里面如果有进程,则将此队列的与过期优先级队列互换身份,此运行队列变成过期优先级队列,而过期优先级队列变成正在执行的运行队列。然后重复2中步骤直到此队列的所有进程全部执行完毕并且释放
  4. 接下来就是执行下一个最高优先级队列里面的进程了,重复1-4步骤。

2.4. Linux内核:抢占式多任务

2.5. 进程类型:

  • 守护进程: daemon,在系统引导过程中启动的进程,和终端无关进程
  • 前台进程:跟终端相关,通过终端启动的进程
  • 后台进程:跟终端相关,通过终端启动的进程,但是在终端的后台运行;注意后台进程当终端关闭后也同样会关闭,它和守护进程并不相同。
    注意:两者可相互转化

2.6. 进程状态:

  • 运行态:running
  • 就绪态:ready
  • 睡眠态:
    • 可中断:interruptable :可中断睡眠状态是系统中进程最多的状态
    • 不可中断:uninterruptable
  • 停止态:stopped,暂停于内存,但不会被调度,除非手动启动
  • 僵死态:zombie,结束进程,父进程结束前,子进程不关闭

注意僵死态的进程已经结束了,但是仍然占用部分资源,kill命令无法再次关闭它,最好的方法就是杀掉父进程或者重启系统。

2.7. 进程的分类:

CPU-Bound:CPU密集型,非交互 :比如编译 IO-Bound:IO密集型,交互 :网络吞吐,磁盘读写

最后修改日期: 2021年7月7日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。