文章目录
1.父子进程可以不关闭不需要的读端或者写端吗?
🍎可以不关闭文件描述符数组中,fd[0] 读端, fd[1] 写端,虽然可以不关闭但是强烈建议是将其关闭。原因是:一个进程可以打开的文件是有限的,而且如果把读端和写端都打开了,万一使用的时候错误用了另一个端呢?
2.使用 pipe() 系统调用可以创建一个管道
特点如下:
①🍎不需要把数据刷新到磁盘中去;
②🍎不需要文件的路径和文件名(因为它是在内存中创建的一种特殊文件描述符,直接在内存中打开
);
3.怎么实现双向通信呢?
🍌没有其他更好的办法,因为管道只能单向通信,所以只能通过 创建两个管道 来实现;
4.为什么管道通信时单向的呢?
①🍎最直观的特点就是因为简单,实现了代码复用;
②🍎因为在读写文件时,我们的需求就是就是一个读一个写,如果又读又写的话,所有数据都混合在了共同的一块内存区域当中,造成数据混乱;
5.fork() 之后子进程是能拿到父进程的数据的这个算通信吗?
不太算,因为这是写时拷贝,而且只能由父进程把数据给子进程,不能由子传给父,而且数据不能进行修改;
6.父子进程简单通信过程如下
#include <iostream>
#include <string>
#include <cerrno> // errno.h
#include <cstring> // string.h
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// fork之后子进程是能拿到父进程的数据的 --- 通信吗?写时拷贝,对方都看不到
// char buffer[1024]; // 不行的
const int size = 1024;
// 获取更多的子进程信息
std::string getOtherMessage()
{
static int cnt = 0;
std::string messageid = std::to_string(cnt); // stoi -> string -> int
cnt++;
pid_t self_id = getpid();
std::string stringpid = std::to_string(self_id);
std::string message = "messageid: ";
message += messageid;
message += " my pid is : ";
message += stringpid;
return message;
}
// 子进程进行写入
void SubProcessWrite(int wfd)
{
std::string message = "father, I am your son prcess!";
while (true)
{
std::string info = message + getOtherMessage(); // 这条消息,就是我们子进程发给父进程的消息
write(wfd, info.c_str(), info.size()); // 写入管道的时候,没有写入\0, 有没有必要?没有必要
// std::cerr << info << std::endl;
sleep(1); // 子进程写慢一点
}
}
// 父进程进行读取
void FatherProcessRead(int rfd)
{
char inbuffer[size]; // c99
while (true)
{
sleep(2);
// sleep(500);
ssize_t n = read(rfd, inbuffer, sizeof(inbuffer) - 1); // sizeof(inbuffer)->strlen(inbuffer);
if (n > 0)
{
inbuffer[n] = 0; // == '\0'
std::cout << inbuffer << std::endl;
}
}
}
int main()
{
// 1. 创建管道
int pipefd[2];
int n = pipe(pipefd); // 输出型参数,rfd, wfd
if (n != 0)
{
std::cerr << "errno: " << errno << ": "
<< "errstring : " << strerror(errno) << std::endl;
return 1;
}
// pipefd[0]->0->r(嘴巴 - 读) pipefd[1]->1->w(笔->写)
std::cout << "pipefd[0]: " << pipefd[0] << ", pipefd[1]: " << pipefd[1] << std::endl;
sleep(1);
// 2. 创建子进程
pid_t id = fork();
if (id == 0)
{
std::cout << "子进程关闭不需要的fd了, 准备发消息了" << std::endl;
sleep(1);
// 子进程 --- write
// 3. 关闭不需要的fd
close(pipefd[0]);
SubProcessWrite(pipefd[1]);
close(pipefd[1]);
exit(0);
}
std::cout << "父进程关闭不需要的fd了, 准备收消息了" << std::endl;
sleep(1);
// 父进程 --- read
// 3. 关闭不需要的fd
close(pipefd[1]);
FatherProcessRead(pipefd[0]);
close(pipefd[0]);
pid_t rid = waitpid(id, nullptr, 0);
if (rid > 0)
{
std::cout << "wait child process done, exit sig: " << std::endl;
std::cout << "wait child process done, exit code(ign): " << std::endl;
}
return 0;
}