一、进程通信的方式
(一)管道:
管道分为匿名管道和命名管道,管道本质上是一个内核中的一个缓存,当进程创建管道后会返回两个文件描述符,一个写入端一个输出端。缺点:半双工通信,一个管道只能一个进程写,一个进程读。不适合进程间频繁的交换数据
(二)消息队列:
可以边发边收,但是每个消息体都有最大长度限制,队列所包含的消息体的总数量也有上限并且在通信过程中存在用户态和内核态之间的数据拷贝问题
(三)共享内存:
解决了消息队列存在的内核态和用户态之间的数据拷贝问题。
信号量:进程通信和线程通信都好用的通信方式
本质上是一个计数器,当使用共享内存的通信方式时,如果有多个进程同时往共享内存中写入数据,有可能先写的进程的内容被其他进程覆盖了,信号量就用于实现进程间的互斥和同步PV操作不限于信号量+-1,而且可以任意加减正整数(
P操作(Wait/Proberen)
P操作通常被称为“等待”操作。当一个线程执行P操作时,它会检查信号量的值。如果信号量的值大于0,线程可以继续执行,并将信号量的值减1。如果信号量的值为0,则线程被阻塞,直到信号量的值变为非0。
V操作(Signal/Verhogen)
V操作通常被称为“信号”操作。当一个线程完成对共享资源的访问或完成某项任务后,它会执行V操作,将信号量的值加1。如果有其他线程因等待该信号量而被阻塞,其中一个线程将被唤醒并继续执行。
使用场景
P和V操作通常用于控制对共享资源的访问,确保资源的同步和互斥。例如,在生产者-消费者问题中,P和V操作可以用来控制对缓冲区的访问,确保生产者不会在缓冲区满时写入数据,消费者不会在缓冲区空时读取数据。)
(四)信号
#include <iostream>
#include <signal.h>
#include <unistd.h>
void handler(int signum) {
std::cout << "Signal received: " << signum << std::endl;
}
int main() {
signal(SIGINT, handler); // 注册信号处理函数
std::cout << "Press Ctrl+C to send SIGINT" << std::endl;
while (true) {
sleep(1); // 保持程序运行
}
return 0;
}
(五)套接字
二、线程通信的方式
(一)信号量:
进程通信和线程通信都好用的通信方式。
(二)条件变量+互斥量:
条件变量:利用线程间共享的全局变量进行同步的一种机制,概括来说就是一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”而发出信号。消费者们等生产者们生产出产品来才可以排队使用。
互斥量:访问一个互斥量时对其进行加锁,让其他请求该互斥量的线程阻塞。使用完后进行释放,阻塞中的线程开始活动,最先活动的线程加锁,重复上述使用过程。