【Linux进程】进程间的通信
目录
1. 进程间通信
1.1 进程间通信的目的
2. 管道
2.1 什么是管道
2.2. 匿名管道
匿名管道的特性
管道的4种情况
联系shell中的管道
2.3. 命名管道
代码级建立命名管道
2.4. 小结
总结
1. 进程间通信
进程间通信(Inter-Process Communication,IPC)是指在操作系统中,多个进程之间进行数据交换和信息传递的一种机制。由于进程在内存中有各自的地址空间,它们不能直接访问对方的内存,因此需要通过一些特定的方法来实现通信;
1.1 进程间通信的目的
- 数据传输:一个进程需要将它的数据发送给另一个进程
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变
进程间通信的本质:让不同的进程先看到同一份资源,资源通常是由操作系统提供
进程间通信的方式也有很多:匿名管道、命名管道、共享内存、消息队列...;
本文主要介绍匿名管道、命名管道这两种进程通信;
2. 管道
2.1 什么是管道
管道是Unix中最古老的进程间通信的形式;
联系一下日常生活中的管道,水在管道中流到一般都是单向的,这里的管道也是如此,进程之间通过管道通信也是单向的;
管道(Pipes)是一种进程间通信(IPC)机制,用于在一个或多个进程之间传递数据。它通过创建一个临时的通道,允许一个进程的输出直接作为另一个进程的输入。管道主要分为两种类型:匿名管道和命名管道;
管道的通信特点就是单向的,单个管道只能进行单向通信,想要双向通信怎么办?--创建两个管道;
2.2. 匿名管道
匿名管道主要用于有亲缘关系的进程(如父子进程)之间进行通信;
最常见的就是父子进程体系:
父进程创建子进程,子进程会拷贝父进程的 struct file_struct(这里可以认为是浅拷贝);files_struct 中的内容完全和父进程相同,这样父进程和子进程就同时指向了同一块资源;
files_struct:是进程用于管理打开的文件,所描述出来的数据结构;
管道可以视为一种特殊的文件,只存在于内存中的文件;
怎么理解?一个被打开的文件通常包含三个结构:inode、方法集(虚拟文件系统)、文件缓冲区;管道也是如此;只不过他不会把缓冲区的数据刷新到磁盘中;
如上图的结构,父子进程执行的是相同的文件描述对象,如果同时对文件进行写入,是无法辨识数据是谁写入的;为了避免这样的情况,管道在设计之初,它的写入就是单向的;
比如:父进程向子进程发送数据,父进程只能往管道写入数据,子进程只能从管道读取数据;数据传输的过程和管道类似,又因为它内部所使用的文件并不会在磁盘中存在,只会在内存中使用,所以也被称为匿名管道;
#include <unistd.h>
// 功能:创建一无名管道
// 原型
int pipe(int fd[2]);
// 参数
// fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
// 返回值:成功返回0,失败返回错误代码
示例:
#include <iostream>
#include <cassert>
#include <unistd.h>
#include <cstring>
#include <sys/wait.h>
#include <sys/types.h> using namespace std; int main()
{ // 第一步:建立管道 int pipefd[2] = { 0 }; int n = pipe(pipefd); assert(n == 0); cout << "pipefd[0]:" << pipefd[0] << ", pipefd[1]:" << pipefd[1] << endl; // 第二步:创建子进程 pid_t id = fork(); if (id < 0) { perror("fork"); return 1; } // 父进程写入,子进程读取 // 第三步:关闭不需要的fd,形成单向通信的管道 else if (id != 0) // 父进程 { close(pipefd[0]); // 关闭读端 int cnt = 0; while (cnt < 10) // 发送10次 { char msg[1024]; snprintf(msg, sizeof(msg), "hello child! I am father, pid: %d, cnt: %d", getpid(), cnt); cnt++; if (write(pipefd[1], msg, strlen(msg)) < 0) { perror("write"); break; // 处理写入错误 } sleep(1); } cout << "father close write point" << endl; close(pipefd[1]); // 关闭管道写端 pid_t rid = waitpid(id, nullptr, 0); if (rid == id) { cout << "wait success !" << endl; } } else // 子进程 { close(pipefd[1]); // 关闭写端 char buffer[1024]; while (true) { ssize_t n = read(pipefd[0], buffer, sizeof(buffer) - 1); // 预留一个位置给字符串结尾添加'\0' if (n > 0) { buffer[n] = '\0'; // 添加字符串结束符 cout << getpid() << ", father says: " << buffer << " to me!" << endl; } else if (n == 0) { cout << "write quit, me too !" << endl; break; // 读到EOF } else { perror("read"); break; // 处理读取错误 } sleep(1); } cout << "read point close" << endl; close(pipefd[0]); sleep(5); exit(0); } return 0;
}
在文件描述符的视角:
1. 父进程创建管道
开始父进程创建管道,以读方式打开一次以写方式打开一次,打开两次;
2. 父进程创建子进程
父进程创建子进程,子进程继承父进程的属性,也可以对管道也可以进行读和写;
3. 父进程关闭读端、子进程关闭写端
实现单向时,比如父进程向子进程传输数据;父进程关闭读方式打开的文件,子进程关闭写方式打开的文件这样就形成了单向信道;
实际情况:
事实上,父进程以写方式打开管道文件(写端),然后再以读方式打开同一个管道文件(读端),实际上会创建两个不同的文件描述符对象,分别指向管道的写端和读端;
在Linux环境下,两个文件描述符最终会指向同一个inode,共享相同的方法集和缓冲区;
问题来了,父进程以写的方式打开文件,又以读的方式打开文件,单向通信时,父进程需要关闭读方式打开的文件,子进程关闭以写方式打开的文件,父进程关一个,子进程关一个,这样这两个文件描述对象不就没了吗?这还怎么通信?
这样的类似的问题我们之前也遇到过,如何解决呢?--引用计数的方法所以在struct file中有一个类似于引用计数的概念;一个进程关闭一个文件时,引用计数就减一;当一个文件描述对象它的引用计数为0时,它就会自动把文件关掉;
fork创建子进程时,子进程可以读取到父进程的数据,那为什么还要大费周章的这样传输数据?
子进程确实可以通过fork进程父进程的数据,但那也只是在创建时读取到,它无法读取到变化的数据如果任意一方写入修改数据,就会发生写时拷贝;
匿名管道的特性
管道的五种特性:
- 匿名管道,可以允许具有血缘关系的的进程之间进行进程间通信,常用于父与子;
- 匿名管道默认给读写端提供同步机制;
- 面向字节流;
- 管道的生命周期是随进程的;
- 管道是单向通信的,半双工通信的一种特殊情况;
如何去理解?
比如:在以前,在shell中执行父子进程,父子进程各自执行自己的,互不干涉;而匿名管道这里,默认存在读写同步机制;
情况一:子进程写,父进程读,但子进程写的慢;会出现管道中没有数据,此时读端必须等待,直到有数据为止;
情况二:子进程写的快,父进程读的慢;子进程也会等待父进程,子进程会写一部分,然后等父进程读取,读取之后再写;
怎么写和怎么读之间没有什么关系,并不是写一条,读一条;子进程写的快,父进程读的慢,父进程可能一次就读子进程写的几十次或者上百次的数据都读出来,“可以一次只读一个字节,也可以定义一个缓冲区一次就把缓冲区全打满;
管道的4种情况
- 正常情况,如果管道没有数据了,读端必须等待,直到有数据为止
- 正常情况,如果管道被写满了(管道大小约为64kB),写端必须等待,直到有空间为止
- 写端关闭,读端一直读取,当read返回值为0,表示读到文件结尾
- 读端关闭,写端一直写入,OS会直接杀掉写端进程,通过想目标进程发送SIGPIPE(13)信号,终止目标进程;
联系shell中的管道
shell中经常使用的管道 ” | “;
比如:
sleep 1000 | sleep 2000 | sleep 3000
通过上述的测试命令,可以看到sleep之间是兄弟进程,那么它们的原理是什么?
上述测试命令:3个兄弟进程,使用两个管道;父进程先创建管道,因此两个管道对于这个三个进程都是可见的,然后再使用fork创建子进程;
对于进程1,关闭其他的文件,只保留pipefda[1](写);
进程2,只保留对pipefda[0](读)以及对pipefdb[1](写);
进程3,只保留对pipefdb[0](读);
其次就是重定向,在使用管道时,原本要输出在显示器的数据没有显示,而是作为输入,传输给了第二个进程,把进程1的 stdout 重定向为 pipefda[1];(dup2(pipefda[1],1]))
让进程2的输入从管道中读取,所以我们也需要对进程2进行重定向,后续的读写也是需要进行重定向,以此类推;
2.3. 命名管道
上述介绍的匿名管道通信,是用于亲缘关系之间的进程进行通信,如果没有任何关联的进程如何通信呢? --命名管道,都是在内存中作用;
命名管道简单示例:
两个终端实现通信:
终端一:
终端二:
命名管道可以从命令行上创建
命令:mkfifo filename
命名管道是一种特殊类型的文件,它在文件系统中有对应的文件节点,但实际上并不占用磁盘空间存储数据;
两进程之间要想实现通信,那么就需要看到同一份资源;
命名管道(Named Pipe)在文件系统中有对应的文件节点,因此它是存在磁盘中的;
路径是唯一的,所以可以使用路径+文件名访问,让不同的进程来访问相同的资源;
当进程访问命名管道时,操作系统会为该进程创建文件描述符,并为管道在内存中创建缓冲区。数据通过管道在进程间传输时,会经过内存缓冲区进行交换,而不会把数据加载到磁盘;
通信原理:
由此我们也可以发现命名管道的文件节点存放在磁盘中的意义:为了让没有血缘关系的进程能够找到命名管道,进而使得两进程可以访问同一个管道;
代码级建立命名管道
接口:
int mkfifo(const char *filename,mode_t mode);
创建成功返回0,失败返回-1;
有了这些可以模拟的写一个使用命名管道通信的服务端和客户端:
服务端:
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstring>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include "comm.h"
// 服务端
//using namespace std;#define FILENAME "fifo"int Makefifo()
{int n = mkfifo(FILENAME, 0666);if (n < 0){std::cerr << "error: " << errno << " errorstring: " << strerror(errno) << std::endl;return false;}std::cout << "mkfifo success... " << std::endl;return true;
}
int main()
{
Start:// 打开管道文件int rfd = open(FILENAME, O_RDONLY);if (rfd < 0){std::cerr << "error: " << errno << " errorstring: " << strerror(errno) << std::endl;if (Makefifo()) goto Start;else return 1;//return 2;}std::cout << "open fifo success...read " << std::endl;char buffer[1024];while (true){//读取管道数据ssize_t s = read(rfd, buffer, sizeof(buffer) - 1); // 预留一个空间给\0if (s > 0){buffer[s] = 0; //把最后设置为\0表示字符串的结尾std::cout << "Client say: " << buffer << std::endl;}else if (s == 0){std::cout << "Client quit,server quit too " << std::endl;break;}}// 关闭文件close(rfd);std::cout << "close fifo success... " << std::endl;return 0;
}
这里需要特别注意,创建命名管道时,最好先以读方式打开;
先让读端创建好,此时读端会阻塞等待;直到写端打开管道为止;
这种行为保证了在读端尝试读取数据之前,有写端可以向管道写入数据。读端会等待写端打开,以确保有效的通信;
如果是写端先创建好,就可能出现这种情况:
写端先创建好,向管道写数据,但此时读端还未创建好,就会导致程序被OS杀死;
客户端:
#include <iostream>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstring>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include "comm.h"
// 客户端int main()
{int wfd = open(FILENAME, O_WRONLY);if (wfd < 0){std::cerr << "error: " << errno << " errorstring: " << strerror(errno) << std::endl;return 1;}std::cout << "open fifo success...write " << std::endl;std::string msg;while (true){std::cout << "Please Enter#";std::getline(std::cin, msg);//读取客户端一行的输入信息ssize_t s = write(wfd, msg.c_str(), msg.size());//把数据写入到管道中if (s < 0){std::cerr << "error: " << errno << " errorstring: " << strerror(errno) << std::endl;break;}}close(wfd);std::cout << "close fifo success... " << std::endl;return 0;
}
2.4. 小结
命名管道与匿名管道的区别:
- 匿名管道由pipe函数创建并打开。
- 命名管道由mkfifo函数创建,打开用open
- FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完 成之后,它们具有相同的语义;
- 命名管道用于没有任何关系的进程之间进行通信;
- 匿名管道用于有亲缘关系的进程之间进行通信
- 命名管道的文件节点会存储在磁盘中,但管道数据并不会存在磁盘中;
管道的四种情况:
- 正常情况,如果管道没有数据了,读端必须等待,直到有数据为止
- 正常情况,如果管道被写满了(管道大小约为64kB),写端必须等待,直到有空间为止
- 写端关闭,读端一直读取,当read返回值为0,表示读到文件结尾
- 读端关闭,写端一直写入,OS会直接杀掉写端进程,通过想目标进程发送SIGPIPE(13)信号,终止目标进程;
总结
以上便是本文的全部内容,希望对你有所帮助或启发,后续也将会继续介绍其他进程间通信的方式,感谢阅读!
相关文章:
【Linux进程】进程间的通信
目录 1. 进程间通信 1.1 进程间通信的目的 2. 管道 2.1 什么是管道 2.2. 匿名管道 匿名管道的特性 管道的4种情况 联系shell中的管道 2.3. 命名管道 代码级建立命名管道 2.4. 小结 总结 1. 进程间通信 进程间通信(Inter-Process Communication,IPC&…...
面试题整理4----lvs,nginx,haproxy区别和使用场景
LVS、Nginx、HAProxy:区别与使用场景 1. LVS(Linux Virtual Server)1.1 介绍1.2 特点1.3 使用场景 2. Nginx2.1 介绍2.2 特点2.3 使用场景 3. HAProxy3.1 介绍3.2 特点3.3 使用场景 4. 总结对比 在构建高可用、高性能的网络服务时,…...
开放词汇目标检测(Open-Vocabulary Object Detection, OVOD)综述
定义 开放词汇目标检测(Open-Vocabulary Object Detection, OVOD)是一种目标检测任务,旨在检测和识别那些未在训练集中明确标注的物体类别。传统的目标检测模型通常只能识别有限数量的预定义类别,而OVOD模型则具有识别“开放词汇…...
Python读写JSON文件
import jsondef writeJSONFile(self):with open(g_updateFilePath, "w" encodingutf-8) as fiel:json.dump(dictData, fiel, indent4, ensure_asciiFalse)fiel.close()def readJsonToDict(file):with open(file, r, encodingutf-8) as f: # 确保文件以 UTF-8 编码打…...
使用Python开发高级游戏:创建一个3D射击游戏
在这篇文章中,我们将深入介绍如何使用Python开发一个简单的3D射击游戏。我们将使用Pygame库来创建2D游戏界面,并结合PyOpenGL来进行3D渲染。这个项目的目标是帮助你理解如何将2D和3D图形结合起来,创建更复杂的游戏机制,包括玩家控制、敌人AI、碰撞检测和声音效果。 一、开…...
springboot 配置Kafka 关闭自启动连接
这里写自定义目录标题 springboot 配置Kafka 关闭自启动连接方法一:使用 ConditionalOnProperty方法二:手动管理Kafka监听器容器方法三:使用 autoStartupfalse结语 springboot 配置Kafka 关闭自启动连接 在Spring Boot应用程序中,…...
Jenkins中添加节点实战
Jenkins是一个开源的自动化服务器,用于持续集成和持续交付(CI/CD)。为了提高构建和测试的效率,我们可以在Jenkins中添加节点(也称为代理或从属节点)。本文将详细介绍如何在Jenkins中添加节点,包括安装Java 11、Git、设置凭证、多种配置Jenkins Agent的方法以及验证。 …...
DL作业11 LSTM
习题6-4 推导LSTM网络中参数的梯度, 并分析其避免梯度消失的效果 LSTM(长短期记忆网络)是一种特殊的循环神经网络(RNN),旨在解决普通 RNN 在处理长序列时遇到的梯度消失和梯度爆炸问题。它通过设计多个门…...
用 Python 实现井字棋游戏
一、引言 井字棋(Tic-Tac-Toe)是一款经典的两人棋类游戏。在这个游戏中,玩家轮流在 3x3 的棋盘上放置自己的标记,通常是 “X” 和 “O”,第一个在棋盘上连成一线(横、竖或斜)的玩家即为获胜者。…...
构建MacOS应用小白教程(打包 签名 公证 上架)
打包 在package.json中,dependencies会被打进 Electron 应用的包里,而devDependencies则不会,所以必要的依赖需要放到dependencies中。files中定义自己需要被打进 Electron 包里的文件。以下是一个完整的 mac electron-builder的配置文件。 …...
如何高效使用 Facebook Business Manager (商务管理平台)
在数字营销的浪潮中,Facebook Business Manager(商务管理平台)已成为众多企业管理社交广告活动、品牌资产和团队协作的核心工具。无论你是刚刚进入社交广告领域的小型企业主,还是经验丰富的大型品牌经理,掌握 Facebook…...
每天学习一个思维模型 - 损失规避
定义 损失规避(Loss aversion),又称损失厌恶,指人们面对同样数量的利益和损失时,认为损失更加令他们难以忍受。损失带来的负效用为收益正效用的2至2.5倍。损失厌恶反映了人们的风险偏好并不是一致的,当涉及…...
Python知识分享第三十一天-Numpy和Pnadas入门
NumPy Numpy介绍 Numpy是Python中科学计算的基础包,它是一个Python库提供多维数组对象 各种派生对象(如掩码数组和矩阵),以及用于对数组进行快速的各种例程,包括数学 ,逻辑, 形状操作,排序,选择,I/O,离散傅里叶变换,基本线性代数,基本统计运算,随机模拟等等(Numpy的核心是nda…...
mlr3超参数Hyperparameter 自动寻找auto
底层还是根据你本来在R跑单独那一个机器学习的函数,例如randomForest::randomForest(),里面可以填入什么,然后跟你的实际数据取值范围去设个范围。然后用auto_tuner()函数对学习器的超参数自动调参 随机森林randomforest learner_rf <- …...
双臂机器人
目录 一、双臂机器人简介 二、双臂机器人系统的组成 三、双臂机器人面临的主要挑战 3.1 协调与协同控制问题 3.2 力控制与柔顺性问题 3.3 路径规划与轨迹优化问题 3.4 感知与环境交互 3.5 人机协作问题 3.6 能源与效率问题 3.7 稳定性与可靠性问题 四、双臂机器人…...
MATLAB中cvx工具箱的使用
CVX 是 MATLAB 中一个用于解决凸优化问题的建模工具箱。它使得定义、求解和分析凸优化问题变得简单。CVX 允许用户用类似数学表达的方式编写凸优化问题,而不需要过多关注底层的优化算法。CVX 的核心功能是将一个简单的数学问题转化为 MATLAB 可以理解并求解的标准形…...
EGO Swarm翻译
目录 摘要 Ⅰ 介绍 Ⅱ 相关工作 A . 单四旋翼局部规划 B . 拓扑规划 C. 分布式无人机集群 Ⅲ 基于梯度的局部规划隐式拓扑轨迹生成 A.无需ESDF梯度的局部路径规划 B.隐式拓扑轨迹生成 Ⅳ 无人机集群导航 A 机间避碰 B. 定位漂移补偿 C. 从深度图像中去除agent Ⅴ …...
Webpack简单介绍及安装
一、介绍 Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。它将应用程序中的所有依赖项(JavaScript、图片、CSS 等)打包成一个或多个 bundle。这样做的主要目的是减少加载时间和提高应用程序的加载性能…...
如何在Anaconda的虚拟环境中下载Python包
一、首先查看conda下的虚拟环境 使用conda info -e查看当前conda下的虚拟环境: conda info -e 二、激活要添加Python包的虚拟环境 其中base是基础环境,这里我们选择conda_env这个虚拟环境 conda activate conda_env 三、使用conda命令安装需要的Pyth…...
React 事件机制和原生 DOM 事件流有什么区别
发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。 React 的事件机制与原生 DOM 事件流在设计和实现上有一些显著的区别。了解这些区别有助于我们更好地理解 React 是如何管理事件的…...
React 底部加载组件(基于antd)
底部加载组件的意义在于提供一种流畅的用户体验,以便在用户滚动到页面底部时自动加载更多内容。这样可以让用户无需离开当前页面,就能够无缝地浏览更多的内容.通过底部加载组件,可以分批加载页面内容,减少一次性加载大量数据对页面…...
Redis应用—7.大Value处理方案
1.⽅案设计 步骤一:首先需要配置一个crontab定时调度shell脚本,然后该脚本每天凌晨会通过rdbtools⼯具解析Redis的RDB⽂件,接着对解析出的内容进行过滤,把RDB⽂件中的⼤key导出到CSV⽂件。 步骤二:使⽤SQL导⼊CSV⽂件到…...
洛谷P2742 圈奶牛 (凸包 Andrew算法)
[USACO5.1] 圈奶牛Fencing the Cows /【模板】二维凸包 题目背景 upd: 新增一组 hack 数据。 题目描述 农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算…...
Spring(一)---IOC(控制权反转)
目录 引入 1.什么叫IOC(Inversion of Control)控制权反转? 2.什么叫AOP(Aspect-Oriented Programming)面向切面编程(涉及Java代理)? 3.简单谈一下Java怎么实现ICO? Spring框架的介绍 1. Spring框架的概述 2. Spring框架的优点 Spring IOC容器介绍…...
MySQL数据库——门诊管理系统数据库数据表
门诊系统数据库his 使用图形化工具或SQL语句在简明门诊管理系统数据库his中创建数据表,数据表结构见表2-3-9~表2-3-15所示。 表2-3-9 department(科室信息表) 字段名称 数据类型 长度 是否为空 说明 dep_ID int 否 科室…...
linux环境使用yum方式安装nginx
linux环境使用yum方式安装nginx 一、nginx官网 二、nginx安装 点击首页的 Docs 或者 install 都可以,最终都是进入到Installing nginx页面 因为安装的服务器环境是linux centos 所以选择 Installation on Linux下面 packages 跳转链接 点击packages后 最终会跳转…...
2024高级前端面试题大全
🎨 1、v-bind指令绑定所有属性 <comp :title"title" :color"color" /><comp v-bind"props" />🎨 父组件监听字组件渲染周期:hook:updated文章地址🎨 Vue3 defineAsyncComponent动态导…...
[机器学习]XGBoost(3)——确定树的结构
XGBoost的目标函数详见[机器学习]XGBoost(2)——目标函数(公式详解) 确定树的结构 之前在关于目标函数的计算中,均假设树的结构是确定的,但实际上,当划分条件不同时,叶子节点包含的…...
Hutool工具包的常用工具类的使用介绍
前言 Hutool 是一个轻量级的 Java 工具类库,提供了非常丰富的工具方法,可以大大减少开发时的重复性工作。它的目标是让 Java 开发更简单、更高效。Hutool 提供了多种常用功能,以下是一些常用工具类的使用介绍: 1. StrUtil - 字符…...
ETCD备份还原
环境准备: master 192.168.8.128 node1 192.168.8.129 k8s版本: 一:安装etcdctl工具 1.1下载安装包: wget https://github.com/etcd-io/etcd/releases/download/v3.4.13/etcd-v3.4.13-linux-amd64.tar.gz 1.2解压&…...
服务器防火墙设置某个端口号只允许固定 ip地址访问
服务器防火墙设置某个端口号只允许固定 ip地址访问是运维常见的功能,今天我们分享一下: 一、Linux环境 1、firewall 方式 1)允许特定 IP 地址访问 23 端口 sudo firewall-cmd --zonepublic --add-rich-rulerule family"ipv4" s…...
FPGA 基础了解
前言 前期一直在做关于FPGA方面的开发,从开始认真玩FPGA到参考原子、野火、黑金、米联客的教学资料再到参与做项目中,中途也参加了两个比赛整也都获得不错的成绩,整个阶段持续了大概快一年半的时间,学习了乱七八糟的知识…...
Golang学习历程【第二篇 fmt包变量、常量的定义】
Golang学习历程【第二篇 fmt包&变量、常量的定义】 1. fmt 包1.1 打印(print)1.1.1 Print 打印1.1.2 Println 打印后换行1.1.3 Printf 打印格式化参数 1.2 输入(Scan)1.2.1 Scan 输入1.2.2 Scanf 格式化输入 2. 变量2.1 变量的声明2.2 变量初始化&am…...
深入QML语法
文章目录 深入了解 QML 文档的结构和语法什么是 QML 文档?导入语句导入语句的格式示例 对象声明基本语法示例更复杂的对象声明 QML 对象类型详解1. Rectangle(矩形)2. Gradient(渐变)3. Text(文本ÿ…...
Viggle Api上线V3-beta模型,圣诞节跳舞视频来临
历史文章 Suno AI API接入 - 将AI音乐接入到自己的产品中,支持120并发任务 万物皆能舞,AI让你秒变“舞”林高手 – Viggle AI“舞”所不能 Viggle AI:打造爆款 AI 视频,让照片 “踢” 起足球 又一款AI对口型神器,让…...
前端excel的实现方案Luckysheet
一、介绍 Luckysheet是一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源的插件。目前已暂停维护,但是其已有功能大概能满足常见需求的使用。 二、引入 ①cdn引入(目前应该已经不支持,可自行尝试) <l…...
数据字典类型/条目表的设计目的
1.以前的设计思路 对于下拉框选项储存的思路 我们以前是直接针对每一个下拉框都关联一个表格于数据库中 这种行为很不妥当 如果对于不同业务情景下的相同下拉框来说 多个相同下拉框就会在数据库中产生多个表格 当某个下拉框的选项需要更新或者新增时 那么对应的需要同步更新相…...
abc 383 C (bfs 最短路 )D(唯一分解定理,欧拉筛)
C 题: 首先暴力的想,对于每一个加湿器的位置去 上下左右扩展是 nm 的复杂度 。最多会有 nm 个加湿器。所以复杂度到达了n^3 。肯定超时了。 我们可以发现 对于一个点 会标记很多次,这回导致超时。 可以采用类似 bfs 求最短路的形式ÿ…...
常用消息中间件介绍
在消息中间件这个领域,确实有不少专业且强大的选择,它们各自都有着独特的优势和适用场景。 1. Apache Kafka: • Kafka以其高吞吐量、低延迟和分布式架构著称,非常适合处理大数据量、实时性要求高的场景。 • 它支持发布/订阅模式…...
vue基础
1.v-text,v-html <!-- v-text,v-html都可以显示内容 ,v-html可以解析html标签--> <p>{{msg}}</p> <p v-text"msg"></p> <p v-html"msg"></p> <script> let appnew Vue({ el:"#max", data:{ ms…...
从Windows远程访问Linux上的数据库
从Windows远程访问Linux上的数据库 目录 简介在Linux上安装MySQL/MariaDB配置MySQL/MariaDB以允许远程连接 修改MySQL/MariaDB配置文件重启MySQL/MariaDB服务确保防火墙允许MySQL/MariaDB端口 创建远程访问用户授予用户权限测试远程连接 检查网络连通性使用图形化工具连接 创…...
Android HandlerThread、Looper、MessageQueue 源码分析
Android HandlerThread、Looper、MessageQueue 源码分析 简介 在 Android 开发中,大家应该对 HandlerThread 有一定了解。顾名思义,HandlerThread 是 Thread 的一个子类。与普通的 Thread 不同,Thread 通常一次只能执行一个后台任务&#x…...
ASP.NET |日常开发中定时任务详解
ASP.NET |日常开发中定时任务详解 前言一、定时任务的概念与用途1.1 定义1.2 应用场景 二、在ASP.NET中实现定时任务的方式2.1 使用System.Timers.Timer2.2 使用Quartz.NET 三、定时任务的部署与管理3.1 部署考虑因素3.2 管理与监控 结束语优质源码分享 ASP.NET &am…...
Unity动态读取外部图片转Texture2D,内存过大问题解决方案
问题描述 加载原始图片2.63M的图片,分辨率为3023*4032,占用内存108.5M 加载原始图片12.6 M的图片,分辨率为6000*8000,占用内存427.2M 太恐怖了吧 解决方案 1.加载完图片,等比缩放,宽高改为1024或者512以下 1024占用5.2M,512占用1.3M,相比小了很多 2.原始Texture2…...
【Where语法全解密】.NET开源ORM框架 SqlSugar 系列
文章目录 前言一、普通表达式查询 Where二、根据SQL查询 where三、动态查询四、动态拼表达式查询 ,拼拉姆达五、条件拼接查询六、链式条件查询七、根据Class查询,根据实查询八、根据Class中主键查询九、根据字典查询十、查询函数十一、Where中有子查询十…...
人工智能练习题--大题题库速通指南
随着人工智能(AI)技术的快速发展,越来越多的企业和个人开始重视AI的应用和发展。在这个背景下,人工智能训练师这一职业应运而生,他们专注于数据标注、模型训练、算法优化等方面的工作,以确保AI系统能够准确…...
写给Pythoner的前端进阶指南(四):异步编程 - 原生支持的 async/await
在开发中,异步编程是处理并发任务的重要方式。无论是请求数据、读取文件还是执行网络操作,异步编程能够有效提升程序的性能和响应速度。Python 和 JavaScript 都支持异步编程,但它们的实现方式有所不同。在这篇文章中,我们将深入探…...
项目搭建+姓名唯一性校验
一 : 添加时对姓名进行唯一性校验 ① : 给姓名绑定一个改变事件 ② : 取值 ③ : 组装对象 ④ : ajax (Controller定义对姓名唯一性校验的方法) 在成功回调函数里 判断姓名是否添加过(0>已添加 1>未添加) 未添加过,添加成功后,(清空) /*** 对姓名进行唯一性校验*/$("…...
MacOS下PostIn安装配置指南
PostIn是一款开源免费的接口管理工具, 下面介绍私有部署版本的MacOS下安装与配置。私有部署版本更适合有严格数据安全要求的企业,实现对数据和系统的完全控制。   1、MacOS服务端安装 Mac安装包下载地址:下载Mac安…...
时光回响,中原之声 ——漓岛⾳乐节x SONICE
音乐像呼吸一样在大地起伏,中原的回响透过时空,从遥远的内陆弥漫扩散至温暖的南方,年轻的呼唤似一阵快雨淋落在辽阔的海面,波澜游弋,终掀浪涛。来自中原的独立音乐厂牌SONICE将与澄迈漓岛音乐节联合呈现乘风舞台&#…...