【消息队列+信号量】System V通信{了解消息队列和信号量的原理}

在这里插入图片描述

1.引入概念

  1. 基于对共享内存的理解
    为了让进程间通信 ⇒ 让不同的进程之间看到同一份资源 ⇒ 之前讲的所有的通信方式(匿名/命名管道 | 共享内存)本质都是优先解决一个问题: 让不同的进程看到同一份资源
  2. 让不同的进程看到同一份资源,对于共享内存来说,带来了一些时序问题,造成数据不一致问题
  3. 把多个进程(执行流)看到的公共的一份资源称为临界资源;在多个进程之间共享的资源,例如共享内存、文件、网络连接等。由于多个进程同时访问临界资源可能会导致数据竞争和冲突以及数据不一致问题,因此需要使用同步和互斥机制来保护临界资源的访问。
  4. 把自己进程中访问临界资源的代码称为临界区。:访问临界资源的代码段,也就是需要使用同步和互斥机制来保护的代码段。在临界区内,进程需要获取互斥锁或信号量等同步机制,以保证多个进程之间对临界资源的访问的正确性和一致性。临界区通常是指一段代码,而不是指某个具体的资源。
  5. 同步:在多个进程之间协调执行的过程,保证它们按照一定的顺序执行,避免出现竞争和冲突。
  6. 为了更好地保护临界区,可以让多执行流在任何时刻都只能有一个进程进入临界区这个动作称为互斥。设置多个执行流互相运行的时候互相干扰这一行为,主要是解决不加保护的访问同样资源(临界资源)造成的数据不一致问题,在非临界区多个执行流互不影响。在多个进程之间共享资源时,保证它们不会同时访问同一个资源,避免出现数据竞争和冲突。
  7. 要么不做,要么做完,没有中间状态,就称之为原子性

2.理解信号量

  1. 每一个进程想进入临界资源,访问临界资源中的一部分,不能让进程直接去使用临界资源,要申请信号量
  2. 信号量本质是一个计数器。
  3. 申请信号量的本质: 让信号量计数器自减
  4. 申请信号量成功,意味着临界资源内部一定预留了用户想要的资源【申请信号量本质是对临界资源的一种 预定 机制】
  5. 通信操作:
    申请信号量 – 计数器自减
    访问临界资源 – 进程执行自己的临界区代码
    释放信号量 – 计数器自增

如何理解信号量?

  1. System V信号量和共享内存一样,也是一种临界资源,用于实现进程之间的同步和互斥。信号量用于表示某个资源的可用数量或状态(计数器)。
  2. 为了避免出现数据竞争和冲突,在多个进程之间共享资源时,它们不能同时访问同一个资源(互斥)。
  3. 每个进程想访问临界资源时,都不能直接访问,必须申请信号量。
  4. 只要申请信号量成功,临界资源的内部一定会预留相应的资源。
  5. 访问结束后,必须释放信号量。申请信号量的本质是对临界资源的一种预定机制。

进程可以通过对信号量进行P操作和V操作来实现信号量的申请和释放

P操作:申请信号量,会将信号量的值-1,如果信号量的值小于0,则进程会被阻塞,直到信号量的值变为正数。
V操作:释放信号量,会将信号量的值+1,如果有进程因为等待信号量而被阻塞,则会唤醒其中一个进程。

信号量可以设置不同的初始值,以适应不同的应用场景。信号量可以设置不同的权限,以控制进程对信号量的访问。

System V信号量的使用

semget函数创建一个新的信号量,返回一个信号量的标识符。
semctl函数初始化信号量的值和权限。
semop函数对信号量进行P操作和V操作,实现进程间的同步和互斥。
semctl函数删除信号量,释放系统资源。

整数能不能标识信号量?

情景:让多个进程(整数n在共享内存里)看到同一个全局变量,大家都进行申请信号量即计数器自减

了解计算机执行“运算”这一行为的机理

  1. 计算操作在CPU 数据存放在内存
  2. CPU执行指令:
    将内存中的数据加载到cpu内的寄存器中(读指令)
    执行运算行为n--(分析&&执行指令)
    将CPU修改完毕的n写回内存(写回结果)
  3. 执行流在执行的时候,任何时刻都可能被切换
  4. 寄存器只有一套,被所有的执行流共享,寄存器里面的数据属于每一个执行流,属于该执行流的上下文数据。没当进程被替换,都要进行上下文保护。再次执行时要进行上下文恢复即将数据放回去再拿出来的行为。
  5. 因为时序问题导致n有中间状态 ⇒ 可能导致数据不一致 ⇒ 不安全
  6. 如果一个运算操作只有一行汇编(一条指令),该操作是原子的。不存在安全问题,也就不用考虑那么多。实际上一个简单的运算总是由多条指令执行的。

什么是中间状态?

比如A进程对 n=10执行了 n-=2 此时n=8; n=8还未写回内存(中间状态),由于某种原因A被切换,B进程对n执行了n-5操作并顺利写回。此时内存中的n=5;A进程此时再次执行,将n=8写回内存。n在正确的角度上看现在应该是n-2-5=3;但此时内存中的n=8 ⇒ 数据不一致。

信号量用于实现进程之间的同步和互斥。信号量也是一种临界资源,在使用时同样存在数据冲突、一致性等问题。谁来保证信号量的安全性呢?⇒ 原子性操作

在进程间通信中,原子性操作是指一个操作不可被中断地执行,要么全部执行成功,要么全部不执行。原子性操作通常用于保证多个进程之间的数据访问的正确性和一致性。

常见的原子性操作

  1. 原子性读写操作:例如原子性读取和写入一个整数值,可以使用原子性操作来保证多个进程之间对该整数值的读写操作的正确性。
  2. 原子性加减操作:例如原子性地对一个计数器进行加减操作,可以使用原子性操作来保证多个进程之间对该计数器的访问的正确性。
  3. 原子性比较交换操作:例如原子性地比较两个整数值的大小,并根据比较结果交换它们的值,可以使用原子性操作来保证多个进程之间对这两个整数值的访问的正确性。

3.信号量计数器

信号量计数器 ⇒ 是对临界资源的预定机制
申请信号量 ⇒ 计数器自减 ⇒ P操作 ⇒ 必须是原子的
释放信号量 ⇒ 计数器自增 ⇒ V操作 ⇒ 必须是原子

  1. 信号量的P, V操作是原子性加减操作。
  2. 保证多个进程之间对信号量的访问的正确性和一致性。
  3. 当多个进程同时对信号量进行P、V操作时,操作会被依次执行,保证了操作的顺序性(同步)
  4. P、V操作是不可中断的,要么全部执行成功,要么全部不执行(互斥),保证了操作的原子性。

4.消息队列

4.1了解即可

System V消息队列是由AT&T公司开发的一种IPC机制,可以在不同进程之间传递消息。

System V消息队列的特点

一个消息链表,每个消息包括类型+数据
可以被多个进程同时访问,进程可以向队列中写入/读取消息
可以设置不同的权限以控制进程对队列的访问。
可以设置不同的优先级,以控制消息的发送和接收顺序。
可以设置不同的大小,以适应不同的应用场景。

System V消息队列的使用

msgget函数创建一个新的消息队列,返回一个消息队列的标识符。
msgsnd函数向消息队列中发送消息,指定消息类型和数据部分。
msgrcv函数从消息队列中接收消息,指定消息类型和数据部分。
msgctl函数删除消息队列,释放系统资源。

4.2一些命令

  1. ipcs命令:显示系统中的IPC资源
    ipcs -m:显示共享内存信息
    ipcs -q:显示消息队列信息
    ipcs -s:显示信号量信息
  2. ipcrm命令:删除系统中的IPC资源
    ipcrm -m:删除共享内存
    ipcrm -q:删除消息队列
    ipcrm -s:删除信号量
  3. msgctl命令:用于控制消息队列
    msgctl -q:获取消息队列的状态
    msgctl -Q:列出所有消息队列的状态
    msgctl -r:删除消息队列
  4. shmctl命令:用于控制共享内存
    shmctl -m:获取共享内存的状态
    shmctl -a:列出所有共享内存的状态
    shmctl -r:删除共享内存
  5. semctl命令:用于控制信号量
    semctl -s:获取信号量的状态
    semctl -a:列出所有信号量的状态
    semctl -r:删除信号量

5.IPC总结

之前讲到的所有方式【pipe/shm/msq/sem】实际上不是进程通信,更准确的来说是给【不同进程看到同一份资源】提供了很多方式,让不同进程能够进行通信,至于怎么通信,交流什么数据是进程的事,之前讲的只不过是,能够让他们通信。

  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿猿收手吧!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值