Linux基础-shell的简单实现
个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创Linux基础-shell的简单实现
收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌
目录
1, 全局变量和常量定义
2. 环境信息获取
2.1 GetUserName
2.2 GetHostName
2.3 GetPwd
2.4 LastDir
3. 命令行提示符
3.1 MakeCommandLine
3.2 PrintCommandLine
4, 命令输入处理
4.1 GetCommandLine
4.2 ParseCommandLine
5. 命令调试
5.1 debug
6. 命令执行
6.1 ExecuteCommand
子进程执行命令:
等待子进程结束:
处理子进程的返回状态:
7. 环境变量管理
7.1 AddEnv
7.2 InitEnv
8. 内建命令处理
8.1 CheckAndExeBuiltCommand
8.1.1 cd命令
8.1.2 export命令
8.1.3 evn命令
8.1.4 echo命令
8.2 为什么使用内建命令
9. 主函数
10. 效果展示:
1, 全局变量和常量定义
功能 : 定义常量和全局变量,包括命令行参数、环境变量、当前工作目录、和最近的命令执行状态代码。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;const int basesize = 1024;
const int argvnum = 64;
const int envnum = 64;//全局的命令行参数
char *gragv[argvnum];
int gargc = 0;//全局变量
int lastcode = 0;//我的系统的环境变量
char *genv[envnum];//全局的当前shell工作路径
char pwd[basesize];
char pwdenv[basesize];
basesize: 定义了缓冲区的基础大小,用于存储用户输入的命令和路径。
argvnum: 定义最大命令行参数的数量。
envnum: 定义最大环境变量的数量。
gargv: 存储解析后的命令行参数的数组。
gargc: 表示当前解析出的参数数量。
lastcode: 保存最近执行命令的退出状态。
genv: 存储环境变量的数组。
pwd 和 pwdenv: 存储当前工作目录和环境变量PWD的缓冲区。
2. 环境信息获取
功能 : 获取当前用户、主机名和当前工作目录的信息,返回相应的字符串。
2.1 GetUserName
GetUserName: 获取当前用户的用户名,使用getenv从环境变量中获取,若未获取到,则返回"None"。
string GetUserName()
{string name = getenv("USER");return name.empty() ? "None" : name;
}
2.2 GetHostName
GetHostName: 获取主机名,类似于获取用户名的方式。
string GetHostName()
{string hostname = getenv("HOSTNAME");return hostname.empty() ? "None" : hostname;
}
2.3 GetPwd
GetPwd: 获取当前工作目录,使用getcwd函数获取并更新环境变量PWD。如果获取失败,返回"None"。
string GetPwd()
{if (nullptr == getcwd(pwd, sizeof(pwd)))return "None";snprintf(pwdenv, sizeof(pwdenv), "PWD=%s", pwd);putenv(pwdenv);return pwd;
}
补充知识:
snprintf 是一个安全的字符串格式化函数,用于将格式化的数据写入字符串。
pwdenv 是另一个字符数组,用于存储更新后的环境变量字符串。
这里,"PWD=%s" 是格式化字符串,%s 被当前工作目录的值(即 pwd 中的值)替换。最终结果类似于 PWD=/home/user(假设当前工作目录是 /home/user)。
putenv 是一个函数,用于设置环境变量。
通过调用 putenv(pwdenv),将之前构造的环境变量字符串 PWD=/path/to/current/dir 添加到进程的环境中。
注意,使用 putenv 要确保 pwdenv 的内容在后续使用中依然有效,因为 putenv 不会复制传入的字符串。
2.4 LastDir
LastDir: 从当前路径中提取最后一个目录名称,方便在命令行提示符中显示。
string LastDir()
{string curr = GetPwd();if (curr == "/" || curr == "None")return curr;size_t pos = curr.rfind("/");if (pos == std::string::npos)return curr;return curr.substr(pos + 1);
}
注意 : 这里curr == "/" || curr == "None" 我们都不需要额外处理, 直接返回就行, 因为curr为"/" 表示根目录, 为None时, 我们直接返会空就行
3. 命令行提示符
功能:生成和打印命令行提示符,包含用户、主机和当前目录信息。
3.1 MakeCommandLine
MakeCommandLine: 生成当前命令行提示符的字符串格式,包括用户、主机和当前目录。
string MakeCommandLine()
{//[XXX@XXXXX myshell]$ 这里就与普通命令行进行区分char command_line[basesize];snprintf(command_line, basesize, "[%s@%s %s]#", GetUserName().c_str(), GetHostName().c_str(), LastDir().c_str());return command_line;
}
3.2 PrintCommandLine
PrintCommandLine: 打印生成的命令行提示符到标准输出。
void PrintCommandLine()
{printf("%s", MakeCommandLine().c_str());fflush(stdout);
}
4, 命令输入处理
功能:从标准输入获取用户输入的命令,并解析成命令及其参数。
4.1 GetCommandLine
GetCommandLine: 从标准输入获取用户的命令行输入,使用fgets读取并处理换行符。
bool GetCommandLine(char command_buffer[], int size)
{//我们认为 : 我们要将用户出入的命令行 -> 当作一个完整的字符串//"ls -a -1 -n"char* result = fgets(command_buffer, size, stdin);if(!result){return false;}command_buffer[strlen(command_buffer) - 1] = 0;if(strlen(command_buffer) == 0) return false;return true;
}
补充知识:
fgets 是一个标准库函数,用于从标准输入(stdin)读取一行字符,最多读取 size - 1 个字符,并将其存储在 command_buffer 中。
fgets 会在读取到换行符 ('\n') 或 EOF(文件结束符)时停止读取,并会在 command_buffer 的末尾自动添加一个空字符 ('\0')。
如果成功读取,result 将指向 command_buffer;如果失败(例如,输入错误或 EOF),result 将为 nullptr。
注意: strlen(command_buffer) - 1 获取字符串的最后一个字符(换行符)的索引,并将其设为 0,以去掉换行符。
比如:我们输入 ls -a -l -n
fgets 会将缓冲区填充为: command_buffer = "ls -a -l -n\n\0"
经过strlen(command_buffer) - 1处理后 : "ls -a -l -n\0"
4.2 ParseCommandLine
ParseCommandLine: 使用strtok将输入的命令行字符串分割为单独的命令和参数,并存储在gargv数组中。
void ParseCommandLine(char command_buffer[], int len)
{(void)len;memset(gargv, 0, sizeof(gargv));gargc = 0;//"ls -a -l -n"const char *sep = " ";gargv[gargc++] = strtok(command_buffer, sep);//=是刻意写的while((bool)(gargv[gargc++] = strtok(nullptr, sep)));gargc--;
}
补充知识:
strtok 函数会将 command_buffer 字符串中的第一个分隔符(空格)替换为 \0,并返回指向第一个标记的指针,存储到 gargv 数组中。
strtok(nullptr, sep) 意味着继续解析之前传入的字符串。
注意 (bool) 转换是为了确保表达式的结果为布尔值,这样可以明确表示循环的条件。
5. 命令调试
5.1 debug
功能 : 输出当前命令参数的数量和每个参数的值,以帮助开发和调试。
void debug()
{printf("argc: %d\n", gargc);for(int i = 0; gargv[i]; i++){printf("argv[%d]: %s\n", i, gargv[i]);}
}
6. 命令执行
6.1 ExecuteCommand
功能:通过fork()和execvpe()创建子进程执行用户命令,并等待其完成。
bool ExecuteCommand()
{//让子进程进行执行pid_t id = fork();if(id < 0) return false;if(id == 0){//子进程//1. 执行命令execvpe(gargv[0], gargv, genv);//2. 退出exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){if(WIFEXITED(status)){lastcode = WEXITSTATUS(status);}else{lastcode = 100;}return true;}return false;
}
子进程执行命令:
execvpe(gargv[0], gargv, genv);:execvpe 用于执行指定的命令。它会用新的程序替换当前进程(子进程)。参数说明:
gargv[0]:命令的名称(通常是命令的路径)。
gargv:一个字符串数组,包含传递给命令的参数。
genv:一个字符串数组,包含环境变量。
如果 execvpe 成功,当前进程(子进程)将被新的程序替换,之后的代码将不会执行。
如果 execvpe 失败(例如命令未找到),子进程将执行 exit(1),返回状态 1,以指示错误。
等待子进程结束:
int status = 0;:用于存储子进程的退出状态。
waitpid(id, &status, 0):在父进程中调用,等待指定的子进程(由 id 指定)结束。结果存储在 status 变量中。
返回值 rid:如果成功,返回已结束子进程的 PID;如果失败,返回 -1。
处理子进程的返回状态:
if(rid > 0):确认 waitpid 调用成功,rid 应该是大于 0 的子进程 PID。
WIFEXITED(status):这个宏检查子进程是否正常退出(通过 exit() 或 return 语句)。
WEXITSTATUS(status):如果子进程正常退出,获取其返回状态并将其存储在 lastcode 中。
如果子进程未正常退出(例如由于信号导致的终止),则将 lastcode 设置为 100,这通常用于指示异常情况。
return true;:表示成功执行命令并处理了其退出状态。
7. 环境变量管理
功能:动态分配内存,将新的环境变量添加到genv数组中。
7.1 AddEnv
void AddEnv(const char* item)
{int index = 0;while(genv[index]){index++;}genv[index] = (char*)malloc(strlen(item) + 1);strncpy(genv[index], item, strlen(item) + 1);genv[++index] = nullptr;
}
功能 : 添加环境变量:该函数接受一个字符串 item 作为参数,并将其添加到 genv 环境变量数组中。
逐行分析
int index = 0;:初始化索引为 0,用于遍历 genv 数组。
while(genv[index]):遍历 genv 数组,直到找到第一个空指针,表示可以插入新环境变量的位置。
genv[index] = (char*)malloc(strlen(item) + 1);:
为新的环境变量分配内存。malloc 分配的内存大小为 item 字符串的长度加 1(为字符串结束符 \0 留出空间)。
strncpy(genv[index], item, strlen(item) + 1);:
将 item 的内容复制到 genv[index] 中。使用 strncpy 复制到长度 strlen(item) + 1,确保包含字符串结束符。
genv[++index] = nullptr;:
在数组中下一个位置设置为 nullptr,标志着环境变量的结束。
7.2 InitEnv
void InitEnv()
{extern char **environ;int index = 0;while(environ[index]){genv[index] = (char*)malloc(strlen(environ[index] + 1));strncpy(genv[index], environ[index], strlen(environ[index] + 1));index++;}genv[index] = nullptr;
}
功能 : 初始化环境变量:该函数从系统环境变量中读取所有环境变量并将其存储在 genv 数组中。
逐行分析
extern char **environ;:声明外部变量 environ,这是一个指向环境变量字符串数组的指针
int index = 0;:初始化索引为 0,用于遍历 environ。
while(environ[index]):遍历 environ 数组,直到找到第一个空指针,表示所有环境变量都已读取。
genv[index] = (char*)malloc(strlen(environ[index]) + 1);:
为每个环境变量分配内存。这里 strlen(environ[index]) 计算字符串的长度,并加 1 来包含 \0 结束符。
strncpy(genv[index], environ[index], strlen(environ[index] + 1));:
将 environ[index] 的内容复制到 genv[index] 中。这里同样存在一个错误,应该是 strncpy(genv[index], environ[index], strlen(environ[index]) + 1);。
index++;:增加索引,以便处理下一个环境变量。
genv[index] = nullptr;:在数组最后设置 nullptr,表示环境变量的结束
8. 内建命令处理
8.1 CheckAndExeBuiltCommand
bool CheckAndExeBuiltCommand()
{if(strcmp(gargv[0], "cd") == 0){//内建命令if(gargc == 2){chdir(gargv[1]);lastcode = 0;}else{lastcode = 1;}return true;}else if(strcmp(gargv[0], "export") == 0){//export也是内建命令if(gargc == 2){AddEnv(gargv[1]);lastcode = 0;}else{lastcode = 2;}return true;}else if(strcmp(gargv[0], "env") == 0){for(int i = 0; genv[i]; i++){printf("%d\n", genv[i]);}lastcode = 0;return true;}else if(strcmp(gargv[0], "echo") == 0){if(gargc == 2){//echo $?//echo $PATH//echo helloif(gargv[1][0] == '$'){if(gargv[1][1] == '?'){printf("%d\n", lastcode);lastcode = 0;}else{printf("%s\n", gargv[1]);lastcode = 0;}}else{lastcode = 3;}return true;}return false;}
}
8.1.1 cd命令
功能:用于更改当前工作目录。
逻辑:
检查参数个数 gargc 是否等于 2(即命令和目录)。
如果参数正确,调用 chdir 函数改变目录,并将 lastcode 设置为 0,表示成功。
如果参数不正确,将 lastcode 设置为 1,表示错误。
chdir() : 将调用进程的当前工作目录更改为path中指定的目录
8.1.2 export命令
功能:用于设置或导出环境变量。
逻辑:
同样检查参数个数 gargc 是否为 2。
如果正确,调用 AddEnv 函数添加环境变量,并将 lastcode 设置为 0。
如果参数不正确,设置 lastcode 为 2。
8.1.3 evn命令
功能:列出所有环境变量。
逻辑:
遍历 genv 数组,打印每个环境变量。
将 lastcode 设置为 0。
8.1.4 echo命令
功能:输出字符串或变量。
逻辑:
检查参数个数是否为 2。
如果是,检查 gargv[1] 的第一个字符是否为 $:
如果是 $?,输出 lastcode 的值。
如果是其他以 $ 开头的字符串,直接输出这个字符串(假设它是环境变量)。
如果没有 $,则将 lastcode 设置为 3。
如果参数个数不正确,返回 false。
8.2 为什么使用内建命令
快速响应:内建命令通常直接在 shell 进程内执行,无需创建新的进程,减少了上下文切换的开销。这使得内建命令的执行速度更快。
基本功能:内建命令提供了一些与 shell 紧密相关的基本功能,如改变目录(cd)、设置环境变量(export)、获取当前环境(env)等,这些操作通常与 shell 的状态直接相关。
环境影响:某些内建命令(如 cd)会影响 shell 的状态(例如当前工作目录),如果用外部程序实现,改变的状态不会反映到 shell 中。
简化用户操作:用户可以直接使用内建命令而无需担心路径问题。例如,cd 命令只需要提供目标路径,而不必寻找相应的外部可执行文件。
状态保持:内建命令如 echo 和 export 能够直接访问 shell 的状态和环境变量,而不需要通过外部程序来管理,这样可以更好地处理如 $?(上一个命令的退出状态)这样的特殊情况。
9. 主函数
功能:主程序循环,负责显示提示符、获取用户命令、解析命令、检查内建命令,并执行命令。
int main()
{InitEnv();char command_buffer[basesize];while(true){//1. 命令行提示符PrintCommandLine();//command_buffer -> output//2. 获取用户命令if(!GetCommandLine(command_buffer, basesize)){continue;}//3. 解析命令ParseCommandLine(command_buffer, strlen(command_buffer));if(CheckAndExeBuiltCommand()){continue;}4. 执行命令ExecuteCommand();}return 0;
}
10. 效果展示:
相关文章:

Linux基础-shell的简单实现
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 Linux基础-shell的简单实现 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 1, 全局变…...

Tomcat日志文件详解及catalina.out日志清理方法
目录 前言1. Tomcat日志文件详解1.1 catalina.out1.2 localhost_access_log1.3 catalina.<date>.log1.4 host-manager.<date>.log 和 manager.<date>.log1.5 localhost.<date>.log 2. catalina.out文件管理与清理方法2.1 为什么不能直接删除catalina.o…...

react 中的hooks中的useState
(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作 (2). 语法: const [xxx, setXxx] React.useState(initValue) (3). useState()说明:参数: 第一次初始化指定的值在内部作缓存返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的…...

STM32学习笔记---DMA
目录 一、什么是DMA 1、DMA是什么 2、DMA的工作流程 3、DMA控制器与外设控制器 二、如何配置DMA 1、DMA框图 2、功能说明 2.1 通道选择 2.2 仲裁器 2.3 源、目标和传输模式 2.4 指针递增 2.5 循环模式 2.6 DMA流控制器和外设流控制器 3、程序设计 三、具体使用DMA…...

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质)
Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质) 核心代码完整代码在线示例Cesium 给实体对象(Entity)提供了很多实用的样式,基本满足普通项目需求; 但是作为 WebGL 引擎,肯定不够丰富,尤其是动态效果样式。 对于实体对象(Entity),可以通过自定义材质,实现各种…...

进程间关系与守护进程
一、进程组 1.1、什么是进程组 提到进程的概念, 其实每一个进程除了有一个进程 ID(PID)之外 还属于一 个进程组。进程组是一个或者多个进程的集合, 一个进程组可以包含多个进程。 每一 个进程组也有一个唯一的进程组 ID(PGID), 并且这个 PG…...

金山翻译接口逆向
网址(加密后):aHR0cHM6Ly93d3cuaWNpYmEuY29tL3RyYW5zbGF0ZQ 文章目录 抓包sign值结果加密 逆向sign值第一步第二步1.2.3. 解密content第一步1.2.3. 抓包 F12 -> 翻译框输入spider -> 点击Fetch/XHR -> 找到接口 index.php? 开头的…...
unified-runtime编译与验证
unified-runtime编译与验证 一.创建容器二.编译unified-runtime三.生成一个cuda ptx kernel四.API测试 unified-runtime编译与验证 一.创建容器 docker run --gpus all --shm-size32g -ti \-e NVIDIA_VISIBLE_DEVICESall --privileged --nethost \--rm -it \-v $PWD:/home \-…...
【Python】最详细--基础语法
Python是一种强大且易于学习的编程语言,广泛用于各种应用程序的开发,如web开发、数据科学、人工智能等。以下是一些Python的基础知识: 1. Python的注释 Python的注释用于在代码中添加说明,以提高代码的可读性。注释在代码执行时…...
二叉树基础:什么样的二叉树适合用数组来存储?
二叉树基础:什么样的二叉树适合用数组来存储? 在计算机科学中,二叉树是一种非常重要的数据结构。它具有许多应用,如搜索、排序、表达式解析等。在存储二叉树时,我们可以使用多种方法,其中一种是使用数组。但是,并不是所有的二叉树都适合用数组来存储。那么,什么样的二…...

iTOP-RK3568开发板独立NPU通过算法加特应用到以下的场景
iTOP-3568开发板采用瑞芯微RK3568处理器,内部集成了四核64位Cortex-A55处理器。主频高达2.0Ghz,RK809动态调频。集成了双核心架构GPU,ARM G52 2EE、支持OpenGLES1.1/2.0/3.2、OpenCL2.0、Vulkan1.1、内嵌高性能2D加速硬件。 内置独立NPU,算力…...

Java基于SpringBoot微信小程序的跳蚤市场系统设计与实现(lw+数据库+讲解等)
项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…...
【分布式微服务云原生】《Redis 的高效之道:线程模型、IO 模型与 Reactor 模型全解析》
标题:《分布式缓存Redis 的高效之道:线程模型、IO 模型与 Reactor 模型全解析》 摘要:本文深入探讨分布式缓存 Redis 的 I线程模型、IO 模型以及 Reactor 模型。详细介绍了 Redis 在不同版本中的线程变化、IO 模型的特点和工作流程ÿ…...

科研类型PPT的制作技巧
目录 科研类型PPT的制作技巧 荣誉: 首页:ppt开头结尾 小标题 重点标记:加粗红色下划线 使用三线表 图片,文本排版 一、明确目的与受众分析 二、基础设计原则 三、内容组织与呈现 四、绘图与模型制作 五、其他注意事项 科研类型PPT的制作技巧 荣誉: 首页:ppt开…...

rom定制系列------小米6x_MIUI14_安卓13刷机包修改写入以及功能定制 界面预览
在接待一些定制化系统中。有很多工作室或者一些特殊行业的友友需要在已有固件基础上简略修改其中的功能。方便使用。例如usb调试默认开启。usb安装设置以及usb安装与内置删减一些app的定制服务。今天给友友预览其中小米6X此款机型定制相关的一些界面与功能演示。 定制机型以及…...

线性代数基础02
目录 1.向量 1.1向量的定义 1.2向量的运算 1.2.1向量加法 1.2.2向量数乘 1.2.3向量点积 1.3矩阵的特征值和特征向量 1.4向量的模 1.4.1向量的模的定义 1.4.2向量的模的几何解释 1.4.3向量的模的性质 1.5向量的内积 1.5.1向量的内积的定义 1.5.2向量的内积的几何解…...
「4.4」祖孙询问
「4.4」祖孙询问 题目描述 已知一棵 n 个节点的有根树。有 m 个询问,每个询问给出了一对节点的编号 x 和 y,询问 x 与 y 的祖孙关系。 输入格式 输入第一行包括一个整数 n 表示节点个数; 接下来 n 行每行一对整数对 a 和 b 表示 a 和 b 之…...

Datawhale 组队学习 文生图 Prompt攻防 task03随笔
这期我们从不同角度切入探讨赛题的进阶思路 思路1:对比不同大模型 首先我们可以选择尝试不同的大模型,使用更复杂的大模型可以提高文本改写的质量和效果。随着模型大小的增加,其表示能力也随之增强,能够捕捉更细微的语言特征和语…...

游戏投屏软件有哪些?分享这10款比较好用的!
说到投屏,这个事情我还是比较有发言权的! 一般手机下载个APP,然后就可以通过WiFi、蓝牙或者USB进行连接投屏啦,下面是国内比较主流的一些游戏投屏软件,可以根据他们的优缺点进行选择哦! 01.幕连 国内首款…...

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十六集(下篇):制作小BOSS龙牙哥
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、制作小BOSS龙牙哥 1.导入素材制作动画2.制作两种攻击行为3.制作从惊醒到转身到走路or跑步行为总结 前言 hello大家好久没见,之所以隔了一天时间…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...

Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...

一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...