看图,这些通信工具也可以用在线程间通信,但是一般不用,
通信工具可以分为数据传输工具和共享内存,共享内存通过让俩个进程中的页表条目指向同一个RAM分页来实现,性能更好,数据传输工具需要将数据从用户内存传到内核内存,内核内存再传到用户内存。
数据传输
可以进一步将数据传输工具分成下列类别。
y 字节流:通过管道、FIFO 以及数据报 socket 交换的数据是一个无分隔符的字节流。
每个读取操作可能会从 IPC 工具中读取任意数量的字节,不管写者写入的块的大小是
什么。这个模型参考了传统的 UNIX“文件是一个字节序列”模型。
y 消息:通过 System V 消息队列、 POSIX 消息队列以及数据报 socket 交换的数据是以
分隔符分隔的消息。每个读取操作读取由写者写入的一整条消息,无法只读取部分
消息,而把剩余部分留在 IPC 工具中,也无法在一个读取操作中读取多条消息。
y
伪终端:伪终端是一种在特殊情况下使用的通信工具,在 64 章将会介绍有关伪终端
的详细信息。
数据传输工具和共享内存之间的差别包括以下几个方面。
y 尽管一个数据传输工具可能会有多个读取者,但读取操作是具有破坏性的。读取操作
会消耗数据,其他进程将无法获取所消耗的数据。
y读取者和写者进程之间的同步是原子的。如果一个读取者试图从一个当前不包含数据
的数据传输工具中读取数据,那么在默认情况下读取操作会被阻塞直至一些进程向该
工具写入了数据。
共享内存
大多数现代 UNIX 系统提供了三种形式的共享内存: System V 共享内存、 POSIX 共享内存以
及内存映射。在后面介绍这些工具的章节中将会描述它们之间的差别(特别是在 54.5 节中)
。
下面是使用共享内存时的注意点。
y 尽管共享内存的通信速度更快,但速度上的优势是用来弥补需要对在共享内存上发生的
操作进行同步的不足的。如当一个进程正在更新共享内存中的一个数据结构时,另一个
进程就不应该试图读取这个数据结构。在共享内存中,信号量通常用来作为同步方法。
y
放入共享内存中的数据对所有共享这块内存的进程可见。(这与上面数据传输工具中
介绍的破坏性读取语义不同。)
同步工具
通过图 43-1 中的同步工具可以协调进程的操作。通过同步可以防止进程执行诸如同时更
新一块共享内存或同时更新文件的同一个数据块之类的操作。如果没有同步,那么这种同时更新的操作可能会导致应用程序产生错误的结果。
UNIX 系统提供了下列同步工具。
y 信号量:一个信号量是一个由内核维护的整数,其值永远不会小于 0。一个进程可以
增加或减小一个信号量的值。如果一个进程试图将信号量的值减小到小于 0,那么内
核会阻塞该操作直至信号量的值增长到允许执行该操作的程度。(或者进程可以要求
执行一个非阻塞操作,那么就不会发生阻塞,内核会让该操作立即返回并返回一个标
示无法立即执行该操作的错误。)信号量的含义是由应用程序来确定的。一个进程减
小一个信号量(如从 1 到 0)是为了预约对某些共享资源的独占访问,在完成了资源
的使用之后可以增加信号量来释放共享资源以供其他进程使用。最常用的信号量是二
元信号量——一个值只能是 0 或 1 的信号量,但处理一类共享资源拥有多个实例的应
用程序需要使用最大值等于共享资源数量的信号量。 Linux 既提供了 System V 信号量,
又提供了 POSIX 信号量,它们的功能是类似的。
y
文件锁:文件锁是设计用来协调操作同一文件的多个进程的动作的一种同步方法。它
也可以用来协调对其他共享资源的访问。文件锁分为两类:读(共享)锁和写(互斥)
锁。任意进程都可以持有同一文件(或一个文件的某段区域)的读锁,但当一个进程
持有了一个文件(或文件区域)的写锁之后,其他进程将无法获取该文件(或文件区
域)上的读锁和写锁。 Linux 通过 flock()和 fcntl()系统调用来提供文件加锁工具。 flock()
系统调用提供了一种简单的加锁机制,允许进程将一个共享或互斥锁加到整个文件
上。由于功能有限,现在已经很少使用 flock()这个加锁工具了。fcntl()系统调用提供
了记录加锁,允许进程在同一文件的不同区域上加上多个读锁和写锁。
y 互斥体和条件变量:这些同步工具通常用于 POSIX 线程,第 30 章对此进行了介绍。
标签:信号量,读取,文件,间通信,进程,工具,共享内存 From: https://www.cnblogs.com/woodx/p/17185361.html