0


C++多进程

多进程与多线程

  • 多进程并发

使用多进程并发是将一个应用程序划分为多个独立的进程(每个进程只有一个线程),这些独立的进程间可以互相通信,共同完成任务。由于操作系统对进程提供了大量的保护机制,以避免一个进程修改了另一个进程的数据,使用多进程比多线程更容易写出安全的代码。但是这也造就了多进程并发的两个缺点:

  1. 在进程间的通信,无论是使用信号、套接字,还是文件、管道等方式,其使用要么比较复杂,要么就是速度较慢或者两者兼而有之。
  2. 运行多个进程的开销很大,操作系统要分配很多的资源来对这些进程进行管理。

由于多个进程并发完成同一个任务时,不可避免的是:操作同一个数据和进程间的相互通信,上述的两个缺点也就决定了多进程的并发不是一个好的选择。

  • 多线程并发

多线程并发指的是在同一个进程中执行多个线程。

优点

有操作系统相关知识的应该知道,线程是轻量级的进程,每个线程可以独立的运行不同的指令序列,但是线程不独立的拥有资源,依赖于创建它的进程而存在。也就是说,同一进程中的多个线程共享相同的地址空间,可以访问进程中的大部分数据,指针和引用可以在线程间进行传递。这样,同一进程内的多个线程能够很方便的进行数据共享以及通信,也就比进程更适用于并发操作。

缺点

由于缺少操作系统提供的保护机制,在多线程共享数据及通信时,就需要程序员做更多的工作以保证对共享数据段的操作是以预想的操作顺序进行的,并且要极力的避免死锁(deadlock)。

进程间通信

进程间通信:管道pipe、有名管道、消息队列MessageQueue、共享内存SharedMemory、信号量Semaphore、信号sinal、套接字socket。

管道:

管道,通常指无名管道,管道是最简单,效率最差的一种通信方式,不适合进程间频繁的交换数据。

  1. 是一种半双工的通信方式;
  2. 只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系;
  3. 它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

有名管道FIFO

  1. FIFO可以在无关的进程之间交换数据,与无名管道不同;
  2. FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。

消息队列

消息队列,是消息的链接表,存放在内核之中。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

  1. 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级;
  2. 消息队列是独立于发送和接收进程的,进程终止时,消息队列及其内容并不会被删除;
  3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。

共享内存:

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。

共享内存解决了消息队列存在的内核态和用户态之间数据拷贝的问题。

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

信号量

信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段

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

信号

信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

信号的处理有三种方法,分别是:忽略、捕捉和默认动作。

  • 忽略信号,大多数信号可以使用这个方式来处理,但是有两种信号不能被忽略(分别是 SIGKILL和SIGSTOP);
  • 捕捉信号,需要告诉内核,用户希望如何处理某一种信号,说白了就是写一个信号处理函数,然后将这个函数告诉内核。当该信号产生时,由内核来调用用户自定义的函数,以此来实现某种信号的处理。
  • 系统默认动作,对于每个信号来说,系统都对应由默认的处理动作,当发生了该信号,系统会自动执行。具体的信号默认动作可以使用man 7 signal来查看系统的具体定义。

信号处理函数的注册:

  1. 入门版:函数signal
  2. 高级版:函数sigaction

信号处理发送函数:

  1. 入门版:kill
  2. 高级版:sigqueue

套接字

套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

进程间通信方式总结:

  1. 管道:速度慢,容量有限,只有父子进程能通讯;
  2. 有名管道FIFO:任何进程间都能通讯,但速度慢;
  3. 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题;
  4. 共享内存:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题;
  5. 信号:有入门版和高级版两种,区别在于入门版注重动作,高级版可以传递消息。只有在父子进程或者是共享内存中,才可以发送字符串消息;
  6. 信号量:不能传递复杂消息,只能用来同步。用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
标签: c++

本文转载自: https://blog.csdn.net/qq_45780653/article/details/130915214
版权归原作者 逆风路途 所有, 如有侵权,请联系我们删除。

“C++多进程”的评论:

还没有评论