目录
- 1. 管道(Pipe)
- 匿名管道(Anonymous Pipe)
- 命名管道(FIFO)
- 示例代码
- 2. 消息队列(Message Queue)
- 示例代码
- 3. 共享内存(Shared Memory)
- 示例代码
- 4. 信号量(Semaphore)
- 示例代码
- 5. 套接字(Socket)
- 示例代码
- 服务器端
- 客户端
- 6. 信号(Signal)
- 示例代码
- 总结
1. 管道(Pipe)
- 适用场景:用于具有亲缘关系的进程间通信,如父子进程。
- 优点:实现简单,使用方便。
- 提出背景:早期操作系统中,父子进程间需要简单通信机制。
- 时间顺序:是最早的进程间通信方式之一。
- 通信原理:通过内核缓冲区实现数据传输,数据只能单向流动,若需双向通信需建立两个管道。
- 效率:效率中等,数据量大时可能阻塞。
- 传递的消息:无格式字节流。
匿名管道(Anonymous Pipe)
- 定义:匿名管道是一种简单的进程间通信机制,主要用于父子进程之间的单向通信。
- 创建方式:通过 pipe 系统调用创建。
- 适用场景:仅限于具有亲缘关系的进程(如父子进程)。
- 提出背景:作为早期操作系统中简单高效的父子进程通信机制。
命名管道(FIFO)
- 定义:命名管道是一种特殊的文件,通过文件系统中的路径名标识,允许不相关的进程进行通信。
- 创建方式:通过 mkfifo 函数创建。
- 适用场景:无亲缘关系的进程间通信。
- 优点:允许非亲缘进程通信。
- 提出背景:为解决匿名管道只能用于亲缘进程的限制。
- 时间顺序:在匿名管道之后。
- 通信原理:通过文件系统中的路径名访问,数据按先进先出顺序传输。
- 效率:效率中等,比匿名管道稍低。
- 传递的消息:无格式字节流。
示例代码
父子进程之间传递数据,例如,父进程向子进程发送字符串。 父进程通过 pipe 创建管道、父进程向管道的写端写入数据、子进程从管道的读端读取数据。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main() {int pipefds[2];pid_t pid;char message[] = "Hello from parent!";char buffer[80];// 创建管道if (pipe(pipefds) == -1) {perror("pipe");exit(1);}// 创建子进程pid = fork();if (pid == -1) {perror("fork");exit(1);}if (pid == 0) { // 子进程close(pipefds[1]); // 关闭写端read(pipefds[0], buffer, sizeof(buffer)); // 从管道读取数据printf("Child received: %s\n", buffer);close(pipefds[0]);} else { // 父进程close(pipefds[0]); // 关闭读端write(pipefds[1], message, strlen(message)); // 向管道写入数据close(pipefds[1]);wait(NULL); // 等待子进程结束}return 0;
}
2. 消息队列(Message Queue)
- 适用场景:多个进程间传递结构化数据,支持异步通信。
- 优点:传递结构化数据,支持异步通信。
- 提出背景:克服信号传递信息量少、管道只能承载无格式字节流的缺点。
- 时间顺序:在管道之后。
- 通信原理:消息存储在内核中,进程通过系统调用发送和接收消息。
- 效率:效率中等,数据拷贝较多。
- 传递的消息:结构化数据,每条消息有类型标识。
示例代码
多个进程之间传递结构化消息,例如,生产者向消费者发送消息。 使用 msgget 创建消息队列、父进程通过 msgsnd 发送消息、子进程通过 msgrcv 接收消息。
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <unistd.h>struct msg_buffer {long msg_type;char msg_text[80];
};int main() {