0
点赞
收藏
分享

微信扫一扫

进程间通信

未定义变量 2021-09-25 阅读 77
Linux

管道

最传统的模型就是软件开发的瀑布模型,其实就是将整个软件开发过程分成多个阶段,往往是上一个阶段完全做完,才将输出结果交给下一个阶段。

管道是一种单向传输数据的机制,它其实是一段缓存,里面的数据只能从一端写入,从另一端读出。如果想互相通信,我们需要创建两个管道才行。

管道需要通过mkfifo命令显式地创建

mkfifo hello

hello就是这个管道的名称。管道以文件的形式存在,这也符合Linux里面一切皆文件的原则。
我们可以往管道里面写入东西

# echo "hello world" > hello

管道里面的内容没有被读出,这个命令就是停在这里的,这说明当一个项目组要把它的输出交接给另一个项目组做输入。

所以我们就需要重新连接一个终端。在终端中,用下面的命令读取管道里面的内容:

# cat < hello 
hello world

管道里面的内容被读取出来,打印到了终端上;另一方面,echo那个命令正常退出了,也即交接完毕,前一个项目组就完成了使命,可以解散了。

消息队列

和管道将信息一股脑儿地从一个进程,倒给另一个进程不同,消息队列有点儿像邮件,发送数据时,会分成一个一个独立的数据单元,也就是消息体,每个消息体都是固定大小的存储块,在字节流上不连续。

  1. 创建一个消息队列,使用msgget函数。这个函数需要有一个参数key,这是消息队列的唯一标识,应该是唯一的。
  2. 发送消息主要调用msgsnd函数。第一个参数是message queue的id,第二个参数是消息的结构体,第三个参数是消息的长度,最后一个参数是flag。
  3. 收消息主要调用msgrcv函数,第一个参数是message queue的id,第二个参数是消息的结构体,第三个参数是可接受的最大长度,第四个参数是消息类型,最后一个参数是flag

共享内存

可以看出来,共享会议室这种模型,类似进程间通信的共享内存模型。前面咱们讲内存管理的时候,知道每个进程都有自己独立的虚拟内存空间,不同的进程的虚拟内存空间映射到不同的物理内存中去。这个进程访问A地址和另一个进程访问A地址,其实访问的是不同的物理内存地址,对于数据的增删查改互不影响。

但是,咱们是不是可以变通一下,拿出一块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西,另外一个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去。

信号量

这里你是不是有一个疑问,如果两个进程attach同一个共享内存,大家都往里面写东西,很有可能就冲突了。例如两个进程都同时写一个地址,那先写的那个进程会发现内容被别人覆盖了。

所以,这里就需要一种保护机制,使得同一个共享的资源,同时只能被一个进程访问。在System V IPC进程间通信机制体系中,早就想好了应对办法,就是信号量(Semaphore)。因此,信号量和共享内存往往要配合使用

信号量其实是一个计数器,主要用于实现进程间的互斥与同步,而不是用于存储进程间通信数据

对于信号量来讲,会定义两种原子操作,一个是P操作,我们称为申请资源操作。这个操作会申请将信号量的数值减去N,表示这些数量被他申请使用了,其他人不能用了。另一个是V操作,我们称为归还资源操作,这个操作会申请将信号量加上M,表示这些数量已经还给信号量了,其他人可以使用了。

信号

对应到操作系统中,就是信号。信号没有特别复杂的数据结构,就是用一个代号一样的数字。Linux提供了几十种信号,分别代表不同的意义。信号之间依靠它们的值来区分。这就像咱们看警匪片,对于紧急的行动,都是说,“1号作战任务”开始执行,警察就开始行动了。情况紧急,不能啰里啰嗦了。

信号可以在任何时候发送给某一进程,进程需要为这个信号配置信号处理函数。当某个信号发生的时候,就默认执行这个函数就可以了。这就相当于咱们运维一个系统应急手册,当遇到什么情况,做什么事情,都事先准备好,出了事情照着做就可以了。

举报

相关推荐

0 条评论