没有血缘关系的进程之间是如何做到通信的?
管道应用的一个就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
命名管道是一种特殊类型的文件。用命名管道通信。
mkfifo
命名管道也可以从程序里创建,相关函数有:int mkfifo(const char *filename,mode_t mode);
创建好管道之后,要让进程之间能过通信,而进程能够通信的本质是看到同一份资源!要让不同进程看到同一个命名管道文件
再打开文件时怎么知道打开的是同一个文件?同一路径下同一个文件名 = 路径+文件名。路径+文件名有唯一性。
不同进程之间通信就是两个启动的程序进行通信,形成两个程序,在程序中用函数创建一个管道文件调用mkfifo函数,而管道文件只需要创建一次就可以了。然后要考虑让两个进程都看见同一个通信信道管道文件。进程要通信先创建管道。两个进程通信一个为服务端一个为客户端,服务端为客户端提供服务,管道由服务端创建,但是在建立管道之后,只是将信道建立好了,服务方不能立即打开文件,因为写方没有向管道文件中写入数据,那么服务端就会阻塞,要等待客户端写入之后服务端才开始打开文件然后读取客户端给服务端发送的数据。
头文件方法实现,建立管道文件和删除管道文件放在了头文件中实现,当建立好管道文件之后两个进程都能拿到,当一个文件刚被建立时有文件权限
comm.hpp
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#define FIFO_FILE "./myfifo"
#define MODE 06
using namespace std;
enum
{
FIFO_CREATE_ERR = 1,
FIFO_DELETE_ERR,
FIFO_OPEN_ERR
};
class Init
{
public:
Init()
{
int n = mkfifo(FIFO_FILE,MODE);
if(n==-1)
{
perror("mkfifo");
exit(FIFO_CREATE_ERR);
}
}
~Init()
{
int m = unlink(FIFO_FILE);
if (m == -1)
{
perror("unlink");
exit(FIFO_DELETE_ERR);
}
}
};
删除管道文件用unlink
#include<iostream>
#include"comm.hpp"
int main()
{
Init init;
int fd = open(FIFO_FILE,O_RDONLY);
if(fd<0)
{
perror("open");
exit(FIFO_OPEN_ERR);
}
cout<<"server open file"<<endl;
while (true)
{
char buffer[1024] = {0};
int x = read(fd, buffer, sizeof(buffer));
if (x > 0)
{
buffer[x] = 0;
cout << "client say# " << buffer << endl;
}
else if (x == 0)
{
break;
}
else
break;
}
close(fd);
return 0;
}
客户端,向管道文件中写入数据,但是要当服务端将信道建立之后才能往信道中写入数据进行通信
client.cc
#include<iostream>
#include"comm.hpp"
using namespace std;
int main()
{
int fd = open(FIFO_FILE,O_WRONLY);
if(fd < 0)
{
perror("open");
exit(FIFO_OPEN_ERR);
}
cout << "client open file done" << endl;
string line;
while(true)
{
cout<<"Please enter@ ";
getline(cin,line);
write(fd,line.c_str(),line.size());
}
close(fd);
return 0;
}
不能先执行客户端