当前位置: 首页 > news >正文

【Linux篇】探索进程间通信:如何使用匿名管道构建高效的进程池

从零开始:通过匿名管道实现进程池的基本原理

  • 一. 进程间通信
    • 1.1 基本概念
    • 1.2 通信目的
    • 1.3 通信种类
      • 1.3.1 同步通信
      • 1.3.2 异步通信
    • 1.4 如何通信
  • 二. 管道
    • 2.1 什么是管道
    • 2.2 匿名管道
      • 2.2.1 pipe()
      • 2.2.2 示例代码:使用 pipe() 进行父子进程通信
      • 2.2.3 管道容量
      • 2.2.4 特点
  • 三. 基于匿名管道原理实现进程池
    • 3.1 简介
    • 3.2 实现进程池
      • 3.2.1 Channel类
      • 3.2.2 ChannelManager 类
      • 3.2.3 taskManager类
      • 3.2.4 ProcessPool 类
      • 3.2.5 总结
  • 四. 最后

进程间通信(IPC)的匿名管道是一种无名的通信方式,通常用于父子进程之间的数据传递。它通过在内核中创建一个缓冲区,允许一个进程将数据写入管道,另一个进程从管道读取数据。管道只能在创建它的进程及其子进程之间使用,因此具有“匿名”特性。匿名管道通过文件描述符实现数据流动,一个进程将数据写入管道,另一个进程从中读取。进程池的实现可以利用匿名管道将任务分配给多个工作进程,通过管道实现父进程与工作进程之间的有效通信,提高系统处理能力和资源利用率。

💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力!
👍点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力!
🚀分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对Linux OS感兴趣的朋友,让我们一起进步!

一. 进程间通信

1.1 基本概念

进程间通信(IPC, Inter-Process Communication)是指不同进程之间为了交换数据或协调工作所使用的一种机制。在多任务操作系统中,进程是独立的执行实体,通常无法直接访问彼此的内存空间。因此,进程间通信提供了一种让进程之间传递信息、同步操作和共享资源的方式。

1.2 通信目的

  1. 数据交换:不同进程需要交换数据,例如一个进程处理数据后,另一个进程需要读取或使用这些数据。IPC提供了数据传递的途径,如管道、消息队列等。
  2. 进程同步与控制:在多进程环境中,多个进程可能需要协同工作。通过IPC,进程可以进行同步控制,确保按照预定的顺序执行,避免竞争条件。例如,信号量和条件变量可以用于进程同步。
  3. 资源共享:多个进程可能需要共享某些资源,如内存、文件或硬件设备。通过共享内存等IPC机制,进程能够安全高效地共享资源,避免冲突。
  4. 异步通信:某些进程可能需要在后台运行,处理任务后通知主进程或其他进程。IPC允许实现异步通信,主进程不需要等待所有子进程完成,可以继续执行其他任务。

1.3 通信种类

1.3.1 同步通信

在同步通信中,发送方和接收方需要在通信过程中保持同步。发送方在发送消息后会等待接收方的响应或确认才能继续执行。

  1. 管道(pipe):匿名管道,命名管道
  2. 消息队列(Message Queue)
  3. 共享内存(Shared Memory)

1.3.2 异步通信

在异步通信中,发送方和接收方不需要在同一时间进行操作。发送方发送消息后可以继续执行,而接收方可以在适当的时机接收消息。

  1. 套接字(Socket)
  2. 事件驱动机制

1.4 如何通信

先让不同的进程看到同一份资源,然后才有通信的条件。

声明:本文先讲述同步通信中管道(匿名管道)的原理,后面的将在后面的文章中一一详解。

二. 管道

2.1 什么是管道

管道(Pipe)是一种进程间通信(IPC)机制,允许一个进程将数据传输到另一个进程。管道提供了一种简单、高效的方式来在同一台机器上的进程之间传递数据,常见于父子进程或兄弟进程之间的通信。管道通过一个缓冲区传递数据,发送进程将数据写入管道,而接收进程从管道中读取数据。

2.2 匿名管道

  • 匿名管道通常用于子进程之间的通信,不需要命名,存在于内存中,生命周期与进程的生命周期相关。
  • 它通常只能在具有亲缘关系的进程之间使用(如父进程与子进程)。
  • 数据流动是单向的,即进程只能写入数据或读取数据。
  • 匿名管道的典型应用是Unix/Linux系统中的管道命令(|)连接不同的命令执行。

2.2.1 pipe()

函数原型:

int pipe(int pipefd[2]);
参数:

  • pipefd:整数数组,系统调用会将管道的文件描述符数组通过该数组返回,其中pipefd[0]:读端,pipefd[1]:写端
    返回值:
  • 成功:返回0
  • 失败:返回-1,同时error被设置

2.2.2 示例代码:使用 pipe() 进行父子进程通信

#include <stdio.h>
#include <unistd.h>
#include <string.h>int main() {int pipefd[2];pid_t pid;char message[] = "Hello from parent process!";char buffer[100];// 创建管道if (pipe(pipefd) == -1) {perror("pipe");return 1;}pid = fork();  // 创建子进程if (pid == -1) {perror("fork");return 1;}if (pid == 0) {  // 子进程close(pipefd[1]);  // 关闭写端read(pipefd[0], buffer, sizeof(buffer));  // 从管道中读取数据printf("Child received: %s\n", buffer);close(pipefd[0]);  // 关闭读端} else {  // 父进程close(pipefd[0]);  // 关闭读端write(pipefd[1], message, strlen(message) + 1);  // 向管道写数据close(pipefd[1]);  // 关闭写端}return 0;
}

该示例子进程从父进程写入管道的数据中读取数据。

原理图:
在这里插入图片描述
原理:父进程关闭读端,子进程关闭写端。

四种不同的通信情况:

  1. 写端往管道中写入数据得慢,而读端从管道中读数据读得快,读端就会发生阻塞(进程),等待写端写入数据。
  2. 写端往管道中写入数据得快,而读端从管道中读数据读得慢,管道中数据满了,写端就要发生阻塞。
  3. 写端直接关闭,而读端继续从管道中读数据,read会读到返回值为0,表示文件结尾。
  4. 读端直接关闭,而写端继续从管道中写数据,OS会终止写端进程,发送信号13(SIGPIPE)

2.2.3 管道容量

在 Unix/Linux 系统中,管道的容量(也称为缓冲区大小)是管道可以存储的最大数据量。管道的容量由操作系统内核设定,并且在不同的操作系统和系统配置中可能会有所不同。管道容量的大小对数据的读写性能以及进程间通信的效率有直接影响。

管道容量的大小

  • 默认容量:在大多数现代 Unix 和 Linux 系统中,匿名管道的默认容量通常是 4 KB 到 64 KB
    之间。这意味着,管道缓冲区可以存储一定量的数据,在缓冲区满时,写入操作会阻塞直到有数据被读取。
  • 可配置性:在某些操作系统和文件系统中,管道容量的大小可以被调整。用户可以通过内核参数来修改管道的缓冲区大小。在 Linux
    系统中,可以通过 sysctl 或修改 /proc/sys/fs/pipe-max-size 来调整管道的缓冲区大小。
    查看管道缓冲区大小语法:

cat /proc/sys/fs/pipe-max-size

2.2.4 特点

  • 单向数据流:管道本身只支持单向的数据流,但可以通过双向管道(通过两个管道实现)来模拟双向通信。
  • 缓冲区机制:管道实现了数据缓冲区,发送方写入数据,接收方从管道读取数据,管道自动管理数据的存储和传递。
  • 阻塞性:当管道缓冲区已满时,写入操作会被阻塞,直到接收方读取数据。反之,当管道为空时,读取操作会被阻塞,直到写入方写入数据。

三. 基于匿名管道原理实现进程池

3.1 简介

进程池是一种多进程并发处理模型,它通过预先创建一定数量的进程来处理任务,从而避免了在每个任务执行时频繁创建和销毁进程的开销。进程池中的进程通常在任务到达时被复用,任务完成后,进程不会被销毁,而是返回进程池等待下一个任务。

进程池的主要目的是提高系统的并发性和响应速度,同时减少频繁创建和销毁进程带来的性能损耗。

3.2 实现进程池

本进程池分为四个模块,分别为 Channel 类,ChannelManager 类,ProcessPool 类,taskManager类。下面将详细介绍各个模块的功能及成员方法。

3.2.1 Channel类

  • 功能:

管道类,表示父进程与子进程之间的通信通道。它提供了发送任务、关闭通道、等待子进程等功能。

(Channel 是管道的封装类)该类主要职责:

  1. 通过管道发送任务(Send() 方法)。
  2. 管理进程间的通信,确保任务能够顺利地传递到子进程。
  3. 管理与子进程相关的资源,例如等待子进程的结束(Wait() 方法)。
  4. 提供进程 ID 和管道文件描述符(Fd() 和 SubId() 方法)。
    示例代码:
class Channel
{
public:Channel(int fd, pid_t id) : _wfd(fd), _subid(id){_name = "channel-" + std::to_string(_wfd) + "-" + std::to_string(_subid);}~Channel() {}void Send(int code){int n = write(_wfd, &code, sizeof(code));(void)n;}void Close(){close(_wfd);}void Wait(){pid_t rid = waitpid(_subid, nullptr, 0);(void)rid;}int Fd() { return _wfd; }pid_t SubId() { return _subid; }std::string Name() { return _name; }private:int _wfd;pid_t _subid;std::string _name;int loadnum;
};

Channel 类不仅封装了管道的创建与关闭,还可以通过 Send() 方法向子进程发送任务,Wait() 方法确保父进程能够正确地等待子进程结束。

3.2.2 ChannelManager 类

  • 功能:

管理多个 Channel 对象,负责处理所有管道和子进程的管理。它可以选择一个空闲的 Channel,发送任务,关闭所有通道等。

(ChannelManager 负责管理多个 Channel 对象)该类主要职责:

  1. Insert() 方法:将一个新的 Channel 对象加入管理列表。
  2. Select() 方法:轮询选择一个空闲的 Channel,实现负载均衡。
  3. CloseAll() 和 StopSubProcess():关闭所有管道及对应的进程,回收资源。
  4. WaitSubProcess() 和 CloseAndWait():确保所有子进程都被回收,并进行资源的清理。
    示例代码:
class ChannelManager
{
public:ChannelManager() : _next(0){}void Insert(int wfd, pid_t subid){_channels.emplace_back(wfd, subid);// Channel c(wfd,subid);//_channels.push_back(std::move(c));}Channel &Select(){auto &c = _channels[_next];_next++;_next %= _channels.size();return c;}void PrintChannel(){for (auto &channel : _channels){std::cout << channel.Name() << std::endl;}}void CloseAll(){for (auto &channel : _channels){channel.Close();//std::cout << "关闭: " << channel.Name() << std::endl;}}void StopSubProcess(){for (auto &channel : _channels){channel.Close();std::cout << "关闭: " << channel.Name() << std::endl;}}void WaitSubProcess(){for (auto &channel : _channels){channel.Wait();std::cout << "回收: " << channel.Name() << std::endl;}}void CloseAndWait(){for (auto &channel : _channels){channel.Close();std::cout << "关闭: " << channel.Name() << std::endl;channel.Wait();std::cout << "回收: " << channel.Name() << std::endl;}// 方案1:从后往前关闭管道// for (int i = _channels.size() - 1; i >= 0; i--)// {//     _channels[i].Close();//     std::cout << "关闭: " << _channels[i].Name() << std::endl;//     _channels[i].Wait();//     std::cout << "回收: " << _channels[i].Name() << std::endl;// }}~ChannelManager() {}private:std::vector<Channel> _channels;int _next;
};

通过 ChannelManager 管理的多个 Channel,可以高效地实现对子进程的管理和任务的分配。

3.2.3 taskManager类

  • 功能:

负责注册和执行任务,这里假设它是一个任务管理器,可以注册不同的任务类型,并根据任务码执行对应的任务。

(任务管理器(taskManager)负责管理各种类型的任务,包括任务的注册和执行)该类主要职责:

  1. 任务注册:通过 Register() 方法,将任务函数(如 PrintLog, DownLoad, UpLoad)与任务码绑定。
  2. 任务执行:通过 Execute() 方法,根据任务码执行对应的任务。任务的执行通过 tm.Execute(code) 完成。
    示例代码:
#pragma once#include<iostream>
#include<vector>
#include<ctime>typedef void (*task_t)();void PrintLog()
{std::cout << "我是一个打印日志的任务" << std::endl;
}
void DownLoad()
{std::cout << "我是一个下载的任务" << std::endl;
}
void UpLoad()
{std::cout<< "我是一个上传的任务" << std::endl;
}class taskManager
{
public:taskManager(){srand(time(nullptr));}void Register(task_t t){_tasks.push_back(t);}int Code(){return rand()%_tasks.size();}void Execute(int code){if(code >= 0 && code < _tasks.size()){_tasks[code]();}}~taskManager(){}
private:std::vector<task_t> _tasks;
};

3.2.4 ProcessPool 类

  • 功能:

进程池类,负责管理子进程的创建、任务分配、进程回收等。

(ProcessPool 负责整个进程池的初始化、任务分配、任务执行和进程回收。)该类主要职责:

  1. 进程池初始化:通过 Start() 方法创建多个子进程,并为每个子进程创建一个管道。每个子进程从管道中接收任务,并执行对应的操作。
  2. 任务分配:通过 Run() 方法从任务管理器中选择一个任务码,并选择一个空闲的 Channel,将任务分配给相应的子进程。
  3. 进程停止与回收:通过 Stop() 方法关闭所有管道并回收所有子进程,确保资源得到释放。
    示例代码:
class ProcessPool
{
public:ProcessPool(int num) : _process_num(num){_tm.Register(PrintLog);_tm.Register(DownLoad);_tm.Register(UpLoad);}void Work(int rfd){while (true){// std::cout << "我是子进程, 我的rfd是:" << rfd << std::endl;// sleep(5);int code = 0;ssize_t n = read(rfd, &code, sizeof(code));if (n > 0){if (n != sizeof(code)){continue;}std::cout << "子进程[" << getpid() << "]收到一个任务码:" << code << std::endl;_tm.Execute(code);}else if (n == 0){// 当所有写端关闭后,读端会读到0,表示EOF。但如果有多个写端,情况会复杂一些。// 当某个写端关闭时,其他写端可能还在打开状态,此时读端可能仍然阻塞,直到所有数据被读取或所有写端关闭。// 管道EOF触发机制// 当且仅当所有写端都关闭时,读端才会收到EOF(read返回0)// 若存在多个写端,即使部分写端关闭,只要还有一个写端保持打开状态,读端就会持续阻塞等待数据std::cout << "子进程退出" << std::endl;break;}else{std::cout << "读取错误" << std::endl;break;}}}bool Start(){for (int i = 0; i < _process_num; i++){// 1.创建管道int pipefd[2] = {0};int n = pipe(pipefd);if (n < 0)return false;// 2.创建子进程pid_t subid = fork();if (subid < 0)return false;else if (subid == 0){// child// 让子进程关闭自己继承下来的,它哥哥进程w段关闭即可!// 3.关闭不需要的文件描述符_cm.CloseAll();//关闭所有的w端close(pipefd[1]);Work(pipefd[0]);close(pipefd[0]);exit(0);}else{// parent// 3.关闭不需要的文件描述符close(pipefd[0]);_cm.Insert(pipefd[1], subid);}}return true;}void debug(){_cm.PrintChannel();}void Run(){// 1.选择一个任务int taskcode = _tm.Code();// 1.选择一个信道[子进程],负载均衡的选择一个信道,完成任务auto &c = _cm.Select();std::cout << "选择一个子进程:" << c.Name() << std::endl;// 2.发送任务c.Send(taskcode);std::cout << "发送了一个任务码:" << taskcode << std::endl;}void Stop(){// //关闭父进程所有wfd的写端// _cm.StopSubProcess();// //回收所有子进程// _cm.WaitSubProcess();_cm.CloseAndWait();}~ProcessPool(){}private:ChannelManager _cm;int _process_num;taskManager _tm;
};#endif

该类封装了创建进程池,均衡的选择任务,同时回收和终止进程相关的资源等。

3.2.5 总结

这个进程池设计的过程体现了如何通过管道和子进程的协作实现任务的并发处理和负载均衡。通过合理的封装和资源管理,确保了系统能够高效地处理大量并发任务,同时能够避免过多的资源浪费。

四. 最后

本文介绍了如何通过匿名管道实现进程池的基本原理。进程池通过预先创建一组子进程来避免频繁创建和销毁进程的开销,提高系统并发性和资源利用率。文章首先讲解了进程间通信的概念,并重点介绍了匿名管道的工作原理及其应用。接着,详细解析了如何利用管道实现进程池,包括 Channel、ChannelManager、taskManager 和 ProcessPool 四个模块。每个模块的设计确保了任务的有效分配、进程的管理和资源的回收。最终,通过合理的进程复用和负载均衡,提升了系统的性能和效率。

路虽远,行则将至;事虽难,做则必成

亲爱的读者们,下一篇文章再会!!!

相关文章:

【Linux篇】探索进程间通信:如何使用匿名管道构建高效的进程池

从零开始&#xff1a;通过匿名管道实现进程池的基本原理 一. 进程间通信1.1 基本概念1.2 通信目的1.3 通信种类1.3.1 同步通信1.3.2 异步通信 1.4 如何通信 二. 管道2.1 什么是管道2.2 匿名管道2.2.1 pipe()2.2.2 示例代码&#xff1a;使用 pipe() 进行父子进程通信2.2.3 管道容…...

Mixture-of-Experts with Expert Choice Routing:专家混合模型与专家选择路由

摘要 稀疏激活的专家混合模型(MoE)允许在保持每个token或每个样本计算量不变的情况下,大幅增加参数数量。然而,糟糕的专家路由策略可能导致某些专家未被充分训练,从而使得专家在特定任务上过度或不足专业化。先前的研究通过使用top-k函数为每个token分配固定数量的专家,…...

ai学习中收藏网址【1】

https://github.com/xuwenhao/geektime-ai-course课程⾥所有的代码部分&#xff0c;通过 Jupyter Notebook 的形式放在了 GitHub 上 https://github.com/xuwenhao/geektime-ai-course 图片创作 https://www.midjourney.com/explore?tabtop 创建填⾊本 How to Create Midjour…...

【滑动窗口】最⼤连续 1 的个数 III(medium)

⼤连续 1 的个数 III&#xff08;medium&#xff09; 题⽬描述&#xff1a;解法&#xff08;滑动窗⼝&#xff09;&#xff1a;算法思路&#xff1a;算法流程&#xff1a; C 算法代码&#xff1a;Java 算法代码&#xff1a; 题⽬链接&#xff1a;1004. 最⼤连续 1 的个数 III …...

ClawCloud的免费空间(github用户登录可以获得$5元/月的免费额度)

免费的空间 Welcome to ClawCloud Lets create your workspace 官网&#xff1a;ClawCloud | Cloud Infrastructure And Platform for Developers 区域选择新加坡 然后这个页面会变成新加坡区域&#xff0c;再按一次确定&#xff0c;就创建好了工作台。 初始界面&#xff0…...

sql之DML(insert、delete、truncate、update、replace))

&#x1f3af; 本文专栏&#xff1a;MySQL深入浅出 &#x1f680; 作者主页&#xff1a;小度爱学习 数据库使用时&#xff0c;大多数情况下&#xff0c;开发者只会操作数据&#xff0c;也是就增删改查&#xff08;CRUD&#xff09;。 增删改查四条语句&#xff0c;最重要的是查…...

Spring Boot常用注解全解析:从入门到实战

&#x1f331; Spring Boot常用注解全解析&#xff1a;从入门到实战 #SpringBoot核心 #注解详解 #开发技巧 #高效编程 一、核心启动与配置注解 1. SpringBootApplication 作用&#xff1a;标记主启动类&#xff0c;整合了Configuration、EnableAutoConfiguration和Component…...

Python 赋能区块链教育:打造去中心化学习平台

Python 赋能区块链教育:打造去中心化学习平台 引言 区块链技术正在重塑全球多个行业,而教育领域也不例外。传统的在线学习平台往往依赖中心化存储和管理模式,导致数据安全、用户隐私、资源共享等问题难以解决。而随着 Web 3.0 的发展,区块链在教育场景中的应用逐渐受到关…...

verilog float mult

module pipe_float_mul(input wire clk ,// 时钟信号input wire en ,// 使能信号input wire rst_n ,// 复位信号input wire round_cfg ,// 决…...

Android开发四大组件和生命周期及setFlags

文章目录 Android开发四大组件1. Activity&#xff08;活动&#xff09;2. Service&#xff08;服务&#xff09;3. BroadcastReceiver&#xff08;广播接收器&#xff09;4. ContentProvider&#xff08;内容提供者&#xff09;共同特点 Activity 生命周期详解完整的生命周期方…...

mysql的函数(第二期)

九、窗口函数&#xff08;MySQL 8.0&#xff09;​​ 适用于对结果集的子集&#xff08;窗口&#xff09;进行计算&#xff0c;常用于数据分析场景。 ​​ROW_NUMBER()​​ ​​作用​​&#xff1a;为每一行生成唯一的序号。​​示例​​&#xff1a;按分数降序排名 SELECT n…...

MATLAB 控制系统设计与仿真 - 39

多变量系统控制器设计实例2 假如原系统对象中有位于虚轴上的极点&#xff0c;则不能直接应用鲁棒控制设计来设计控制器。 在这样的情况下&#xff0c;需引入一个新的变量p&#xff0c;使得 即可在对象模型中用p变量取代s变量&#xff0c;这样的变换称为双线性变换&#xff0c…...

深入理解C++ 中的vector容器

一、引言 在C 的标准模板库&#xff08;STL&#xff09;中&#xff0c; vector 是一个极为常用且功能强大的序列容器。它就像是一个动态数组&#xff0c;既能享受数组随机访问元素的高效性&#xff0c;又能灵活地动态调整大小。在本文中&#xff0c;我们将深入探讨 vector …...

ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(显示输出类外设之LED)

目录 ESP-ADF外设子系统深度解析&#xff1a;esp_peripherals组件架构与核心设计&#xff08;显示输出类外设之LED&#xff09;简介模块概述功能定义架构位置核心特性 LED外设分析LED外设概述LED外设功能特点常见应用场景LED外设架构图 LED外设API和数据结构公共API事件类型配置…...

[特殊字符] Kotlin与C的类型别名终极对决:typealias vs typedef,如何让代码脱胎换骨?

在 Kotlin 中&#xff0c;typealias 是一个非常实用的关键字&#xff0c;它可以为已有的类型定义一个新的名称&#xff0c;起到简化代码和提升可读性的作用。比如&#xff1a; // 定义一个复杂函数类型的别名 typealias ClickListener (View, Int) -> Unitfun setOnClickL…...

第9期:文本条件生成(CLIP + Diffusion)详解

“让我们用一句话&#xff0c;让模型画出一幅画。” 在前几期中我们学习了 Denoising Diffusion Probabilistic Models&#xff08;DDPM&#xff09;如何在无条件情况下生成图像。而在本期&#xff0c;我们将跨入更具挑战性但也更酷的领域 —— 文本条件图像生成&#xff08;Te…...

8 编程笔记全攻略:Markdown 语法精讲、Typora 编辑器全指南(含安装激活、基础配置、快捷键详解、使用技巧)

1 妙笔在手&#xff0c;编程无忧&#xff01; 1.1 编程为啥要做笔记&#xff1f;这答案绝了&#xff01; 嘿&#xff0c;各位键盘魔法师&#xff01;学编程不记笔记&#xff0c;就像吃火锅不配冰可乐 —— 爽到一半直接噎住&#xff01;你以为自己脑子是顶配 SSD&#xff0c;结…...

C#测试linq中的左连接的基本用法

使用linq联表或者连接两个对象集合查询时一般使用的是join关键字&#xff0c;返回结果中包含两个表或两个对象集合中连接字段相等的数据记录&#xff0c;如果要实现sql语句中的左连接效果&#xff0c;并没有现成的left join关键字&#xff0c;此时可以使用DefaultIfEmpty 实现左…...

【Android面试八股文】Android系统架构【一】

Android系统架构图 1.1 安卓系统启动 1.设备加电后执行第一段代码&#xff1a;Bootloader 系统引导分三种模式&#xff1a;fastboot&#xff0c;recovery&#xff0c;normal&#xff1a; fastboot模式&#xff1a;用于工厂模式的刷机。在关机状态下&#xff0c;按返回开机 键进…...

什么是 Stream

Stream 是对集合对象功能的增强&#xff0c;它不是集合&#xff0c;也不存储数据&#xff0c;而是从集合中抽象出一条数据通道&#xff0c;让你可以用链式方式一步步处理数据。 &#x1f527; 常见操作分类 类型方法举例创建stream(), Stream.of(), Arrays.stream()中间操作fi…...

网络编程 - 4 ( TCP )

目录 TCP 流套接字编程 API 介绍 SeverSocket Socket 用 TCP 实现一个回显服务器 服务端 客户端 运行调试 第一个问题&#xff1a;PrintWriter 内置的缓冲区 - flush 刷新解决 第二个问题&#xff1a;上述代码中&#xff0c;需要进行 close 操作吗&#xff1f; 第三…...

在STM32的定时器外设中,选择使用哪个外部时钟配置函数

在STM32的定时器外设中&#xff0c;选择使用哪个外部时钟配置函数主要取决于以下几个因素&#xff1a; 时钟源类型&#xff1a; TIM_ITRxExternalClockConfig&#xff1a;使用内部触发输入(ITRx)&#xff0c;即来自其他定时器的时钟信号 TIM_TIxExternalClockConfig&#xff1…...

【Tauri2】026——Tauri+Webassembly

前言 不多废话 直言的说&#xff0c;笔者看到这篇文章大佬的文章 【04】Tauri 入门篇 - 集成 WebAssembly - 知乎https://zhuanlan.zhihu.com/p/533025312尝试集成一下WebAssembly&#xff0c;直接开始 正文 准备工作 新建一个项目 安装 vite的rsw插件和rsw pnpm instal…...

jenkins尾随命令

在访问jenkins的网址后面可以追加命令&#xff0c;比如访问地址是 http://10.20.0.124:8080/&#xff0c;常用的有以下几种方式&#xff1a; 1.关闭Jenkins 只要浏览器输入http://10.20.0.124:8080/exit即可退出&#xff0c;或者http://localhost:8080/exit 2.重启Jenkins …...

基于机器学习 LSTM 算法的豆瓣评论情感分析系统

基于机器学习 LSTM 算法的豆瓣评论情感分析系统 博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f44…...

腾讯云对象存储m3u8文件使用腾讯播放器播放

参考腾讯云官方文档&#xff1a; 播放器 SDK Demo 体验_腾讯云 重要的一步来了&#xff1a; 登录腾讯云控制台&#xff0c;找到对象存储的存储桶。 此时&#xff0c;再去刷新刚才创建的播放器html文件&#xff0c;即可看到播放画面了。...

基于chatgpt和deepseek解答显卡的回答

当然可以&#xff01;了解显卡特别是英伟达&#xff08;NVIDIA&#xff09;的系列&#xff0c;对于选购、升级或者了解游戏和创作性能都很重要。下面我帮你系统整理一下 NVIDIA 显卡的各个系列&#xff0c;并加点选购建议&#xff0c;方便你快速上手。 chatgpt &#x1f9e0; …...

2025年渗透测试面试题总结-拷打题库06(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 1. Sleep被禁用后的SQL注入 2. XSS属性控制利用 3. CSRF防护 4. 危险请求头 5. XXE高发场景 6. Ja…...

【一起学Rust】使用Thunk工具链实现Rust应用对Windows XP/7的兼容性适配实战

前言 在Rust语言快速发展的今天&#xff0c;开发者经常面临将现代语言特性与遗留系统兼容的挑战。特别是在工业控制、嵌入式设备等场景中&#xff0c;Windows XP/7等经典操作系统仍占据重要地位。本文深入解析如何通过Thunk工具链突破Rust编译器对旧版Windows系统的兼容性限制…...

leetcode 674. Longest Continuous Increasing Subsequence

目录 题目描述 第一步&#xff0c;明确并理解dp数组及下标的含义 第二步&#xff0c;分析明确并理解递推公式 第三步&#xff0c;理解dp数组如何初始化 第四步&#xff0c;理解遍历顺序 代码 题目描述 这是动态规划解决子序列问题的例子。与第300题的唯一区别就是&#…...

在VMware Workstation 17 Pro上实现Windows与UOS虚拟机之间复制粘贴文本及文件

在VMware Workstation 17 Pro上实现Windows与UOS虚拟机之间复制粘贴文本及文件 在本教程中&#xff0c;我们将介绍如何在VMware Workstation 17 Pro中安装UOS虚拟机&#xff0c;并通过安装open-vm-tools-desktop软件来实现Windows和UOS系统之间的文本和文件复制粘贴功能。 1.…...

十一、数据库day03--SQL语句02

文章目录 一、查询语句1. 基本查询2. 条件查询2.1 ⽐较运算符&逻辑运算符2.2 模糊查询2.3 范围查询2.4 判断空 3. 其他复杂查询3.1 排序3.2 聚合函数3.3 分组3.4 分页查询 二、回顾1. 使⽤ Navicat ⼯具中的命令列2.命令⾏基本操作步骤 提示&#xff1a;以下是本篇文章正文…...

第6章 类文件结构《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》

第6章 类文件结构 代码编译的结果从本地机器码转变为字节码&#xff0c;是存储格式发展的一小步&#xff0c;却是编程语言发展的一大步。 6.1 概述 老师说过&#xff0c;计算机只认识0和1&#xff0c;所以我们写的程序需要被编译器翻译成由0和1构成的二进制格式才能被计算机…...

【Vue】模板语法与指令

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Vue 文章目录 1. Vue 模板语法基础1.1 文本插值1.2 原始 HTML1.3 属性绑定 2. Vue 指令系统2.1 条件渲染2.2 列表渲染2.3 事件处理2.4 表单输入绑定 3. 计算属性与侦听器3.1 计算属性3.2 侦听器 4. 类与样式绑定4.1 绑定 HTML 类…...

Python语法系列博客 · 第5期[特殊字符] 模块与包的导入:构建更大的程序结构

上一期小练习解答&#xff08;第4期回顾&#xff09; ✅ 练习1&#xff1a;判断偶数函数 def is_even(num):return num % 2 0print(is_even(4)) # True print(is_even(5)) # False✅ 练习2&#xff1a;求平均值 def avg(*scores):return sum(scores) / len(scores)print(…...

HashMap 初步理解 put 操作流程 HashMap 的线程安全问题

一、HashMap 核心原理 HashMap 是 Java 中最常用的哈希表实现&#xff0c;基于 数组 链表/红黑树 的复合结构&#xff0c;核心特性如下&#xff1a; 哈希函数 键的哈希值通过 hashCode() 计算&#xff0c;并通过扰动函数优化分布&#xff1a;static final int hash(Object ke…...

服务治理-服务发现和负载均衡

第一步&#xff1a;引入依赖 第二步&#xff1a;配置地址 改写购物车服务的代码 负载均衡成功实现。 假如有一个服务挂了&#xff0c;比如说8081&#xff0c;cart-service能不能正常访问&#xff0c;感知到。 再重新启动8081端口。 不管服务宕机也好&#xff0c;还是服务刚启动…...

GNU,GDB,GCC,G++是什么?与其他编译器又有什么关系?

文章目录 前言1. GNU和他的工具1.1 gcc与g1.2 gdb 2.Windows的Mingw/MSVC3.LLVM的clang/clang4.Make/CMake 前言 在开始之前我们先放一段Hello World&#xff1a;hello.c #include <stdio.h>int main() {printf("Hello World");return 0; }然后就是一段老生常…...

定制一款国密浏览器(9):SM4 对称加密算法

上一章介绍了 SM3 算法的移植要点,本章介绍对称加密算法 SM4 的移植要点。 SM4 算法相对 SM3 算法来说复杂一些,但还是比较简单的算法,详细算法说明参考《GMT 0002-2012 SM4分组密码算法》这份文档。铜锁开源项目的实现代码在 sm4.c 文件中,直接拿过来编译就可以。 但需要…...

kafka集群认证

1、安装Kerberos(10.10.10.168) yum install krb5-server krb5-workstation krb5-libs -y ​ 查看版本 klist -V ​ Kerberos 5 version 1.20.1 ​ 编辑/etc/hosts 10.10.10.168 ms1 10.10.10.150 ms2 10.10.10.110 ms3 vim /etc/krb5.conf # Configuration snippets ma…...

Mermaid 是什么,为什么适合AI模型和markdown

什么是 Mermaid&#xff1f; Mermaid 是一个基于 JavaScript 的开源绘图和图表工具&#xff0c;允许用户通过简单的文本语法创建图表。它支持生成流程图、时序图、类图、甘特图等多种类型的可视化内容&#xff0c;并直接从类似 Markdown 的代码中渲染。Mermaid 因其与 Markdow…...

为什么信号完整性对于高速连接器设计至关重要?

外部连接器通过在各种电子元件和系统之间可靠地传输数据而不损失保真度来保持信号完整性。在本文中&#xff0c;我们将讨论信号完整性的重要性&#xff0c;回顾高速部署挑战&#xff0c;并重点介绍各种连接器设计策略&#xff0c;以防止失真和降级。 了解连接器信号完整性挑战…...

【FFmpeg从入门到精通】第三章-FFmpeg转封装

1 音视频文件转MP4格式 在互联网常见的格式中&#xff0c;跨平台最好的应该是MP4文件&#xff0c;因为MP4文件既可以在PC平台的 Flashplayer 中播放&#xff0c;又可以在移动平台的 Android、ios 等平台中进行播放&#xff0c;而且使用系统默认的播放器即可播放&#xff0c;因…...

PG数据库推进医疗AI向量搜索优化路径研究(2025年3月修订版)

PG数据库推进医疗AI向量搜索优化路径研究 一、医疗 AI 向量搜索的发展现状与挑战 1.1 医疗数据特征与检索需求 医疗数据作为推动医疗领域进步与创新的关键要素,具有鲜明且复杂的特征。从多模态角度看,医疗数据涵盖了结构化数据,如患者基本信息、检验检查报告中的数值结果;…...

Android 下拉栏中的禁用摄像头和麦克风隐藏

Android 下拉栏中的禁用摄像头和麦克风隐藏 文章目录 Android 下拉栏中的禁用摄像头和麦克风隐藏一、前言二、下拉框中的禁用摄像头和麦克风隐藏实现1、设置支持属性为false2、修改代码 三、其他1、下拉栏中的禁用摄像头和麦克风隐藏小结2、 Android SensorPrivacyService ps&a…...

阿里云Clickhouse 冷热数据分层存储 实战记录

一、 背景 某业务Clickhouse库月数据增长超过2.5T&#xff0c;云上Clickhouse容量并不是无限的&#xff0c;单节点有32T上限&#xff0c;而业务已使用一半以上&#xff0c;依此速度&#xff0c;半年内就将达到上限。 与业务讨论&#xff0c;大致有以下几种解决思路&#xff1a;…...

ARINC818-实现

1.编码和解码&#xff1b;分隔符插入和删除&#xff1b;空闲idle字符插入 2.视频TX和RX接口&#xff1a;可以设计为流传输和帧同步传输 3.传输媒介&#xff1a;光纤或者铜缆 4.链路支持fc 1x,2x,3x,5x,6x,8x 上图中N有限制&#xff0c;N不能允许ADVB帧负载和填充长度不超过2112…...

OpenStack Yoga版安装笔记(23)Swift安装

一、官方文档 Object Storage Install Guide — Swift 2.29.3.dev5 documentation 二、环境准备 之前的实验&#xff0c;已经有controller, compute1, block1节点&#xff0c;并已经完成Keystone、Glance、Nova、Neutron、Cinder等主要OpenStack Service的安装。 此处新增…...

MySql 三大日志(redolog、undolog、binlog)详解

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/aa730ab3f84049638f6c9a785e6e51e9.png 1. redo log&#xff1a;“你他妈别丢数据啊&#xff01;” 干啥的&#xff1f; 这货是InnoDB的“紧急备忘录”。比如你改了一条数据&#xff0c;MySQL怕自己突然断电嗝屁了&am…...

算法题(128):费解的开关

审题&#xff1a; 本题需要我们将多组测试用例中拉灯数小于等于6的最小拉灯数输出&#xff0c;若拉灯数最小值仍大于6&#xff0c;则输出-1 思路&#xff1a; 方法一&#xff1a;二进制枚举 首先我们先分析一下基本特性&#xff1a; 1.所有的灯不可能重复拉&#xff1a;若拉的数…...