进程间的五种通信方式详解之——管道
进程间的通信方式有以下几种:
- 管道
- 消息队列
- 共享内存
- 信号量
- Socke
- 信号
- 文件锁
下面就来详细讲解其中一种通信方式——通过管道通信
1、管道
不同的进程可以通过“管道”进行通信,管道具体分为以下两种:
1. 1 匿名管道
1.1.1匿名管道的概念
所谓“匿名管道”就是在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利。
匿名管道用于进程之间通信,且仅限于本地父子进程之间通信,一般使用fork函数实现父子进程的通信,结构简单,实现容易,类似于一根非水平状态的水管,一端进水另一端出水。
1.1.2 匿名管道的特点:
①只提供单向通信,也就是说,两个进程都能访问这个文件,假设进程1往文件内写东西,那么进程2 就只能读取文件的内容。
②只能用于具有血缘关系的进程间通信,通常用于父子进程建通信
③管道是基于字节流来通信的
④依赖于文件系统,它的生命周期随进程的结束结束(随进程)
⑤其本身自带同步互斥效果
1.1.3 匿名管道的应用:
匿名管道主要用于本地父进程和子进程之间的通信,在父进程中的话,首先是要创建一个匿名管道,在创建匿名管道成功后,可以获取到对这个匿名管道的读写句柄,然后父进程就可以向这个匿名管道中写入数据和读取数据了,但是如果要实现的是父子进程通信的话,那么还必须在父进程中创建一个子进程,同时,这个子进程必须能够继承和使用父进程的一些公开的句柄,为什么呢?因为在子进程中必须要使用父进程创建的匿名管道的读写句柄,通过这个匿名管道才能实现父子进程的通信,所以必须继承父进程的公开句柄。同时在创建子进程的时候,必须将子进程的标准输入句柄设置为父进程中创建匿名管道时得到的读管道句柄,将子进程的标准输出句柄设置为父进程中创建匿名管道时得到的写管道句柄。然后在子进程就可以读写匿名管道了。
1.1.4 匿名管道代码举例:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1
int main(void)
{
char write_msg[BUFFER_SIZE] = "Greetings";
char read_msg[BUFFER_SIZE];
pid_t pid;
int fd[2];
/* create the pipe */
if (pipe(fd) == -1) {
fprintf(stderr,"Pipe failed");
return 1;
}
/* now fork a child process */
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid > 0) {
/* parent process */
/* close the unused end of the pipe */
close(fd[READ_END]);
/* write to the pipe */
write(fd[WRITE_END], write_msg, strlen(write_msg)+1);
/* close the write end of the pipe */
close(fd[WRITE_END]);
}
else {
/* child process */
/* close the unused end of the pipe */
close(fd[WRITE_END