• 进程中包括有多个线程,进程与进程之间是相对比较独立的。
  • 进程中有一个逻辑内存,每个进程都会有分配到一个独立的内存空间,还分配了一个文件/网络句柄,
  • 句柄类似一个标识符,所有的进程所或多或少都有一定的句柄数的引用,句柄实际上是一个指针,指向一块包含具体信息数据的内存,所以句柄是当你要访问该进程时取得的,使用完必须释放。(打个比方,我要使用redis需要打开6379端口,这个时候需要访问句柄,获取到内存地址去访问获取对应的资源来执行该进程)
  • 一个进程可以拥有多个句柄数目,但是只有一个进程ID
  • 进程不同时刻所引用的句柄数目是不一定的

     
    进程结构
  • 线程中有一个栈内存(很多人把它称为堆栈),主要用来存储局部变量资源或者内存地址
  • 还有一个PC块,主要是存储下一条执行指令的地址,PC是指向一块共同的内存(进程里面的被系统分配到的逻辑内存)。
  • TCS :ThreadLocalStorage 主要存储线程自己定义的变量,不想和其他线程进行共享,理解为线程的私有变量。
  • 线程共享进程的资源主要有:进程代码块、进程的全局和静态变量、进程打开的文件描述符、信号的处理器、进程当前的目录、进程ID、进程组ID
  • 进程是程序资源分配的最小单位,线程是程序执行的最小单位。
  • 进程有自己的内存地址空间,线程包含在进程的地址空间中。
  • 相对于进程与进程之间线程之间通信方式比较方便,线程能共享进程分配到的逻辑内存的资源。也就是说,同一进程下的线程共享全局变量、静态变量等数据,具体共享的内容1.2中介绍线程已经说明。
  • 进程的分配开销比线程大,但是进程的健壮性比线程高,因为进程间不会互相影响,线程一个挂掉了可能会造成进程崩溃。
  • 也可以这么说,线程是程序执行的单位,进程只是存放线程的容器,容器会提供线程执行的资源。

因为进程与进程之间是相互独立的,所以关于进程之间的通信数据共享复杂,需要用IPC;数据是分开的,同步简单,但是占用内存多,切换复杂,CPU利用率低。

IPC的方式通常有:管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等

管道,通常指无名管道,是 UNIX 系统IPC最古老的形式。

  • 它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
  • 它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
  • 它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中

当一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。如下图:要关闭管道只需将这两个文件描述符关闭即可。

 
管道原型

单个进程中的管道几乎没有任何用处。所以,通常调用 pipe 的进程接着调用 fork,这样就创建了父进程与子进程之间的 IPC 通道。如下图所示:

 
示例

若要数据流从父进程流向子进程,则关闭父进程的读端(fd[0])与子进程的写端(fd[1]);反之,则可以使数据流从子进程流向父进程。

FIFO,也称为命名管道,它是一种文件类型。

  • 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
  • FIFO可以在无关的进程之间交换数据,与无名管道不同。
  • FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中

FIFO的通信方式类似于在进程中使用文件来传输数据,只不过FIFO类型文件同时具有管道的特性。在数据读出时,FIFO管道中同时清除数据,并且“先进先出”。

消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。用户进程可以向消息队列添加消息,也可以向消息队列读取消息。

  • 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级
  • 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除,所以另一个进程读写的时候要判断前进程是否已经读完数据。
  • 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的指定类型读取

信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

  • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存
  • 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作
  • 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数
  • 支持信号量组。

共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。

  • 共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
  • 因为多个进程可以同时操作,所以需要进行同步。
  • 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

1.管道:速度慢,容量有限,只有父子进程能通讯
2.FIFO:任何进程间都能通讯,但速度慢
3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
4.信号量:不能传递复杂消息,只能用来同步
5.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。

作者:浅蓝色的麻吉
链接:https://www.jianshu.com/p/00bd894ff86c
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

版权声明:本文为sandea原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/sandea/p/11777416.html