进程间通信的必要性
单进程没有并发能力,无法实现多进程协同。
进程通信的本质理解
1.进程通信的前提,让不同的进程看到同一块"内存"
2.看到的内存不属于任何进程,是共享的
进程间通信(IPC)发展
LINUX原生能提供 --- 管道
symstem V进程间通信 -- 多进程
共享内存、消息队列、信号量
POSIX进程间通信 -- 多线程
管道
只能单向通信,传输的都是资源,管道都是单向传输内容
管道实际是文件
管道的原理
管道通信
父进程task_struct{ //有指针指向文件描述符表},每个进程都有自己的一张文件描述符表files_struct,这张表的下标就是fd文件描述符,通过fd找到文件struct file{},
1.分别以读写的方式打开同一个文件
2.fork()创建子进程,子进程需要去复制父进程的files_struct{ }。因此父子进程能够看到同一份文件资源
3.匿名管道的调用实际上是调用了pipe这个函数,父进程创建管道文件是分别以读和写这两种方式打开文件,pipefd[0]表示读,pipefd[1]表示写。
模拟实现父子进程管道通信
int pipe(int pipefd[2]); 成功:0;失败:-1
函数调用成功返回r/w两个文件描述符。无需open,但需手动close。规定:pipefd[0] → r; pipefd[1] → w,就像0对应标准输入,1对应标准输出一样。向管道文件读写数据其实是在读写内核缓冲区。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib> //stdlib.h
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define N 2
#define NUM 1024
using namespace std;
// child
void Writer(int wfd) // wfd pipefd[1]
{
string s = "hello, I am child";
pid_t self = getpid();
int number = 0;
char buffer[NUM];
while (true)
{
sleep(1);
char c = 'c';
write(wfd, &c, 1); // strlen(buffer) + 1???
number++;
cout << number << endl;
if(number >= 5) break;
}
}
// father
void Reader(int rfd)
{
char buffer[NUM];
while(true)
{
buffer[0] = 0;
// system call
ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof != strlen
if(n > 0)
{
buffer[n] = 0; // 0 == '\0'
cout << "father get a message[" << getpid() << "]# " << buffer << endl;
}
else if(n == 0)
{
printf("father read file done!\n");
break;
}
else break;
// cout << "n: " << n << endl;
}
}
//子进程写入父进程读取
int main()
{
int pipefd[N] = {0};
int n = pipe(pipefd);
if (n < 0)
return 1;
pid_t id = fork();
if (id < 0)
return 2;
if (id == 0)
{
// 子进程
close(pipefd[0]);
Writer(pipefd[1]);
close(pipefd[1]);
exit(0);
}
close(pipefd[1]);
Reader(pipefd[0]);
int p1 = 0;
pid_t rid = waitpid(id, &p1, 0);
if(rid < 0) return 3;
close(pipefd[0]);
sleep(5);
return 0;
}
管道的特点
1.管道是用来进行具有血缘关系的进程间通信--常用于父子通信
2.管道具有通过让进程间协同,提供了访问控制
3.管道提供的是面向流式的通信服务--面向字节流
父进程写入很多,但是子进程在sleep一段时间后再读取,会将父进程这一段时间的写入全部读取,写入10次可能一次读完
4.管道是基于文件的,文件的生命周期是随进程的,一个进程结束那么管道也就会结束
5.管道是单向通信,半双工通信的方式