目录
一.进程间通信的介绍
概念:进程间通信简称IPC(Interprocess communication),进程间通信就是在不同进程之间传播或交换信息。
1.1通信的目的
数据传输: 一个进程需要将它的数据发送给另一个进程。
资源共享: 多个进程之间共享同样的资源。
通知事件: 一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件,比如进程终止时需要通知其父进程。
进程控制: 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
本质就是让不同的进程可以看到同一份资源。
每个进程都是独立的,各个进程之间若想实现通信,一定要借助第三方资源,这些进程就可以通过向这个第三方资源写入或是读取数据,进而实现进程之间的通信,这个第三方资源实际上就是操作系统提供的一段内存区域。
1.2进程间通信的分类
管道
- 匿名管道
- 命名管道
System V IPC
- System V 消息队列
- System V 共享内存
- System V 信号量
POSIX IPC
- 消息队列
- 共享内存
- 信号量
- 互斥量
- 条件变量
- 读写锁
二.匿名管道
管道是Unix中最古老的进程间通信的形式,我们把从一个进程连接到另一个进程的数据流称为一个“管道”。
2.1概念
匿名管道用于进程间通信,但仅限于本地父子进程之间的通信。使用匿名管道通信,可以让父子进程看到同一份资源,父子进程可以对其进行读写操作,从而实现通信。
如图:
补充:
1.这里父子进程看到的同一份资源是由操作系统维护的,父子进程对其进行读写操作时不会发生写时拷贝。
2.管道虽然用的是文件的方案,但操作系统不会把进程进行通信的数据刷新到磁盘当中,因为这样做有IO参与会降低效率。也就是说,这种文件是一批不会把数据写到磁盘当中的文件,换句话说,磁盘文件和内存文件不一定是一一对应的,有些文件只会在内存当中存在,而不会在磁盘当中存在。
创建匿名管道的函数:
int pipe(int pipefd[2]);
解释:pipe函数的参数是一个输出型参数,数组pipefd用于返回两个指向管道读端和写端的文件描述符。函数调用成功返回0,失败返回-1。
数组元素 | 含义 |
---|---|
pipefd[0] | 管道读端的文件描述符 |
pipefd[1] | 管道写端的文件描述符 |
2.1.2使用步骤
创建匿名管道实现父子进程间通信的过程中,需要pipe函数和fork函数搭配使用.
例如:
1.先由父进程调用pipe函数,创建管道。
2.父进程在创建子进程。
3.父进程关闭写端,子进程关闭读端。
也可站在文件描述的角度来看待:
用代码进行演示:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
int fd[2] = { 0 };
if (pipe(fd) < 0){ //使用pipe创建匿名管道
perror("pipe");
return 1;
}
pid_t id = fork(); //使用fork创建子进程
if (id == 0)
{
close(fd[0]); //子进程关闭读端
char arr[20]="hello world";
for(int i=0;i<5;i++)
{ write(fd[1], arr, strlen(arr)); //子进程向管道写入数据
sleep(1);
}
close(fd[1]); //子进程写入完毕,关闭文件
exit(0);
}
close(fd[1]); //父进程关闭写端
char buff[64];
while (true)
{
ssize_t s = read(fd[0], buff, sizeof(buff