进程
基本概念
进程的概念
- 进程是正在运行的程序的实例。是一个具有一定独立功能的程序关于某个数据集合的一次运行活动
- 它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
- 可以用一个程序来创建多个进程,进程是由内核定义的抽象实体,并为该实体分配用以执行程序的各项系统资源
并行和并发
- 并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。
- **并发(concurrency)😗*指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
进程的状态
- 运行态:进程占有处理器正在运行
- 就绪态:进程具备运行条件,等待系统分配处理器以便运行。当进程已分配到除CPU以外的所有必要资源后,只要再获得CPU,便可立即执行。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列
- 阻塞态:又称为等待(wait)态或睡眠(sleep)态,指进程不具备运行条件,正在等待某个事件的完成
- 新建态:进程刚被创建时的状态,尚未进入就绪队列
- 终止态:进程完成任务到达正常结束点,或出现无法克服的错误而异常终止,或被操作系统及有终止权的进程所终止时所处的状态。进入终止态的进程以后不再执行,但依然保留在操作系统中等待善后。一旦其他进程完成了对终止态进程的信息抽取之后,操作系统将删除该进程。
进程创建
系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型。系统会规定进程数量的上限。
每个进程都会有一个虚拟地址空间。内核不复制整个进程的地址空间,而是让父子进程共享一个地址空间。在需要写入时复制地址空间。
资源的复制在写入时进行,此外都是以只读的方式共享。
孤儿进程
父进程运行结束,但子进程还在运行(未运行结束)。
僵尸进程
进程终止时,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。
进程间通信
概念
不同进程(这里所说的进程通常指的是用户进程)之间的资源是独立的,没有关联,不能在一个进程中直接访问另一个进程的资源。但是,进程不是孤立的,不同的进程需要进行信息的交互和状态的传递等,因此需要进程间通信( IPC: InterProcesses Communication ).
进程间通信的目的:
- 数据传输:一个进程需要将它的数据发送给另一个进程。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 资源共享:多个进程之间共享同样的资源。为了做到这一点,需要内核提供互斥和同步机制。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
进程间通信的方式
匿名管道(管道)
管道也叫无名(匿名)管道,它是是UNIX系统IPC(进程间通信)的最古老形式,所有的UNIX系统都支持这种通信机制。
- 管道其实是一个在内核内存中维护的缓冲器,这个缓冲器的存储能力是有限的,不同的操作系统大小不一定相同。
- 管道拥有文件的特质:读操作、写操作,匿名管道没有文件实体,有名管道有文件实体,但不存储数据。可以按照操作文件的方式对管道进行操作。
- 一个管道是一个字节流,使用管道时不存在消息或者消息边界的概念,从管道读取数据的进程可以读取任意大小的数据块,而不管写入进程写入管道的数据块的大小是多少。
- 通过管道传递的数据是顺序的,从管道中读取出来的字节的顺序和它们被写入管道的顺序是完全一样的。。在管道中的数据的传递方向是单向的,一端用于写入,一端用于读取,管道是半双工的。
- 从管道读数据是一次性操作,数据一旦被读走,它就从管道中被抛弃,释放空间以便写更多的数据,在管道中无法使用Iseek()来随机的访问数据。
- 匿名管道只能在具有公共祖先的进程(父进程与子进程,或者两个兄弟进程,具有亲缘关系)之间使用。
有名管道(命名管道)
1.为了克服匿名管道没有名字,只能用于亲缘关系的进程间通信缺点,提出了有名管道(FIFO),也叫命名管道、FIFO文件。
⒉有名管道(FIFO)不同于匿名管道之处在于它以FIFO的文件形式存在于文件系统中,并且其打开方式与打开一个普通文件是一样的。这样即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信,因此,通过FIFO不相关的进程也能交换数据。
3.与管道一样,FIFO也有一个写入端和读取端,并且从管道中读取数据的顺序与写入的顺序是一样的。FIFO的名称也由此而来:先入先出。
4.有名管道(FIFO)和匿名管道(pipe)有一些特点是相同的,不一样的地方在于
- FIFO在文件系统中作为一个特殊文件存在,但FIFO中的内容却存放在内存中
- 当使用FIFO 的进程退出后,FIFO文件将继续保存在文件系统中以便以后使用
- FIFO有名字,不相关的进程可以通过打开有名管道进行通信。
内存映射
内存映射(Memory-mapped lO)是将磁盘文件的数据映射到内存,用户通过修改内存就能修改磁盘文件。
信号
信号是Linux进程间通信的最古老的方式之一,是事件发生时对进程的通知机制,有时也称之为软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。信号通常源于内核,引发内核产生信号的事件有:
- 对于前台进程,用户可以通过输入特殊的终端字符来给它发送信号。比如输入Ctrl+C通常会给进程发送一个中断信号。
- 硬件发生异常,即硬件检测到一个错误条件并通知内核,随即再由内核发送相应信号给相关进程。比如执行一条异常的机器语言指令,诸如被0除,或者引用了无法访问的内存区域。
- 系统状态变化,比如alarm定时器到期将引起SIGALRM信号,进程执行的CPU时间超限,或者该进程的某个子进程退出。
- 运行kill命令或调用kill函数。
信号的特点
- 简单
- 不能携带大量信息
- 满足某个特定条件才发送
- 优先级比较高
信号的几种状态
- 产生
- 未决
- 递达
信号的处理动作
- 终止进程
- 进程忽略信号
- 终止进程并产生Core文件
- 暂停进程
- 继续执行被暂停的进程
共享内存
两个或多个进程共享物理内存的同一块区域(通常为 段 )。这种IPC机制无须内核介入。这段数据对其他所有共享一个段的进程可用。
与管道等要求发送进程将数据从用户空间的缓冲区复制进内核内存和接收进程将数据从内核内存复制进用户空间的缓冲区的做法相比,这种IPC技术的速度更快。
进程调度
- 何时调度(调度的时机)
- 是否能够在内核执行的任意位置进行调度(调度的方式)
- 如果完成进程切换(上下文切换)
- 如果选择“合适”的进程执行(调度策略/调度算法)
- 如果评价选择的合理性(进程调度的指标)
调度的类型
- 作业调度–高级调度
将外部存储中处于后备队列中的哪些作业调入内存,处于内存的就绪队列,准备执行。 - 进程调度–低级调度
决定就绪队列中那个进程将获得处理机 - 交换调度–中级调度
目的是提高内存的利用率和系统的吞吐量