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

【Linux】详解shell代码实现(上)

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

          主厨:邪王真眼

主厨的主页:Chef‘s blog  

所属专栏:青果大战linux

总有光环在陨落,总有新星在闪烁

学校开始搞蓝桥的校选了,很好,300块钱不用掏了。昨天还看到一个OS的比赛,可以我这没实力,不然真想去试试。

我相信不少同学(包括我),最开始都理解不了所谓的shell或者说bash到底是什么,他被称之为命令行解释器,他创建子进程,他辅助用户和内核之间进行联系,它本身也是一个进程,这些定义都太抽象了,那么它到底是什么,他又是如何实现这些功能的,要搞清楚这个,其实只要手写一个shell就好了。

为了方便区分,下文对于系统自带的shell我们称之为shell,对于我们自己写的shell我们称之为myshell

思路大纲:

1.首先所谓shell其实就是运行起来的程序,不难发现shell他以运行以来就不会停止,所以可以想到他的代码最外层是一个死循环。

2.循环里面有什么,我们可以分为四个模块 ----【创建命令行提示符】 ------【获取用户命令】------

【分析用户命令】-----【执行用户命令】

接下来我会挨个介绍四个模块。

int main(){char command_buffer[basesize];while(true){ PrintCommradLine();//打印命令行提示符GetCommandLine(command_buffer,basesize))//获取命令ParseCommandLine(command_buffer,(int)strlen(command_buffer));//分析命令ExecuteCommandLine();//执行命令}return 0;
}

创建命令行提示符

 不难发现,在我们输入指令的那一行永远都会有一串字符,我们称其为命令行提示符,它由四部分构成:

[用户名+@+主机名+空格+当前路径]+#/$

细节:如果用户是root最后就是#,否则是$

要获取这些信息很简单,我们有很多接口,比如通过getenv从环境变量中获取,或者getcwd从进程信息里找,这里我们先用getenv,后面到cd指令我会在带领大家修改。

string GetUserName(){string name= getenv("USER");return name.empty()?"NULL":name;
}string GetHostName(){string name= getenv("HOSTNAME");return name.empty()?"NULL":name;
}
char pwd[basesize];//当前工作路径
char pwdenv[basesize];//PWD的环境变量
string GetPwd(){string name= getenv("PWD");return name.empty()?"NULL":name;
}

通过他们三个函数我们就获得用户名,主机名以及当前路径。

接着我们可以通过snprintf函数把他们拼起来,当然这一步你想用c++的string操作也可以,我只提供一种思路,大家可以去充分发挥自己的想象力。

函数介绍:

  1. 参数s:表示要把内容输出到s数组中

  2. 参数n:s数组中能被该函数使用的最大空间大小,单位字节 

  3. 参数format:这是一个格式化字符串,类似printf函数中的格式字符串。它包含普通字符和转换说明符。普通字符会原样复制到s中,而转换说明符用于指定如何将后面的可变参数(用...表示)转换为字符串并插入到s中。

const int basesize=1024;string MakeCommandLine(){
char CommandLine[basesize];
snprintf(CommandLine,basesize,"[%s@%s %s]#",GetUserName().c_str(),GetHostName().c_str(),GetPwd().c_str());
return CommandLine;
}

如此一来我们调用这个MakeCommandLine函数就可以获得命令行提示符的字符串了

最后我们打印该字符串即可,

void PrintCommradLine(){printf("%s",MakeCommandLine().c_str());fflush(stdout);
}

fflush刷新,因为我们的c语言缓冲区是行刷新的,我们这里又不能输出换行符,为了将字符串刷新到显示器就必须调用fflush刷新缓冲区了。


 获取用户的命令

获取命名本质就是获取显示器上的一些字符串,但是注意我们的命令常常有空格作为分隔符,例如ls -a -l等等,所以直接scanf显然是满足不了我们的,对于c++我们可以用getline,他会以回车作为结束符,并且丢掉回车字符,也可以用c语言的fgets,当fgets从显示器输入时他会以回车符为结束标志,并且接受到回车符

强调:getline会丢弃掉回车符(不是不接收,而是丢弃!!),fgets会接受回车符。

  • 参数 
  1. 参数str:这是一个字符数组,用于存储从文件流中读取到的字符串

  2. 参数num:它表示最多读取的字符数(包括结束符\0

  3. 参数stream:这是一个指向FILE类型的指针,表示要从中读取数据的文件流

  • 返回值

如果读取成功,函数返回指向str的指针,读取失败返回NULL

为了保证我们能成功接收到命令,我们把GetCommandLine的返回值设置为布尔值,当fgets调用失败时,就返回0,main函数搭配判断该返回值的语句,为0则继续调用GetCommandLine直到成功。

bool  GetCommandLine(char*command_buffer,int size)//获取命令
{
char *result=fgets(command_buffer,size,stdin);
if(!result)return 0;
command_buffer[strlen(command_buffer)-1]='\0';
if(strlen(command_buffer)==0)return 0;
return 1;
}
int main(){while(true){ if(! GetCommandLine(command_buffer,basesize))//获取命令{continue; }}return 0;
}

细节 

  1. 我们要记得把最后的回车符的给删除掉,因为我们的指令本体其实是不含回车的,可以直接把他换成‘\0’。

  2. 当发现传入的命令为空串(也就是直接敲回车)我们就返回0,让用户重新输入,因为对空串解析没有意义,还可能引发问题。


分析命令

之前我们了解到shell会把接受的命令转化为对应的命令行参数,即argc、argv,这就是现在的工作。

我们的想法是按照空格把命令分开,并放入到一个char* argv[]数组存储,按照目标分隔符分割字符串,这显然就是strtok的任务了。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

​编辑 

  • 参数 
  1. 参数str:这是一个字符串,是要被分割的原始字符串。在第一次调用strtok时,需要将这个原始字符串的指针传递进来。如果要继续分割同一个字符串,继续调用函数时,str参数要设置为NULL。
  2. 参数delimiters:这是一个包含分隔符的字符串。例如,如果想要以逗号和句号作为分隔符来分割字符串,该参数可以是",。"。这个字符串中的每个字符都被视为一个分隔符。
  • 他的返回值

 当函数成功分割字符串时,它返回从左到右第一个分割出来的子串的指针。这个指针指向子串的开头位置。例如,对于“apple,banana,cherry”字符串,第一次调用函数(假设delim",")会返回一个指向apple这个子字符串的指针。无法继续分割时则返回NULL 

void ParseCommandLine(char command_buffer[],int len){memset(argv,0,sizeof argv);argc=0;(void)(len);const char*sep=" ";argv[argc++]=strtok(command_buffer,sep);char*Next=NULL;while((bool)(Next=strtok(NULL,sep)))//不加强转会有waring{argv[argc++]=Next;}
}

细节

  1. 这里我说个小知识点,vim里你定义一个变量但不用时会有waring,为了不出现警报你可以对该变量原地强转,就可以让编译器认为他被使用过了,如上面函数里的形参len。 

  2. 注意argv要以NULL结尾


  执行命令

我们一直听说shell会创建子进程去执行用户输入的命令,现在我们就看看她是怎么做的

fork创建子进程,接着我们对子进程进行进程替换,我们这里用的是execvpe函数,为什么是他呢

  1. 首先我们再命令分析时已经做好了argv,所以用argv传参更方便

  2. 其次输入p可以让我们只输入文件名就行了不用输入他的路径很方便

  3. 至于为什么要带传入环境变量功能,我们后面说

关于exec系列函数忘记的,进程替换不清楚的,请移步至这里进程替换及exec系列函数使用

父进程的工作自然就是waitpid回收进程,这里我们直接阻塞等待就好了

void ExecuteCommandLine(){pid_t id=fork();if(!id){execvpe(argv[0],argv,env);exit(1);}int status=0;pid_t rid=waitpid(id,&status,0);
}

假如进程替换失败了我们就exit(1),返回一个错误码

有了上面的这些函数我们的shell其实已经完成九成了,但绝不可小看剩下的一成,倒不如难点就在此处。


内建命令

此时已经自己通过上面的讲解构建好了myshell的同学可以试试,你们输入pwd,ls,mkdir这些指令都可以正常运行,但是你试试cd,就会发现没用。

原因不难想出,我们是先fork创建子进程接着再子进程跑指令,那么你的cd指令此时就是修改了子进程的路径,这对吗?这不对,因为我们实际要的是修改父进程也就是myshell的路径,于是我们就知道cd指令不用也不能让子进程去跑,而要myshell自己去跑,我们称这一类需要myshell自己跑的指令为内建命令

cd

对于cd其实就是改变进程的当前工作路径,于是我们可以用一个系统接口chdir,

他会把当前的进程工作路径修改为传入的path 

bool CheckAndExecBuiltCommand(){if(0==strcmp(argv[0],"cd")){if(argc==2){chdir(argv[1]);}return true;}

此时我们就要注意一个问题了,当我们cd路径后,myshell打印的命令行提示符中的路径部分是不会变得,这是因为我们的路径是通过环境变量获取的,但是环境变量再cd后不会自动更新,所以我们就要换个接口了,改用getcw的,该函数于获取当前工作目录(Current Working Directory,CWD)的路径。,这份信息来自/proc文件中,他存储了所有进程的相关信息。同时别的忘了通过putenv修改环境变量。

  

参数

  1. buf参数:这是一个字符数组,用于存储获取到的当前工作目录路径。

  2. size参数:它表示buf的大小,单位是字节。 

返回值:

  • 如果函数调用成功,getcwd返回buf的指针,也就是存储当前工作目录路径的字符数组的首地址。
  • 如果出现错误,getcwd返回NULL。常见的错误原因包括buf大小不够、没有权限访问当前工作目录等
string GetPwd(){
snprintf(pwdenv,sizeof pwdenv,"%s%s","PWD=",pwd);
putenv(pwdenv);if(getcwd(pwd,sizeof pwd)==nullptr)return "NULL";return pwd;
}

export

它的作用是导入新的环境变量 或修改已有的环境变量

首先我们创建自己的环境变量表,shell的环境变量表来自于再你打开xshell软件时他会自动读取一些配置文件来获得环境变量,这个比较复杂大家知道这个过程就行,我们就直接读取myshell从shell那里获得environ这个数组就好了

extern char** environ;
const int envnum=64;
char*env[envnum];//环境变量表
//本质是从真正的shell获取环境变量
void InitEnv(){int index=0;while(environ[index]) {env[index]=(char*)malloc(strlen(environ[index])+1);strcpy(env[index],environ[index]);index++;// env[index]=environ[index++];}env[index]=nullptr;
}

env要以NULL结尾

else  if(0==strcmp(argv[0],"export")){if(argc==2){AddEnv(argv[1]);}return true;}

所谓的添加就是把export后面的字符串加入到env数组中,但是注意export的另一个功能修改已经存在的环境变量这个功能我没有实现 

void AddEnv(char *item){int index=0;while(env[index]){index++;}env[index]=(char*)malloc(strlen(item)+1);strcpy(env[index],item);env[++index]=nullptr;
}

 为了让myshel创建的子进程的环境变量与myshell保持一致,我们就要用execvpe函数传递env了(waitpid前文)

env指令 

   else  if(0==strcmp(argv[0],"env")){for(int i=0;env[i];i++)printf("%s\n",env[i]);}

有了我们自己创建的环境变量表后,我们也就要重写env指令了,因为系统自带env指令不会去我们自己写的表中查看环境变量。


最后我们其实也要重写echo,别的不说,shell的echo是可以查看本地变量和环境变量的,而系统自带的echo接口只可以看环境变量

但是因为我比较懒所以就没写

但是我想锻炼一下大家,所以就没写

源码如下

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;
const int basesize=1024;const int argvnum=64;
char* argv[argvnum];
int argc=0;extern char** environ;
const int envnum=64;
char*env[envnum];//环境变量表
//本质是从真正的shell获取环境变量
void InitEnv(){int index=0;while(environ[index]) {env[index]=(char*)malloc(strlen(environ[index])+1);strcpy(env[index],environ[index]);index++;// env[index]=environ[index++];}env[index]=nullptr;
}string GetUserName(){string name= getenv("USER");return name.empty()?"NULL":name;
}string GetHostName(){string name= getenv("HOSTNAME");return name.empty()?"NULL":name;
}
char pwd[basesize];//当前工作路径
char pwdenv[basesize];//PWD的环境变量
string GetPwd(){
// string name= getenv("PWD");
snprintf(pwdenv,sizeof pwdenv,"%s%s","PWD=",pwd);
putenv(pwdenv);if(getcwd(pwd,sizeof pwd)==nullptr)return "NULL";return pwd;
//ZZ return name.empty()?"NULL":name;
}string MakeCommandLine(){
char CommandLine[basesize];
snprintf(CommandLine,basesize,"[%s@%s %s]#",GetUserName().c_str(),GetHostName().c_str(),GetPwd().c_str());
return CommandLine;
}void PrintCommradLine(){printf("%s",MakeCommandLine().c_str());fflush(stdout);
}bool  GetCommandLine(char*command_buffer,int size)//获取命令
{
char *result=fgets(command_buffer,size,stdin);
if(!result)return 0;
command_buffer[strlen(command_buffer)-1]='\0';
if(strlen(command_buffer)==0)return 0;
return 1;
}
void ParseCommandLine(char command_buffer[],int len){memset(argv,0,sizeof argv);argc=0;(void)(len);const char*sep=" ";argv[argc++]=strtok(command_buffer,sep);char*Next=NULL;while((bool)(Next=strtok(NULL,sep)))//不加强转会有waring{argv[argc++]=Next;}
}void ExecuteCommandLine(){pid_t id=fork();if(!id){execvpe(argv[0],argv,env);exit(1);}int status=0;waitpid(id,&status,0);
}
void AddEnv(char *item){int index=0;while(env[index]){index++;}env[index]=(char*)malloc(strlen(item)+1);strcpy(env[index],item);env[++index]=nullptr;
}
bool CheckAndExecBuiltCommand(){if(0==strcmp(argv[0],"cd")){if(argc==2){chdir(argv[1]);}return true;}else  if(0==strcmp(argv[0],"export")){if(argc==2){AddEnv(argv[1]);}return true;}else  if(0==strcmp(argv[0],"env")){for(int i=0;env[i];i++)printf("%s\n",env[i]);}return false;
}
int main(){char command_buffer[basesize];InitEnv();while(true){ PrintCommradLine();//打印命令行提示符if(! GetCommandLine(command_buffer,basesize))//获取命令{continue; }ParseCommandLine(command_buffer,(int)strlen(command_buffer));//分析命令
if( CheckAndExecBuiltCommand())//检测并执行内建命令
{continue;
}ExecuteCommandLine();//执行命令}return 0;
}

之后我会对于echo、文件、set、export修改功能以及别的细节来更新一次博客,大家敬请期待。 

-------------------------------创作不易,觉得有用就点赞或关注支持一下吧--------------------------------------

相关文章:

【Linux】详解shell代码实现(上)

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 学校开始搞蓝桥的校选…...

Ruby 模块(Module)

Ruby 模块&#xff08;Module&#xff09; 概述 Ruby 是一种动态、开放源代码的编程语言&#xff0c;以其简洁明了的语法和强大的功能而闻名。在 Ruby 中&#xff0c;模块&#xff08;Module&#xff09;是一个重要的概念&#xff0c;它用于封装一组相关的方法和常量。模块提…...

成都睿明智科技有限公司怎么样可靠不?

在这个日新月异的数字时代&#xff0c;电商行业如同一股不可阻挡的洪流&#xff0c;席卷着每一个消费者的生活。而抖音&#xff0c;作为短视频与电商完美融合的典范&#xff0c;更是为无数商家开辟了一片全新的蓝海。在这片充满机遇与挑战的海洋中&#xff0c;成都睿明智科技有…...

内网安全隧道搭建-ngrok-frp-nps-sapp

1.ngrok 建立内网主机与公网跳板机的连接&#xff1a; 内网主机为客户机&#xff1a; 下载客户端执行 2.frp &#xff08;1&#xff09;以下为内网穿透端口转发 frp服务端配置&#xff1a; bindPort 为frp运行端口 服务端运行 ./frps -c frps.ini frp客户端配置&#xf…...

k8s 对外服务之 Ingress

LB ingress //Ingress 简介 service的作用体现在两个方面&#xff0c;对集群内部&#xff0c;它不断跟踪pod的变化&#xff0c;更新endpoint中对应pod的对象&#xff0c;提供了ip不断变化的pod的服务发现机制&#xff1b;对集群外部&#xff0c;他类似负载均衡器&#xff0c;…...

前端速通(JavaScript)

1 初识JavaScript 1 JavaScript是什么 JavaScript 是一种高层的、轻量级的、解释型的编程语言&#xff0c;最初由 Netscape 公司于 1995 年开发。它的特点包括&#xff1a; 动态性&#xff1a;JavaScript是动态类型语言&#xff0c;允许开发者灵活地操作数据。跨平台&#xf…...

Unity图形学之着色器之间传递参数

1.初始化 struct&#xff1a; UNITY_INITIALIZE_OUTPUT&#xff08;type,name&#xff09; Type: struct 名字 Name :变量的名字 struct Input{float2 uv_MainTex;float3 myColor;};half _Glossiness;half _Metallic;fixed4 _Color;void MyVertx(inout appdata_base v,out I…...

JavaScript中的this指向问题

JavaScript中的this指向问题 1.1 为什么需要this? 为什么需要this? 在常见的编程语言中&#xff0c;几乎都有this这个关键字&#xff08;Objective-C中使用的是self),但是在JavaScript中的this和常见的面向对象语言中的this不太一样 常见面向对象的编程语言中&#xff0c;比…...

Qt之QWidget相关

Qt概述 Qt 是一个跨平台的 C 开发框架。 跨平台支持&#xff1a;可以用于开发 Windows、macOS、Linux、Android、iOS 等多种操作系统下的应用程序。这意味着开发者使用 Qt 编写的代码&#xff0c;在经过适当的编译和配置后&#xff0c;能够在不同平台上运行&#xff0c;减少了…...

Ease Monitor 会把基础层,中间件层的监控数据和服务的监控数据打通,从总体的视角提供监控分析

1. 产品定位 Ease Monitor 有如下的产品定位&#xff1a; 关注于整体应用的SLA。 主要从为用户服务的 API 来监控整个系统。 关联指标聚合。 把有关联的系统及其指示聚合展示。主要是三层系统数据&#xff1a;基础层、平台中间件层和应用层。 快速故障定位。 对于现有的系统…...

苹果MacOS 调用自编译opencv的Dylib显示一个图片程序的步骤

前言 为了测试自编译的opencv库是否能在苹果MacOS系统下使用&#xff0c;需要写一个简单的测试程序。这个测试程序写起来不难&#xff0c;麻烦的是一些配置。网上的办法很多&#xff0c;里面因为版本的问题有一些坑。特此写了一个建立步骤&#xff0c;供大家参考。 1、新建一个…...

网页中调用系统的EXE文件,如打开QQ

遇到一个实际的问题&#xff0c;需要在网页中打开本地的某个工业软件。 通过点击exe文件就可以调用到程序。 比如双击qq的exe就可以启动qq的程序。 那么问题就变成了如何加载exe程序呢&#xff1f; 可以通过Java的 Process process Runtime.getRuntime().exec(command);通过…...

在 Ubuntu 系统上安装 npm 环境以及 nvm(Node Version Manager)

在 Ubuntu 系统上安装 npm 环境以及 nvm&#xff08;Node Version Manager&#xff09; 步骤 1: 更新系统包步骤 2: 安装 nvm步骤 3: 安装 Node.js 和 npm步骤 4: 设置默认 Node.js 版本&#xff08;可选&#xff09;总结 在 Ubuntu 系统上安装 npm 环境以及 nvm&#xff08;No…...

Linux环境开启MongoDB的安全认证

文章目录 1. MongoDB安全认证简介1.1 访问控制1.2 角色1.3 权限 2. MongoDB中的常见角色3. MongoDB Shell3.1 下载MongoDB Shell3.2 通过MongoDB Shell连接MongoDB 4. 创建管理员用户5. 为具体的数据库创建用户6. 开启权限认证7. 重启MongoDB服务8. 连接MongoDB9. MongoDB数据库…...

实现了两种不同的图像处理和物体检测方法

这段代码实现了两种不同的图像处理和物体检测方法&#xff1a;一种是基于Canny边缘检测与轮廓分析的方法&#xff0c;另一种是使用TensorFlow加载预训练SSD&#xff08;Single Shot Multibox Detector&#xff09;模型进行物体检测。 1. Canny边缘检测与轮廓分析&#xff1a; …...

经典工具 | 使用SIFT预测错义突变的有害性

SIFT 用计算机替代人预测复杂事件的影响&#xff0c;是我们这个时代最令人兴奋的科学进展之一。SIFT就是这样一个应用于基因组学研究的经典工具。 SIFT可预测多种生物体的基因组变异&#xff0c;主要是错义突变的影响与效应&#xff0c;最大的特点是物种丰富&#xff0c;是一个…...

如何给 Apache 新站点目录配置 SELinux ?

在 web 服务器管理领域&#xff0c;确保服务器环境的安全性至关重要。SELinux (Security-Enhanced Linux) 是保护 Linux 服务器最有效的工具之一&#xff0c;它是一种强制访问控制 (MAC mandatory access control) 安全机制。当使用最流行的 web 服务器 Apache 提供 web 内容时…...

RTSP播放器EasyPlayer.js播放器分辨率高的视频在设置container的宽高较小时,会出现锯齿状的画面效果

流媒体播放器的核心技术及发展趋势展现了其在未来数字生活中的无限潜力。随着技术的不断进步和市场的持续发展&#xff0c;流媒体播放器将在内容创新、用户体验优化以及跨平台互通等方面取得新的突破。对于从业者而言&#xff0c;把握这些趋势并积极应对挑战将是实现成功的关键…...

云讷科技Kerloud无人飞车专利发布

云讷科技Kerloud无人飞车获得了“一种室内外两用的四旋翼无人飞车”的实用新型专利证书&#xff0c;作为科教社区第一款四旋翼飞车&#xff0c;这项技术结合了无人机和无人车的优势&#xff0c;提供了一种能够在多种环境下使用的多功能飞行器。 这项设计的优势如下&#xff…...

快速识别模型:simple_ocr,部署教程

快速识别图片中的英文、标点符号、数学符号、Emoji, 模型会输出图片中文字行的坐标位置、最低得分、识别结果。当前服务用到的模型&#xff1a;检测模型、数字识别、英文符号识别。 一、部署流程 1.更新基础环境 apt update2.安装miniconda wget https://repo.anaconda.com/…...

Qt交叉编译x86和arm心得

最近一直在Linux上开发qt程序&#xff0c;主要工作是在x86的Ubuntu上开发编译调试程序&#xff0c;确定没有问题后交叉编译到arm的linux系统上运行 1.环境 Qt的交叉编译环境厂家已经提供了&#xff0c;嵌入式的同事帮我安装调试的&#xff0c;具体就是装了厂家给的gcc编译套件…...

用CAXA CAD电子图板导入图框、标题栏并导出pdf的方法

1.导入图框&#xff1a; 点击调入图框->出现读入图框文件 一个一个点击&#xff0c;选择合适的图框 然后点击导入 2.导入标题栏&#xff1a; 调入标题栏->出现读入标题栏文件 一个一个点击&#xff0c;选择合适的标题栏&#xff0c;然后点击导入 3.导出pdf&#x…...

在 Ubuntu/Debian 上安装 Go

使用官方二进制文件安装&#xff08;推荐&#xff09; Go 提供了官方的二进制安装包&#xff0c;适用于大多数 Linux 发行版&#xff0c;包括 Ubuntu 和 Debian。步骤如下&#xff1a; 更新包索引&#xff1a; bash sudo apt update 安装依赖&#xff08;如果尚未安装&#…...

设计模式之策略模式-工作实战总结与实现

文章目录 应用场景存在问题解决方案继续延伸 应用场景 假设有这样的业务场景&#xff0c;大数据系统把文件推送过来&#xff0c;根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码&#xff1a; public class Question {public static void main(String[] args…...

自动语音识别(ASR)与文本转语音(TTS)技术的应用与发展

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

实验十三 生态安全评价

1 背景及目的 生态安全是生态系统完整性和健康性的整体反映&#xff0c;完整健康的生态系统具有调节气候净化污染、涵养水源、保持水土、防风固沙、减轻灾害、保护生物多样性等功能。维护生态安全对于人类生产、生活、健康及可持续发展至关重要。随着城市化进程的不断推进&…...

【MySQL实战45讲笔记】基础篇——redo log 和 binlog

系列文章 基础篇——MySQL 的基础架构 目录 系列文章1. 重要的日志模块&#xff1a;redo log 和 binlog1.1 redo log1.2 binlog1.3 执行器和 InnoDB 引擎内部如何执行更新语句 1. 重要的日志模块&#xff1a;redo log 和 binlog 前面系统的了解了一个查询语句的执行流程&…...

Java 基于SpringBoot+vue框架的老年医疗保健网站

大家好&#xff0c;我是Java徐师兄&#xff0c;今天为大家带来的是Java Java 基于SpringBootvue框架的老年医疗保健网站。该系统采用 Java 语言开发&#xff0c;SpringBoot 框架&#xff0c;MySql 作为数据库&#xff0c;系统功能完善 &#xff0c;实用性强 &#xff0c;可供大…...

Java集合分页

一、前言 在Java开发中&#xff0c;若单次展示的数据量太大&#xff0c;会造成程序响应缓慢&#xff0c;就需要用到分页功能&#xff0c;每一页展示一定量的数据&#xff0c;分多次展示 ... 那么在List集合中&#xff0c;如何实现分页功能呢&#xff1f; 本文将以3种方式&…...

python语言基础-5 进阶语法-5.5 上下文管理协议(with语句)

声明&#xff1a;本内容非盈利性质&#xff0c;也不支持任何组织或个人将其用作盈利用途。本内容来源于参考书或网站&#xff0c;会尽量附上原文链接&#xff0c;并鼓励大家看原文。侵删。 5.5 上下文管理协议&#xff08;with语句&#xff09;&#xff08;参考链接&#xff1…...

周志华深度森林deep forest(deep-forest)最新可安装教程,仅需在pycharm中完成,超简单安装教程

1、打开pycharm 没有pycharm的&#xff0c;在站内搜索安装教程即可。 2、点击“文件”“新建项目” 3、创建项目&#xff0c;Python版本中选择Python39。如果没有该版本&#xff0c;选择下面的Python 3.9下载并安装。 4、打开软件包&#xff0c;搜索“deep-forest”软件包&am…...

技术美术百人计划 | 《2.1 色彩空间介绍》笔记

总览 一、色彩发送器 色彩认知&#xff1a; 光源是出生点&#xff0c;光源发射出光线&#xff0c;光线通过直射反射折射等路径最终进入人眼。 但人眼接收到光线后&#xff0c;人眼的细胞产生了一系列化学反应。 由此把产生的信号传入大脑&#xff0c;最终大脑对颜色产生了认…...

设计模式:6、装饰模式(包装器)

目录 0、定义 1、装饰模式包含的四种角色 2、装饰模式的UML类图 3、示例代码 0、定义 动态地给对象添加一些额外的职责。就功能来说装饰模式相比生成子类更为灵活。 1、装饰模式包含的四种角色 抽象组件&#xff08;Component&#xff09;&#xff1a;抽象组件是一个抽象…...

vue-office:word(.docx)、pdf、excel(.xlsx,.xls)格式文件预览

vue-office&#xff1a;word&#xff08;.docx&#xff09;、excel&#xff08;.xlsx&#xff0c;.xls&#xff09;格式文件预览 组件安装 // docx文档预览组件 npm install vue-office/docx vue-demi0.14.6// excel文档预览组件 npm install vue-office/excel vue-demi0.14.…...

简单工厂模式

简单工厂模式详解 定义 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;用于创建对象的实例。通过一个工厂类来决定实例化哪一个具体类&#xff0c;降低客户端与具体类之间的耦合。 对于长switch或者长if、else&#xff0c;且…...

得物彩虹桥架构演进之路-负载均衡篇

文 / 新一 一、前言 一年一更的彩虹桥系列又来了&#xff0c;在前面两期我们分享了在稳定性和性能2个层面的一些演进&优化思路。近期我们针对彩虹桥 Proxy 负载均衡层面的架构做了一次升级&#xff0c;目前新架构已经部署完成&#xff0c;生产环境正在逐步升级中&#xf…...

【大数据学习 | Spark-Core】spark-shell开发

spark的代码分为两种 本地代码在driver端直接解析执行没有后续 集群代码&#xff0c;会在driver端进行解析&#xff0c;然后让多个机器进行集群形式的执行计算 spark-shell --master spark://nn1:7077 --executor-cores 2 --executor-memory 2G sc.textFile("/home/ha…...

macos 使用 nvm 管理 node 并自定义安装目录

系统环境&#xff1a;MacOS Version 参考文章&#xff1a; Github 地址&#xff1a;https://github.com/nvm-sh/nvm 安装的方式是很简单的&#xff0c;直接执行下面的命令即可&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bas…...

MongoDB分片集群搭建

什么是分片 分片是一种跨多台机器分布数据的方法。MongoDB 使用分片来支持超大数据集和高吞吐量操作的部署。什么情况下使用分片 存储容量受单机限制&#xff0c;即磁盘资源遭遇瓶颈。读写能力受单机限制&#xff0c;可能是CPU、内存或者网卡等资源遭遇瓶颈&#xff0c;导致读…...

MySQL数据库基础

1.数据库的操作 1.1 显示当前数据库 show databses; 1.2 创建数据库 create database [if not exist] db_name; 创建名为db_test1的数据库 create database db_test1; 说明:当我们创建数据库没有指定字符集和校验规则时,系统使用默认字符集;utf8,校验规则是 utf8_general_c…...

前端性能优化

前端性能优化是提升用户体验的重要环节&#xff0c;优化的目标是减少页面加载时间、提高交互响应速度、降低资源消耗。以下从 加载性能优化、渲染性能优化 和 交互性能优化 三个维度详细说明&#xff1a; 一、加载性能优化 目标是减少页面首次加载时间&#xff0c;提升页面的加…...

深度学习中的正则化技术

在深度学习中&#xff0c;正则化是一种防止模型过拟合的重要手段。过拟合是指模型在训练数据上表现良好&#xff0c;但在未见数据上表现不佳的现象。正则化通过引入额外的约束或信息来限制模型的复杂性&#xff0c;从而提高模型的泛化能力。本文将介绍几种常见的正则化技术&…...

工商银行湖仓智一体创新应用实践

数智技术已经成为企业数字化转型的核心动力 国家《“十四五”数字经济发展规划》指出数字经济是未来的主要经济形态,数据因其倍增效应和乘数效应,可以带来全要素效率的提升,已经成为数字经济的核心要素资源,是企业数字化转型的新要素、新动能。为了高质量推进企业数字化转…...

测试实项中的偶必现难测bug之模糊匹配逻辑

问题: 现在有一个场景,如果只是通过功能测试会比较难测,例如刚开始我们做会员的时候,只有白银会员,在用户分群的场景下,需要用条件逻辑匹配,当时开发用了like的匹配方式没有问题。1年后加了白银试用会员,导致在统计会员分群的时候明明条件选的是白银会员,但是统计的数…...

金融科技白皮书:2022-2023年度回顾与前瞻

在金融科技领域&#xff0c;2022至2023年见证了一系列创新技术的应用和发展。本白皮书将回顾过去一年的主要成就&#xff0c;并展望未来一年的发展趋势。 2022年亮点回顾 **低代码平台&#xff1a;**低代码平台通过高度抽象化和自动化的可视化过程&#xff0c;简化了应用程序开…...

40分钟学 Go 语言高并发:sync包详解(下)

sync包详解&#xff08;下&#xff09; 学习目标 知识点掌握程度应用场景WaitGroup使用熟练使用和理解原理并发任务的同步等待Once实现原理理解底层实现和使用场景单例模式、一次性初始化Pool性能优化掌握对象池的使用和调优高并发下的内存优化Cond应用场景了解条件变量的使用…...

android 使用MediaPlayer实现音乐播放--权限请求

在Android应用中&#xff0c;获取本地音乐文件的权限是实现音乐扫描功能的关键步骤之一。随着Android版本的不断更新&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用需要动态请求权限&#xff0c;而到了android 13以上需要的权限又做了进一步…...

空间计算、物理计算、实时仿真与创造拥有「自主行为」的小狗 | 播客《编码人声》

「编码人声」是由「RTE开发者社区」策划的一档播客节目&#xff0c;关注行业发展变革、开发者职涯发展、技术突破以及创业创新&#xff0c;由开发者来分享开发者眼中的工作与生活。 虚拟世界与现实世界的界限逐渐模糊&#xff0c;已然成为不争的事实。但究竟哪些曾经的幻想已然…...

Day24 回溯算法part03

93.复原IP地址 本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了 题目链接/文章讲解:代码随想录 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili class Solution {private List<String> resul…...

PyTorch:如何使用TensorBoard优化和监控深度学习模型

如何使用TensorBoard优化和监控深度学习模型 为了提供一个更加详细和完整的指南关于如何使用 TensorBoard 进行深度学习模型的监控与优化&#xff0c;我们将从TensorBoard的基础知识开始&#xff0c;一步步探讨如何设置和利用其各项功能。 1. TensorBoard简介与基本架构 Ten…...