进程间通信
关于多进程的通信
- linux 下的进程通信⼿段基本上是从 Unix 平台上的进程通信⼿段继承⽽来的。
- 每个进程都有⾃⼰独⽴的地址空间, 当两个不同进程需要进⾏交互时, 就需要使⽤进程间通讯
- 进程间通讯分为单个计算机的进程间通讯与局域⽹的计算机的进程间通讯
- 进程间通讯⽅式有 管道, 信号, 消息队列, 共享内存,⽹络
管道
- 管道分为 ⽆名管道(匿名管道) 与 有名管道
- ⽆名管道⽤于⽗⼦进程之间通讯
- 有名管道⽤于任意进程之间通讯
管道的本质是在内存建⽴⼀段缓冲区,由操作系统内核来负责创建与管理, 具体通讯模型如下:
无名管道(匿名管道)
- 无名管道属于单向通讯
- ⽆名管道只能⽤于 ⽗⼦进程通讯
- ⽆名管道发送端叫做 写端, 接收端叫做 读端
- ⽆名管道读端与写端抽象成两个⽂件进⾏操作,在⽆名管道创建成功之后,则会返回读端与写端的⽂件描述符
创建无名管道
- 创建⽆名管道需要系统调用 pipe()
- pipe() 函数原型如下:
#include <unistd.h>
int pipe(int pipefd[2]);
- pipefd[2] 是一个数组,数组的两个元素分别代表读端和写端的⽂件描述符
- pipefd[0] 代表读端,pipefd[1] 代表写端
- 函数成功返回 0,否则返回 -1 并设置 errno 变量
示例:创建子进程,父进程通过管道向子进程发送消息
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
//创建子进程,父进程通过管道向子进程发送消息
pid_t cpid;//子进程ID
int ret;//返回值
int pipefd[2];//管道文件描述符
ret = pipe(pipefd);//创建管道,内核会将文件描述符号放入pipefd数组中
if (ret < 0) {
//创建失败
perror("pipe");//打印错误信息
exit(EXIT_FAILURE);//退出程序 EXIT_FAILURE 1
}
cpid = fork();//创建子进程
if (cpid < 0) {
//创建失败
perror("fork");//打印错误信息
exit(EXIT_FAILURE);//退出程序 EXIT_FAILURE 1
}else if (cpid == 0) {
//子进程
ssize_t rbytes;//此变量在父进程不存在,在子进程中使用 //ssize_t是read函数的返回类型,表示读取的字节数
close(pipefd[1]);//关闭写端,子进程只读
//操作管道
char buf[1024];
printf("子进程开始等待父进程发送消息...\n");
rbytes = read(pipefd[0]