进程通信的目的:
数据传输:一个进程需要将它的数据发送给另一个进程。
资源共享: 多个进程之间共享同样的资源 (警如文件共享)。
通知事件:一个进程需要向另一个或一组进程发送消息,通知它 (它们)发生了某种事件,比如子进程终止时需要通知其父进程。
进程控制: 有些进程希望完全控制另一个进程的执行(如 Debug 进程),此时控制进程希望能够拦截另一个进程的所有异常,并能够及时知道它的状态改变。
如何实现进程通信:
如果想要实现进程间通信,我们需要借助第三方资源,这个第三方资源其实就是公共资源,这个资源不属于任何进程,而是需要进行通信的各个进程之间的公共资源,这些进程都可以去访问这个公共资源,譬如向公共资源写入数据、或者从公共资源读取数据,从而实现进程间通信的目的。
因为这个第三方资源是由内核提供,所以进程间通信是需要内核参与
进程间通信的本质: 由OS(内核)参与,提供一份所有进程都可以访问的公共资源
公共资源包括:内存块、队列、文件等,所以就出现了多种不同的进程间通信的方法
管道:
把一个进程连接到另一个进程的数据流称为管道
管道分为匿名管道和命名管道
匿名:
匿名管道只能用于父子进程间或是具有“血缘关系”的进程之间的通信
管道中的数据存储在内存中,不会访问存储设备,与访问文件一样,使用read读取管道中的数据,使用write读取数据,并且每个管道会产生两个文件描述符(创建匿名管道,打开匿名管道) //一个读管道,一个写管道
管道是一种单向通信的方法,分两端“读端”“写端”一个进程向管道写入数据,一个进程从管道读出数据,管道创建后,就需要确认双方收发角色。
pipe() | #include <unistd.h> /* On Alpha, IA-64, MIPS, SuperH, and SPARC/SPARC64; see NOTES */ struct fd_pair { long fd[2]; }; struct fd_pair pipe(); /* On all other architectures */ int pipe(int pipefd[2]); | 创建匿名管道 |
数组中的第一个文件描述符用于读管道,第二个文件描述符用于写管道。Pipe函数通常和 fork函数一起使用,首先调用 pipe 函数创建匿名管道,然后调用fork 函数创建子进程,所以子进程就会继承 pipe 函数所得到的的两个文件描述符,从而父子进程之间实现这个文件共享、也就实现了进程间通信。
如何实现进程通信:
如果想要实现进程间通信,我们需要借助第三方资源,这个第三方资源其实就是公共资源,这个资源不属于任何进程,而是需要进行通信的各个进程之间的公共资源,这些进程都可以去访问这个公共资源,譬如向公共资源写入数据、或者从公共资源读取数据,从而实现进程间通信的目的。
因为这个第三方资源是由内核提供,所以进程间通信是需要内核参与
进程间通信的本质: 由OS(内核)参与,提供一份所有进程都可以访问的公共资源
公共资源包括:内存块、队列、文件等,所以就出现了多种不同的进程间通信的方法
进程间通信的方法:
特点:
管道内部有同步、互斥机制。
管道的生命周期随着进程的终止而终止,因为管道本质上是通过文件的方式进行访问。
管道提供的是字节流服务,向管道写入数据或从管道中读取数据的字节大小是任意的只要不超过管道的容量,管道的大小通常是 4K。并且管道中的数据是没有什么格式的。
管道是单向传输的方式,如果要实现双向传输,我们可以创建两个管道。
匿名管道只能是在父子进程间或者是具有血缘关系的进程之间进行通信。
命名管道:
命名管道是有名字的,所以在进行进程间通信之前,需要创建这个管道文件,命名管道文件存在文件系统中,管道文件有自己的名字,只要对这个管道文件进行读写操作,就可以向管道中写入数据或从管道中读取数据。所以,命名管道可以作为同一台主机上的任意进程之间进行通信
信号:
信号可以作为进程间通信的手段,譬如用于通知某个进程发生了某事
内存映射:NILL
消息队列:NULL
共享内存:
所谓共享内存就是指多个进程之间共享同一块内存区域。这块内存区域会映射到各个进程的地址空间,这些进程都可以访问这块内存区域,实现进程间通信。需要程序中去处理同步互斥的问题。
他也是所有的进程间通信方法中最快的一种、效率最高
套接字(socket):NULL