0
点赞
收藏
分享

微信扫一扫

低代码开发:机遇与挑战

愚鱼看书说故事 2024-08-13 阅读 25

目录

一、通信

1、进程为什么要通信?

1.数据的类型

2.父进程和子进程算通信吗?

2、进程如何通信?

3、进程通信的常见方式?

二、管道 

1、概念

1.管道的4种情况:

2.管道的5种特征:

2、匿名管道

1.为什么父子进程会向同一个显示器终端打印数据?

2.进程默认会打开三个标准输入输出:0,1,2 ?

 3.为什么我们子进程主动close(0/1/2),不影响父进程继续使用显示器文件呢?

4.什么是管道文件?

5.管道文件的特点?

6.管道文件结构图

7.父子既然要关闭不需要的fd,那为什么要打开?

8.可以不关不需要的fd吗?

9.如果想双向通信,怎么办?

10.为什么要单向通信?

11.管道的使用(*)

12.read、write的注意点:

read的返回值:

write:

13.命令行中的管道符号:‘ | ’

14.管道多次创建的示意图(*)

 3、命名管道

1.原理

2.匿名管道和命名管道的区别

3.怎么保证两个毫不相干的进程,打开了同一个文件呢?

4.命名管道操作 --- 系统调用篇

5.命名管道操作 --- 指令篇

三、管道的项目 --- 进程池

process_pool.cc

task.hpp

Makefile


一、通信

1、进程为什么要通信?

1.数据的类型

2.父进程和子进程算通信吗?

2、进程如何通信?

3、进程通信的常见方式?

二、管道 

1、概念

1.管道的4种情况:

2.管道的5种特征:

2、匿名管道

1.为什么父子进程会向同一个显示器终端打印数据?

2.进程默认会打开三个标准输入输出:0,1,2 ?

 3.为什么我们子进程主动close(0/1/2),不影响父进程继续使用显示器文件呢?

4.什么是管道文件?

5.管道文件的特点?

6.管道文件结构图

7.父子既然要关闭不需要的fd,那为什么要打开?

8.可以不关不需要的fd吗?

9.如果想双向通信,怎么办?

10.为什么要单向通信?

11.管道的使用(*)

12.read、write的注意点:

13.命令行中的管道符号:‘ | ’

14.管道多次创建的示意图(*)

 3、命名管道

1.原理

2.匿名管道和命名管道的区别

3.怎么保证两个毫不相干的进程,打开了同一个文件呢?

4.命名管道操作 --- 系统调用篇

5.命名管道操作 --- 指令篇

三、管道的项目 --- 进程池

process_pool.cc


#include "Task.hpp"

// 父进程写,子进程读
class Channel
{
private:
    int _wfd;
    int _id;

public:
    Channel(int wfd, int id)
        : _wfd(wfd), _id(id)
    {
    }
    void close_subprocess()
    {
        close(_wfd);
    }
    int get_wfd()
    {
        return _wfd;
    }
    int get_id()
    {
        return _id;
    }
};

void work(int rfd);
void create_ChannelAndSubprocess(std::vector<Channel> *channels, int child_number, work_t work);
int next_channel(std::vector<Channel> &channels);
void send_command(Channel &channel, int option_task);
void ctrl_channel(std::vector<Channel> &channels);
void clean_ChannelAndSubprocess(std::vector<Channel> *channels);
int main(int argv, char* argc[])
{
    std::vector<Channel> channels;
    load_task();

    if (argv != 2)
        return -1;
    int num = std::stoi(argc[1]);
    // 1、创建信道和子进程
    create_ChannelAndSubprocess(&channels, num, work);

    // 2、通过信道控制子进程
    ctrl_channel(channels);

    // 3、回收管道和子进程
    clean_ChannelAndSubprocess(&channels);
    return 0;
}

void create_ChannelAndSubprocess(std::vector<Channel> *channels, int child_number, work_t work)
{
    for (int i = 0; i < child_number; i++)
    {
        int pipefd[2] = {0};
        int exit_code = pipe(pipefd);
        if (exit_code < 0)
        {
            std::cout << "errno : " << exit_code << std::endl;
            exit(1);
        }
        pid_t id = fork();
        if (id == 0)
        {
            // child;
            close(pipefd[1]);
            work(pipefd[0]);
            exit(0);
        }
        // father
        close(pipefd[0]);

        (*channels).emplace_back(pipefd[1], id);
    }

    std::cout << "创建了:" << channels->size() << "个信道和子进程" << std::endl;
}
int next_channel(std::vector<Channel> &channels)
{
    static int count = 0;
    int option = count;
    count++;
    count %= channels.size();
    return option;
}
void send_command(Channel &channel, int option_task)
{
    write(channel.get_wfd(), &option_task, sizeof(option_task));
}
void ctrl_channel(std::vector<Channel> &channels)
{
    // 选择任务
    srand(time(nullptr));
    int n = task_number;
    while (n -- )
    {
        int option_task = rand() % task.size(); // task[option_task]
        // 选择信道
        int option_channel = next_channel(channels); // channels[option_task]
        // 发送任务
        send_command(channels.at(option_channel), option_task);
        sleep(1);
    }
}
void clean_ChannelAndSubprocess(std::vector<Channel> *channels)
{
    for (auto& channel:*channels)
    {
        channel.close_subprocess();
    }
    for (auto& channel:*channels)
    {
        waitpid(channel.get_id(), 0, 0);
    }
}

task.hpp

#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <unistd.h>
#include <cstdlib>
#include <ctime>
#include <sys/types.h>
#include <sys/wait.h>

typedef void (*task_t)();
typedef void (*work_t)(int);

const int size = 4096;
const int task_number = 7;
// 加载
void download()
{
    std::cout << "This is a downlaod task!" << std::endl;
}
// 打印
void print()
{
    std::cout << "This is a print task!" << std::endl;
}
// 刷新
void flush()
{
    std::cout << "This is a flush task!" << std::endl;
}

std::vector<task_t> task;

void load_task()
{
    task.push_back(download);
    task.push_back(print);
    task.push_back(flush);
}
void excute_task(int option_task)
{
    if (option_task < 0 || option_task >= task.size())
        return;
    task.at(option_task)();
}

void work(int rfd)
{
    int t = task_number;
    int option_task = 0;
    int n = read(rfd, &option_task, sizeof(option_task));
    if (n > 0)
    {
        excute_task(option_task);
        std::cout << "--------------------------------" << std::endl;
    }
}

Makefile

process_pool:process_pool.cc
	g++ $^ -o $@ -std=c++11

.PHONY:clean
clean:
	rm -rf process_pool

谢谢大家!

举报

相关推荐

0 条评论