Linux 之 IPC进程间通信(二、管道)

  1. 什么是管道
    1. 管道是Unix中最古老的进程间通信的形式;
    2. 管道是半双工的,数据只能向一个方向流动;
    3. 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)进行通信;????
    4. 本质上是文件io操作;
    5. 最大的数据量为65556(64kb);
    6. 在shell中使用管道
      1. 命令格式如:cmd1 | cmd2;这种信息过滤也是通过管道实现
  2. 优缺点
    1. 能进行块数据的传输;
    2. 内容有上限;
    3. 要双端同时打开才能使用;

匿名管道pipe 

        关键函数

//准备文件描述符:fd[0]读、fd[1]写
int fdarr[2] = { 0 };

//创建管道:利用文件描述符数组,第一个读、第二个写
pipe(fdarr) != 0	//打开一个管道

//管道只能是单向的,读端关闭fd[1]、写端关闭fd[0]
close(fdarr[0])

// 读写操作
//写端
write(fdarr[1], buf, sizeof(buf));
//读端
read(fdarr[0], buf, sizeof(buf));

        用pipe无名管道实现父子进程间通信

#include
#include 
using namespace std;
#include

//匿名管道的训练
int main()
{
	int fdarr[2] = { 0 };//负责父-》子 fd[0]读、fd[1]写
	int fdarr2[2] = { 0 };//负责子-》父
	char buf[50] = { 0 };
	char resbuf[50] = { 0 };

	pid_t pid = 0;
	if (pipe(fdarr) != 0 || pipe(fdarr2) != 0)
	{
		perror("pipe error");
	}
	else {
		pid = fork();
		if (pid > 0)
		{//父亲
			//管道的读端关闭,执行写
			close(fdarr[0]);
			close(fdarr2[1]);
			while (1)
			{
				cout << "父进程发送:" << endl;
				fgets(buf, sizeof(buf),stdin);
				int wres = write(fdarr[1], buf, sizeof(buf));
				cout << "pid = " << getpid() << " 发送:" << buf << " res = " <Fork前创建管道,获得读端和写端的文件描述符、fork后关闭不需要的管道; 
   
  • 匿名管道不能修改通信方向(close(fdarr[0]));
  • 命名管道fifo

    //检测是否存在
    access(pipepath.c_str(), F_OK)
    
    //创建管道
    mkfifo(pipepath.c_str(), 0007)	
    
    //写端
    open(pipepath.c_str(), O_WRONLY)	
    write(Writefd, wbuf, sizeof(wbuf))
    
    //读端
    open(pipepath.c_str(), O_RDONLY)	
    read(Readfd, rbuf, sizeof(rbuf))

    命名管道-伪聊天

    #include
    using namespace std;
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main()
    {
    	string pipepath = "/home/wangcf/data/A2B.pipe";
    	int wfd = 0;
    	int Writefd = 0;
    	char wbuf[50] = { 0 };
    
    	string pipepath2 = "/home/wangcf/data/B2A.pipe";
    	int rfd = 0;
    	int Readfd = 0;
    	char rbuf[50] = { 0 };
    
    	umask(0);	
    
    	if (access(pipepath.c_str(), F_OK) == 0)
    	{
    		cout << "pipe existence存在" << endl;
    	}
    	else {
    		if(mkfifo(pipepath.c_str(), 0007) == -1)
    			{
    			perror("mkfifo error");
    		}
    	}
    
    	if (access(pipepath2.c_str(), F_OK) == 0)
    	{
    		cout << "pipe2 existence存在" << endl;
    	}
    	else {
    		if (mkfifo(pipepath2.c_str(), 0007) == -1)
    		{
    			perror("mkfifo error");
    		}
    	}
    
    	Writefd = open(pipepath.c_str(), O_WRONLY);
    	if (Writefd == -1)
    	{
    		perror("open error");
    	}
    	else {
    		cout<<  "Writefd = " < 0)
    	{
    		while (1) {
    			int rres = read(Readfd, rbuf, sizeof(rbuf));
    			cout << "B		:" << rbuf << endl;
    			bzero(rbuf, sizeof(rbuf));
    		}
    	}
    	return 0;
    }

    1. Open函数
      1. 是阻塞式函数,一定要两段同时开启;
      2. 程序不能以O_RDWR模式打开FIFO文件进行读写;
    2. Read()为阻塞函数;
    3. 命名管道可以修改通信方向:
      1. (先关闭再重新打开FIFO的办法明确地改变数据流的方向);
    4. Fifo文件
      • 不会保留数据,永远大小为0;
      • 把管道删掉还能用,但是不合规。

    用管道实现伪聊天!!!!!

    未实现

    你可能感兴趣的:(linux,c++,开发语言,linux)