进程间通信
进程间通信介绍
进程间通信目的
a. 数据传输:一个进程需要将它的数据发送给另外一个进程。
b. 资源共享: ## 标题多个进程之间共享同样的资源。
c. 通知时间: 一个进程需要向另外一个或一组进程发送通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
进程间通信发展
- 管道
- System V 进程间通信
- POSIX进程间通信
管道
什么是管道
- 管道是Unix中最古老的进程间通信形式。
- 我们把从一个进程连接到另一个进程的一个数据流称为管道。在这里插入代码片
匿名管道pipe
功能:创建一无名管道
原型:int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码
在这里插入代码片#include <iostream>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cassert>
#include <sys/types.h>
#include <sys/wait.h>
#define NUM 1024
using namespace std;
int main()
{
// 第一步:创建管道文件,打开读写端
int fds[2];
int n = pipe(fds);
assert(n == 0);
// 第二步:创建子进程
pid_t id = fork();
assert(id >= 0);
if(id == 0)
{
// 子进程进行写入
close(fds[0]);
//子进程通信代码
const char* s = "我是子进程,我正在给你发信息";
int cnt = 0;
while(true)
{
cnt++;
char buffer[NUM];
snprintf(buffer,sizeof buffer,"child->parent say: %s[%d][%d]",s,cnt,getpid());
write(fds[1],buffer, strlen(buffer));
//sleep(10000);//细节,每隔一秒休息写一次
break;
}
close(fds[1]);
exit(0);
}
// 父进程进行读
close(fds[1]);
// 父进程通信
while(true)
{
//cout << "AAAAAAAAAAAAAAAAAAAAAAAAAA" << endl;
char buffer[NUM];
ssize_t s = read(fds[0],buffer,sizeof(buffer) - 1);
//cout << "BBBBBBBBBBBBBBBBBBBBBBBBBB" << endl;
if(s > 0)
{
buffer[s] = 0;
cout << "Get Message# " << buffer << " | mypid: " << getpid() << endl;
}
else if(s == 0)
{
cout << "read: " << buffer << endl;
break;
}
//cout << "Get Message# " << buffer << " | mypid: " << getpid() << endl;
//sleep(5);
}
n = waitpid(id, nullptr, 0);
assert(n == id);
close(fds[0]);
//fds[0]: read
//fds[1]: write
// cout << "fds[0]:" << fds[0] << endl;
// cout << "fds[1]:" << fds[1] << endl;
//std::cout << "Hello C++" << std::endl;
return 0;
}
命名管道
- 管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
- 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
- 命名管道是一种特殊类型的文件
命名管道:是一个文件,读写端进程共同打开同一个文件,以不同的方式打开,实现通信需求。
管道的读写规则
a. 读慢,写快
管道写满时,write 调用阻塞,等待对方进程进行读取
b. 读快,写慢
没数据可读时,read调用阻塞,即读进程暂停执行,一直等到写端有数据写入时。
c. 写端关闭,则read端,返回0
d.读端关闭,则write端操作会产生信号SIGPIPE(可以用kill -l linux命令查看SIGPIPE是什么意思),导致操作系统发送信号,write端进程退出。