linux进程间通信之管道

目录

一,管道原理

1,首先父进程调用pipe函数创建管道:

2,父进程创建子进程:

3,然后就是根据需求关闭对应的读写

4,由第三步可以知道,

二,匿名管道

1,创建管道pipe

2,写一段父子通信的代码

3,运行结果

三,命名管道

1,创建命名管道

2,进一步理解

原理展示:

1,服务端先跑起来,创建好命名管道

2,客户端服务端俩个进程,客户端发数据,服务端接收

3,客户端退出,服务端也退出

四,代码链接


一,管道原理

 进程具有独立性,所以要通信首先就是俩个进程要看到同一份资源,围绕这一点理解进程间通信:

1,首先父进程调用pipe函数创建管道:

linux进程间通信之管道_第1张图片

2,父进程创建子进程:

fork();此时子进程实惠拷贝父进程的pcd内容数据的,也就相当于他和父进程都知道了同一个资源,这很重要,因为进程之间是有独立性的,只要写就会发生写实拷贝,所以来个进程要想交互就必须要有同一份资源。

linux进程间通信之管道_第2张图片

3,然后就是根据需求关闭对应的读写

这里因为是管道是单项通信的,它里面比我话的要复杂一点,是由同步互斥机制的,但是原理就是这样。

我们假设父进程给子进程发消息,那么父进程写,子进程读。

linux进程间通信之管道_第3张图片

4,由第三步可以知道,

父进程可以发消息给子进程了,但是子进程如何发消息给父进程呢,答案就是关系关闭文件对调一下,但是如果父子进程都想发消息,还邮箱收到消息呢,那么此时我们就可以创建俩个管道。注意这里的管道只能是由父进程创建的,只要这样才可以把文件指向"继承给子进程" ,所以,匿名管道也可以理解为血缘间的通信,一般是父子,兄弟之间。

二,匿名管道

1,创建管道pipe

linux进程间通信之管道_第4张图片

俩个函数,第二个多了一个参数,看文档正确使用就好了。

pipe是一个输出线参数,打开的俩个文件描述符由一个数组待会来。

2,写一段父子通信的代码

我们假设由父进程发送命令,子进程接收命令,模拟这样一个简单的通信。

主要有以下及部分组成:

父进程创建管道

创建子进程

父进程发送消息

子进程接收消息

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

// pipe通信的基本过程,匿名管道。
int main()
{
    int pipnum[2] = {0};

    // 1,创建管道。
    if (pipe(pipnum) != 0)
    {
        cerr << "pipe fail" << endl;
        return 2;
    }

    // 2,创建子进程

    pid_t id = fork();

    //我们这次让子进程读,父进程去写,子进程去执行读到的命令。
    if (id < 0)
    {
        cout << "创建失败" << endl;
        return 3;
    }
    else if (id == 0)
    {
#define NUM 1024
        //子进程 读取父进程发送的任务
        char buffer[NUM];
        close(pipnum[1]);

        while (true)
        {
            sleep(1);
              //   注意这里不要傻傻的写成了strlen();显然不对的啊。
            ssize_t tmp = read(pipnum[0], buffer, sizeof(buffer) - 1);
            if (tmp > 0)
            {

                buffer[tmp] = '\0';
                cout << "我是子进程任务: S " << buffer << endl;
                buffer[0] = '\0';
            }
            else if (tmp == 0)
            {
                cout << "父进程发布完任务退出了"
                     << "我也要退出了" << endl;
                break;
            }
            else
            {
                cout << "出现bug了" << endl;
                break;
            };
        };

        close(pipnum[0]);
        exit(0);
    }
    else if (id > 0)
    {
        //父进程

        close(pipnum[0]);
        const char *msg = "你好子进,这次任务是打击小日子,你这次的任务编号是 ";

        char seetchar[128];

        memset(seetchar, 0, sizeof(seetchar));
        int count = 5;
        while (count)
        {

            //格式化输入。printf格式话输出。   注意要加 "  ";
            sprintf(seetchar, "%s : %d", msg, count);
            sleep(1);
            cout << "我是父进程,我发送的任务编号是" << count << endl;
            write(pipnum[1], seetchar, strlen(seetchar));
            count--;
        };

        cout << "父进程发完任务了,要退出了" << endl;
        close(pipnum[1]);
    };


        //等待子进程,回收资源。
        pid_t pi = waitpid(id, nullptr, 0);
        if (pi > 0)
            cout << "等待子进程成功" << endl;
    return 0;
}

3,运行结果

linux进程间通信之管道_第5张图片

我们发现父子进程确实是可以通信的,

三,命名管道

1,创建命名管道

他的原理其实就是俩个完全不同的进程如何访问同一份资源么,答案就是路径相同,我们可以把文件的路径放在头文件中,俩个完全不相同的进程都包这个头文件,那么俩个进程就都知道这个文件的路径,名字,再有其中一个进程去创建,这样来个进程就可以通过路径找到同一份资源了。

一下是官方文档对mkfifo:命名管道解释: 

linux进程间通信之管道_第6张图片

2,进一步理解

我们同归一段带码来进一步具体的理解命名管道为什么可以相比匿名管道突破亲缘关系传输数据。

首先准备一个头文件,这个都文件是用户端可客户端都包的,里面保存一个路径这个是不同的俩个进程访问同一份资源的关键。

linux进程间通信之管道_第7张图片

接下里就比较正常了,代码中都有详细的注释,这里就不细说了。

服务端代码:

 linux进程间通信之管道_第8张图片

客户端代码:

linux进程间通信之管道_第9张图片 

原理展示:

1,服务端先跑起来,创建好命名管道

linux进程间通信之管道_第10张图片

2,客户端服务端俩个进程,客户端发数据,服务端接收

我们就使用命名管道实现了俩个完全独立的进程直接的通信,

linux进程间通信之管道_第11张图片

3,客户端退出,服务端也退出

linux进程间通信之管道_第12张图片

四,代码链接

lyh_linux-test: linux代码练习。 - Gitee.com

lyh_linux-test: linux代码练习。 - Gitee.com

 

 

 

 

你可能感兴趣的:(c++,linux,c,linux,运维,服务器)