基本概念(熟记)
1.并发:一段时间内有多个进程执行,可以一个或者多个CPU
2.并行:一个时刻有多个进程执行,必须多个CPU
3.中断(外部中断):来自于外设,来自不同的硬件设备的计时器和网络的中断,处理时间是异步的()
4.异常:来源于不良的应用程序,非法指令或者其他坏的处理状态。像地址越界,算数溢出等,处理时间是同步的。
5.系统调用:来源于应用程序,应用程序主动向操作系统发出服务请求。
6.同步:在发出一个同步调用的时候,在没有得到结果之前就不会返回。那么对于发起调用的进程来说,在完成这个调用之前,它接下来的事情就不能进行,换句话说,就是必须一件一件做,等前一件做完了才能做下一件事。
7.异步:当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知、和回调函数来通知调用者。这里的重点是在调用完成后会通过一种机制来告诉调用者,并且发起调用的进程仍然可以做其他事情。
8.阻塞:一个进程被阻塞的时候,从cpu的角度来说就是要发生上下文切换,那么这个被阻塞的进程就不能被继续执行下去,把cpu让出来给别的进程,这个进程被挂起,直到得到结果才会返回。
9.非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
进程
进程的定义
进程是资源分配的基本单位,运行一个可执行程序会创建一个或多个进程,进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行过程
进程的组成
包含了正在运行的一个程序的所有状态信息
1.程序的代码
2.程序处理的数据
3.程序计数器中的值,指示下一条将运行的指令
4.一组通用的寄存器的当前值,堆,栈;
5.一组系统资源(如打开的文件)
进程和程序
1.程序是产生进程的基础,进程是动态的,程序是静态的,进程是暂时的,程序是永久的,进程是一个状态变化的过程,程序可以永久保存。
2.程序的每次运行构成不同的进程
3.进程是程序功能的体现
4.通过多次执行,一个进程可对应多个进程,通过调用关系,一个进程可包括多个程序。
5.进程组成包括程序,数据和进程控制块(PCB)
进程控制结构
进程控制块:操作系统管理控制进程所用的信息集合,OS用PCB来表述进程的基本情况和运行变化的过程,PCB也是进程存在的唯一标志。
1.使用进程控制块:进程创建生成一个PCB,进程终止回收它的PCB,通过对PCB管理实现进程的管理
2.PCB包含信息:1,进程标识信息:本进程的标识,用户标识 2.进程控制和管理信息:进程当前状态,进程优先级 3.CPU相关信息,CPU中各个寄存器的值等
3.PCB的组织方式:1,链表:统一状态的进程其PCB组成一个链表,多个状态对应不同的链表。 就绪链表:所有处于就绪状态的进程链接在一起 2,索引表:
进程状态变化
参考小林coding公众号,图解系统中的图。
三种状态:
1.运行态:该进程时刻占用CPU
2.就绪态:可运行,但是由于其他进程正在运行而暂时停止运行
3.阻塞态:该进程正在等待某一个事件的发生而暂时停止运行,必须等待事件结束才能转入就绪态完整的状态变化
有几个需要说明的点:
1.有大量阻塞状态的时候需要将阻塞状态的进程的物理内存空间换出到硬盘,等再次调用的时候从硬盘换入到物理内存。
2.挂起状态:**描述进程没有占用实际的物理内存的情况,**区别在于阻塞状态需要等待某个事件返回。分为阻塞挂起:进程在外存并等待某个事件出现,就绪挂起:进程在外存,但只要进入内存,立即运行。
3.进程挂起的原因:
- 进程使用的内存空间不在物理内存
- 通过sleep让进程间歇性挂起,其工作原理是设置一个定时器,到期后唤醒
- 用户希望挂起一个程序的执行,比如在LINUX中用ctrl+z挂起进程
进程的切换
1.首先要知道进程的切换发生在内核态,因为进程是由内核来管理和调度的。
2.进程切换包括虚拟内存、栈,全部变量等用户空间的资源,也包括内存堆栈,寄存器等内核空间的资源。
3.当某个进程的时间片用完,进程在系统资源不足时,进程通过睡眠函数sleep将自己主动挂起时,当有更高优先级的进程时等等都会发生进程切换。
三个特殊的进程
守护进程
在后台运行的,没有控制终端与之相连的进程。它独立于控制终端,周期性地执行某种任务。创建守护进程时有意把父进程结束,然后被1号进程init
收养。
僵尸进程
一个正常运行的子进程,如果此刻子进程退出,父进程没有及时调用wait
或waitpid
收回子进程的系统资源,该子进程就是僵尸进程。其实就是完成进程完成工作后应该被正常销毁,释放它占用的内存资源,但此时这个进程的资源没有被回收,就变成了僵尸进程。
孤儿进程
如果一个正常运行的子进程,父进程退出了但是子进程还在,该进程此刻是孤儿进程,被init
收养。
进程间通信
首先要知道进程的用户地址空间都是独立地,但是内核空间都是每个进程所共享的,所以进程通信需要通过内核。
1.管道:就是内核里面的一段缓存,进行单向的数据传输,想要通信,必须创建两个管道,管道的通信方式效率低,不适合频繁在进程间交换数据。分为匿名管道和命名管道。匿名管道的通信范围是存在父子关系的进程,因为匿名管道是通过fork
来复制父进程fd
文件描述符,而命名管道可以在不相干的进程之间通信,因为提前创建了一个类型为管道的设备文件,在进程里只要使用这个设备文件,就可以相互通信。LINUX创建管道:makfifo
管道名; |就表示管道,管道写数据: echo data>管道名; 管道读取数据: cat<管道名
2.消息队列:是保存在内核中的消息链表,生命周期随内核,在进程间通信的时候,一个进程把数据放在对应的消息队列后就可以正常返回了,另外一个进程再去读取数据;有点像客户端和服务端。但是不适合大数据的传输,而且每次读写数据都会发生内核态和用户态的数据拷贝开销。
3.共享内存:解决了消息队列每次读写都要发生内核态和用户态的数据拷贝过程,实质就是对于不同的进程,拿出一块虚拟地址空间来映射到相同的物理内存中。但是可能在多个进程同时修改同一个共享内存,造成冲突。
4.信号量:主要解决了共享内存存在的多进程竞争共享资源的问题。实质是一个整型计数器,用于实现进程间的互斥和同步。有两种原子操作:P操作和V操作。P操作:将信号量减一,减一后如果信号量<0,表示资源已经被占用,进程需要阻塞等待,如果信号量>=0,表示还有资源可用。V操作:将信号量加1,相加后如果信号量<=0,表明当前有阻塞中的进程,如果信号量>0,表明当前没有阻塞的进程。P用在进入共享资源前,V用在离开共享资源后,这两个操作必须同时出现。每类共享资源设置信号量,初值为1,表示该临界资源未被占用,信号初始化为1代表互斥信号量,初始化为0代表同步信号量 具体参考[小林coding:图解系统]
5.**信号:**通过操作告知某个进程某个事件已经发生。例如Ctrl+C产生SIGINT信号,表示终止该进程,Ctrl+Z产生SIGTSTP信号,表示停止该进程,但还未结束。
6.socket:在不同的主机之间和同一个主机上都可以进行通信的方式。TCP的socket编程模型。参考图解系统,公众号小林coding的图示。
有以下几个过程