进程间通信的方式
- 信号(signal):亲缘进程和非亲缘进程都可以, 也可以进程自己给自己递送信号。
- 管道(pipe):只允许亲缘进程间的通讯。
- 命名管道(FIFO):除了亲缘进程可以通讯外,非亲缘进程也可以通讯。
- 共享内存:多个进程可以访问同一块内存空间,是最快的IPC方式。在进程间传递数据时无须任何内存的拷贝 。可以在亲缘和非亲缘的进程间使用。
- 信号量(semaphore):主要是线程间和亲缘和非亲缘的进程间的同步手段,不做数据传输之用。
- 套接字最通用的进程间通讯方式,它提供了一种让不同机器上进程间通讯方式。
- 消息队列:可以用在非亲缘关系的进程之间使用
管道
管道是UNIX IPC的最老形式,并且所有U N I X系统都提供此种通信机制,管道有两种限制;
(1) 它们是半双工的。数据只能在一个方向上流动。
(2) 它们只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。
管道的写和读有两个特性:
(1) 数据写入时,放在管道的结尾。
(2) 数据读取时,从管道的头开始读取。
一句话概括:先发过去的,对方先收到。
pipe 函数
#include <unistd.h>
int pipe(int fildes[2]);
- 参数filedes返回两个文件描述符: filedes[0]为读而打开,filedes[1]为写而打开。filedes[1]的输出是filedes[0]的输入。
- 成功返回0,失败返回-1.
- 缺点:只能用于亲缘进程间通讯,在一个进程内管道几乎是没有实际用处的
由于管道是单向的,所以通常一个进程需要关闭写端或者读端,而另一个进程则关闭相应的读端或写端。写端不存在时,读端会收到文件结束符。读端不存在时,写端会收到SIGPIPE信号。如果忽略该信号或者捕捉该信号并从其处理程序返回,则w r i t e出错返回,e r r n o设置为EPIPE
在写管道时,常数PIPE_BUF规定了内核中管道缓存器的大小。如果对管道进行w r i t e调用,而且要求写的字节数小于等于PIPE_BUF,则此操作不会与其他进程对同一管道(或FIFO)的write操作穿插进行。但是,若有多个进程同时写一个管道(或FIFO),而且某个或某些进程要求写的字节数超过PIPE_BUF字节数,则数据可能会与其他写操作的数据相穿插。
命名管道
mkfifo 函数
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
- mode参数的规格说明与open函数中的mode相同。一旦已经用mkfifo创建了一个FIFO,就可用open打开它。确实,一般的文件I/O函数(open、close、read、write、unlink等)都可用于FIFO。
- 返回0成功,返回-1失败
FIFO有时被称为命名管道。管道只能由相关进程使用,它们共同的祖先进程创建了管道。但是,通过FIFO,不相关的进程也能交换数据。
创建FIFO类似于创建文件。确实,FIFO的路径名存在于文件系统中。
Linux 下查看消息队列、共享内存、信号量的命令:ipcs
共享内存