1.进程的概念

进程是系统进行资源分配和调度的基本单位,线程是CPU调度和分派的基本单位。

程序:是静态的,就是一个存放在磁盘里的可执行文件,就是一系列的指令集合。
进程:是动态的,是程序的一次执行过程。

2.进程的组成

当进程被创建时,操作系统会为该进程分配一个唯一的,不重复的“身份证号”—PID(Process ID,进程ID)

进程控制块PCB

2.1 进程概论 - 图1PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB。

2.1 进程概论 - 图2PCB是给操作系统的。
数据段和程序块是给进程自己使用的。与进程自身的运行逻辑有关。

知识滚雪球:程序是如何运行的?

image.png
重点理解:进程在内存中的运作。

3.进程的特征

2.1 进程概论 - 图4

4.进程的状态与转换

进程状态分类

创建状态 (New,又称之为:新建态)

进程正在被创建,操作系统为进程分配资源,初始化PCB。

就绪状态

已经具备运行条件,但由于没有空闲CPU,而暂时不能运行。
image.png

运行状态

占有CPU,并在上搞事情运行。
如果一个进程此时在CPU上运行,那么这个进程处于“运行态”。
image.png

阻塞状态

等待被调度的状态,因等待某一件事而暂时不能运行。

在进程运行的过程中,可能会请求等待某个事件的发生(如等待某种系统资源的分配,或者等待其他进程的响应)。在这个事件发生之前,进程无法继续往下执行,此时操作系统会让这个进程暂时释放CPU,并让他进入“阻塞态”。当CPU空闲时,又会选择另一个“继续态”进程上CPU执行。

终止状态

对于进程来讲,可以执行exit系统调用,请求操作系统终止该进程。此时该进程会进入“终止态”,操作系统会让该进程下CPU,并回收内存空间等资源,最后还要回收该进程的PCB。

进程状态间的转换

2.1 进程概论 - 图7
需要注意:

  • 只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
  • 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。

    5.进程的组织

    6.进程控制

7.进程通信

进程通信的概念

进程通信就是指进程之间的信息交换。
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。
为了安全起见,一个进程不能直接访问另一个进程的地址空间。

  1. 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为**进程间通信(IPCInterProcess Communication)**<br />**![](https://cdn.nlark.com/yuque/0/2020/webp/177460/1590071129312-636fb1f9-0795-459a-8f60-d01bf1ed714e.webp#align=left&display=inline&height=181&margin=%5Bobject%20Object%5D&originHeight=181&originWidth=222&size=0&status=done&style=none&width=222)

进程通信的方式

7.1 共享存储

两个进程对共享空间的访问必须是互斥的(操作系统只负责提供共享空间和同步互斥操作工具,如P,V操作)

为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大提高效率。

不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内存连接到他们自己的地址空间中,所有的进程都可以访问共享内存中的地址。如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。

共享内存的通信原理

在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(Addr Space),并且都有一个与之对应的页表,负责将进程的虚拟地址与物理地址进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存。
2.1 进程概论 - 图8
当两个进程通过页表将虚拟地址映射到物理地址时,在物理地址中有一块共同的内存区,即共享内存,这块内存可以被两个进程同时看到。这样当一个进程进行写操作,另一个进程读操作就可以实现进程间通信。但是,我们要确保一个进程在写的时候不能被读,因此我们使用信号量来实现同步与互斥。

对于一个共享内存,实现采用的是引用计数的原理,当进程脱离共享存储区后,计数器减一,挂架成功时,计数器加一,只有当计数器变为零时,才能被删除。当进程终止时,它所附加的共享存储区都会自动脱离。

7.2 管道/匿名管道通信(pipe)

管道:可以理解为用于连接读写进程的一个共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的缓冲区。在Linux 中,管道大小等于内存页面的大小,4KB。
2.1 进程概论 - 图9

  • 管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同事通信,则需要设置两个管道。
  • 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)
  • 各个进程要互斥地访问管道。
  • 数据以字符流的形式写入管道,当管道写满时,写进程的write()系统调用将被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时读进程的read()系统调用将被阻塞。
  • 如果没写满,就不允许读。如果没读空,就不允许写。
  • 数据一旦读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能就会有读错数据的情况。
  • 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

    管道的实质

  • 管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据,管道一端的进程顺序的将数据写入缓冲区,另一端的进程则顺序的读出数据。

  • 该缓冲区可以看做是一个循环队列,读和写的位置都是自动增长的,不能随意改变,一个数据只能被读一次,读出来以后在缓冲区就不复存在了。
  • 当缓冲区读空或者写满时,有一定的规则控制相应的读进程或者写进程进入等待队列,当空的缓冲区有新数据写入或者满的缓冲区有数据读出来时,就唤醒等待队列中的进程继续读写。

    管道的局限

    管道的主要局限性正体现在它的特点上:

  • [x] 只支持单向数据流

  • 只能用于具有亲缘关系的进程之间;
  • 没有名字
  • 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);
  • [x] 管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等;

    7.3 有名管道(FIFO)

    匿名管道,由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道(FIFO)。
    提供了一个路径名与之关联,以有名管道的文件形式存在于文件系统中,这样,即使与有名管道的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过有名管道相互通信.

    有名管道严格遵循
    先进先出(first in first out),对匿名管道及有名管道的读总是从开始处返回数据,对它们的写则把数据添加到末尾。
    有名管道的名字存在于文件系统中,内容存放在内存中。

    匿名管道和有名管道总结

  • [x] 无名管道阻塞问题:无名管道无需显示打开,创建时直接返回文件描述符,在读写时需要确定对方的存在,否则将退出。如果当前进程向无名管道的一端写数据,必须确定另一端有某一进程。如果写入无名管道的数据超过其最大值,写操作将阻塞,如果管道中没有数据,读操作将阻塞,如果管道发现另一端断开,将自动退出。

  • 有名管道阻塞问题:有名管道在打开时需要确实对方的存在,否则将阻塞。即以读方式打开某管道,在此之前必须一个进程以写方式打开管道,否则阻塞。此外,可以以读写(O_RDWR)模式打开有名管道,即当前进程读,当前进程写,不会阻塞。

7.4 信号

7.5 消息队列

7.6 信号量机制

7.6.1 信号量概念

2.1 进程概论 - 图10

7.6.2 生产者与消费者问题

image.png
image.png

7.6.3 PV操作理解死锁的产生条件

image.png

7.7.套接字

8.进程互斥

2.1 进程概论 - 图14 我们把一个时间段内只允许一个进程使用的资源称之为临界资源。
对临界资源的访问,必须互斥地进行。互斥,亦称间接制约关系。进程互斥指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当前访问临界资源的进程访问结束,释放该资源之后,另一个进程才能去访问临界资源。
临界区是进程中访问临界资源的代码段。

8.1进程互斥的软件实现方式

8.2进程互斥的硬件实现方式

引用

进程间通信IPC (InterProcess Communication)
进程间通信——共享内存(Shared Memory)