Linux几乎支持全部UNIX进程间通信方法,包括管道(有名管道和无名管道)、消息队列、共享内存、 信号量和套接字。其中前四个属于同一台机器下进程间的通信,套接字则是用于网络通信。
管道
无名管道
无名管道特点:
无名管道是一种特殊的文件,这种文件只存在于内存中。
无名管道只能用于父子进程或兄弟进程之间,必须用于具有亲缘关系的进程间的通信。
无名管道只能由一端向另一端发送数据,是半双工方式,如果双方需要同时收发数据需要两个 管道。
相关接口:
int pipe(int fd[2]);
fd[2]:管道两端用fd[0]和fd[1]来描述,读的一端用fd[0]表示,写的一端用fd[1]表示。通信双 方的进程中写数据的一方需要把fd[0]先close掉,读的一方需要先把fd[1]给close掉。
有名管道:
有名管道特点:
有名管道是FIFO文件,存在于文件系统中,可以通过文件路径名来指出。
有名管道可以在不具有亲缘关系的进程间进行通信。
相关接口:
int mkfifo(const char *pathname, mode_t mode);
pathname:即将创建的FIFO文件路径,如果文件存在需要先删除。
mode:和open()中的参数相同。
消息队列
相比于 FIFO,消息队列具有以下优点:
消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;
读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收。
共享内存
进程可以将同一段共享内存连接到它们自己的地址空间,所有进程都可以访问共享内存中的地址,如果 某个进程向共享内存内写入数据,所做的改动将立即影响到可以访问该共享内存的其他所有进程。
其他补充
共享内存的方式像极了多线程中线程对全局变量的访问,大家都对等地有权去修改这块内存的值,这就导致在多进程并发下,最终结果是不可预期的。所以对这块临界区的访问需要通过信号量来进行进 程同步。
但共享内存的优势也很明显,首先可以通过共享内存进行通信的进程不需要像无名管道一样需要通信的进程间有亲缘关系。其次内存共享的速度也比较快,不存在读取文件、消息传递等过程,只需要到相应映射到的内存地址直接读写数据即可。
信号量
在提到共享内存方式时也提到,进程共享内存和多线程共享全局变量非常相似。所以在使用内存共享的 方式是也需要通过信号量来完成进程间同步。多线程同步的信号量是POSIX信号量,而在进程里使用 SYSTEM V信号量。
辅助命令
ipcs命令用于报告共享内存、信号量和消息队列信息。
ipcs -a:列出共享内存、信号量和消息队列信息。
ipcs -l:列出系统限额。
ipcs -u:列出当前使用情况。
套接字
与其它通信机制不同的是,它可用于不同机器间的进程通信。