目录
一、进程间通信的重要性
二、常见的进程间通信方式
三、进程间通信的目的
四、进程间通信的本质
在计算机编程的领域中,进程间通信(Inter-Process Communication,IPC)是一个至关重要的概念。当我们在操作系统中运行多个程序或进程时,它们往往需要相互协作、交换信息,而这就是进程间通信发挥作用的地方。
一、进程间通信的重要性
想象一下,在一个复杂的系统中,可能有多个进程同时运行,比如一个图形界面程序、一个数据处理程序和一个网络通信程序。它们各自承担着不同的任务,但有时需要共享数据、协调行动或发送信号。没有有效的进程间通信机制,这些进程就会如同孤立的岛屿,无法高效地协同工作。
在一个分布式计算系统中,不同的计算节点需要通过网络套接字进行通信,以协调任务分配和结果汇总。在一个多线程的应用程序中,线程之间可能通过共享内存来高效地共享数据。而在操作系统中,内核与用户进程之间也常常通过信号来传递重要的事件信息。
二、常见的进程间通信方式
- 管道(无名管道与有名管道):
- 原理与特点:无名管道主要用于具有亲缘关系的进程间通信,而有名管道则可用于无亲缘关系的进程。它们具有简单、高效的特点。
- 示例代码:创建无名管道并进行数据传输的简单示例。
#include <iostream> #include <cassert> #include <cstring> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #define MAX 1024 using namespace std; int main() { // 建立管道 int pipefd[2] = {0}; int n = pipe(pipefd); assert(n == 0); (void)n; cout << "pipefd[0]:" << pipefd[0] << ",pipefd[1]:" << pipefd[1] << endl; // 创建子进程 int pid = fork(); if (pid < 0) { perror("fork"); exit(1); } // 建立单向通信管道,子写 父读 else if (pid == 0) { // child close(pipefd[0]); char message[MAX]; int cnt = 10; while (cnt) { snprintf(message, sizeof(message) - 1, "hello father! I am child,pid:%d,cnt:%d", getpid(), cnt); // 向管道写入信息 write(pipefd[1], message, strlen(message)); cnt--; sleep(1); } } // father close(pipefd[1]); // 向管道读取信息 char buffer[MAX]; while (true) { ssize_t n = read(pipefd[0], buffer, sizeof(buffer) - 1); if (n > 0) { buffer[n] = '\0'; cout << getpid() << ",child say:" << buffer << " to me" << endl; } } int rid = waitpid(pid, nullptr, 0); // ? if (rid == pid) { cout << "wait success!" << endl; } return 0; }
- 消息队列:
- 工作机制:进程可以将消息发送到队列中,其他进程从队列中获取消息。
- 优势与应用:提供了一种异步通信方式,适合不同速率的进程间通信。
- 共享内存:
- 实现原理:多个进程共享一段物理内存区域。
- 同步问题处理:需要通过信号量等机制来确保数据的一致性。
- 信号和信号量:
- 常见信号类型:如 SIGINT、SIGTERM 等。
- 信号的发送与接收:如何发送和响应信号。
- 信号量则侧重于更复杂的同步和资源管理机制。
- 套接字:
- 本地套接字与网络套接字在进程间通信中的应用:可实现跨机器的进程通信。
三、进程间通信的目的
- 数据传输:一个进程需要将它的数据发送给另一个进程
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变。
四、进程间通信的本质
进程是资源分配和系统调度运行的基本单位。
从资源分配角度来看,进程拥有自己独立的各种资源,如内存空间、文件描述符等,操作系统会为其分配所需的资源。每个进程都有自己独立的资源和运行环境,相互之间相对隔离。
为了确保进程的独立性,但进程间又需要通信,所以我们需要一个第三方来为进程间做沟通的中间人,这个第三方就是操作系统,操作系统通过让不同进程间看到同一份资源的方式来让进程间建立沟通。
通信的本质就是:让不同进程看到同一份资源,这份资源是操作系统内核的资源,这是进程通信的指导思想,无论是哪种通信方式的实现,都是基于这个思想!
每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。