进程间的通信简介

在这里插入图片描述

通信工具

通信工具允许进程间相互交换数据,也可以用来不同线程之间交换数据,不过很少使用,一般线程之间通过共享全局变量来交换信息。
通信工具可以分为两类:
数据传输工具:区分这些工具的关键因素是写入和读取的概念。为了进行通信,一个进程将数据写入IPC工具中,另一个进程从中读取数据。这些工具要求在用户内存和内核内存之间进行两次数据传输:一次传输是在写入的时候从用户内存到内核内存,另一次传输是在读取的时候从内核内存到用户内存。
共享内存:共享内存允许进程通过将数据放到由进程间共享的一块内存中以完成信息的交换。一个进程可以通过将数据放到共享内存块中使得其他进程读取这些数据。共享内存速度非常快。

数据传输:

**字节流:**通过管道、FIFO以及数据报socket交换的数据是一个无分隔符的字节流。每个读取操作可能会从IPC工具中读取任意数量的字节。
**消息:**通过systemV 消息队列、POSIX消息队列以及数据报socket交换的数据以分隔符分割消息。每个读取操作读取写者写入的一整条消息,无法只读取部分消息,而把剩余部分留在IPC工具中,也无法在一个读操作中读取多条消息。
数据传输工具和共享内存之间的差别包括:
注意事项:
尽管一个数据传输工具可能会有多个读取者,但读取操作时具有破坏性的。读取操作会消耗数据,其他进程将无法获取所消耗的数据。
读取者和写者进程之间的同步是原子的。如果一个读取者试图从一个当前不包含数据的数据传输工具中读取数据,那么在默认情况下读取操作会被阻塞至一些进程向该工具中写入数据。

共享内存:

Unix系统提供三种形式的共享内存:system V共享内存,POSIX共享内存以及内存映射。
尽管共享内存的通信速度更快,但速度上的优势是用来弥补需要对共享内存上发生的操作进行同步的不足。在共享内存中,信号量通常用来作为同步方法。
放入共享内存中的数据对所有共享这块内存的进程可见。

同步工具

同步工具可以协调进程的操作。通过同步可以防止进程执行诸如同时更新一块共享内存或同时更新文件的同一个数据之类的操作。如果没有同步,这种同时更新的操作会导致应用程序产生错误的结果。
Unix提供了以下同步工具:

信号量:

一个信号量可以使一个由内核维护的整数,其值永远不会小于0。一个进程可以增加或者减小一个信号量的值。如果一个进程试图将信号量的值减小到小于0,那么内核会阻塞该操作直至信号量增长到允许执行该操作的程度。(或者内核里会让该操作立即返回并返回一个标识无法立即执行该操作的错误。)信号量的含义是由应用程序来确定的。一个进程减小一个信号量是为了预约其对某些共享资源的独占访问,在完成了资源的使用之后可以增加信号量来释放共享资源供其他进程使用。最常用的信号是二元信号量—一个值只能是0或1的信号量但处理一类共享资源拥有多个实例的应用程序需要使用最大值等于该共享资源数量的信号量

文件锁:

文件锁是设计用来协调操作同一文件的多个进程的动作的一种同步方法。它可以用来协调对其他共享资源的访问。文件锁分为两类:读(共享)锁和写(互斥)锁。任意进程都可以持有同一个文件的读锁,但当一个进程持有一个文件的写锁之后,其他进程将无法获取该文件上的读锁和写锁。linux下fcntl()和flock()系统调用可以提供文件加锁工具。fcntl()系统调用提供了记录加锁,允许进程在同一文件的不同区域上加上多个读锁和写锁。flock()很少使用。

互斥体和条件变量:

这些同步通常用于POSIX线程。


在执行进程间同步是通常根据功能需求来选择工具。当协调对文件的访问时文件记录加锁通常是最佳的选择,而对于协调对其他共享资源的访问来讲,信号量通常是更加的选择
通信工具也可以用来同步。一般来讲,所有数据传输工具都可以用来同步,只是同步操作时通过在工具中交换消息来完成的。

Linux通过eventfd()系统调用提供了一种非标准的同步机制:

这个系统调用创建了一个eventfd对象,该对象拥有一个相关的由内核维护的8字节无符号整数。它返回一个指向该对象的文件描述符。向这个文件描述符中写入一个整数会把该整数加到对象值上。当对象值为0时对该文件描述符的read()操作将会阻塞。如果对象的值非零,那么read()会返回该值并将对象重置为0。此外可以使用poll()、select()、epoll()来测试对象值是否为零,如果非零的话表示文件描述符可读。

猜你喜欢

转载自blog.csdn.net/weixin_39116058/article/details/88582932
今日推荐