【Linux】探索Linux进程优先级 | 环境变量 |本地变量 | 内建命令

news2024/11/22 5:29:45

最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。

目录

  • 一、进程优先级
    • 1.1优先级VS权限
    • 1.2为什么要有进程优先级?
    • 1.3具体Linux中的优先级
      • 1.3.1查看进程优先级
      • 1.3.2 PRI and NI
      • 1.3.3 PRI VS NI
      • 1.3.4 修改进程优先级
      • 1.3.5优先级队列实现原理
    • 1.4拓展小知识
      • 1.4.1并发
      • 1.4.2几个小问题
        • 1.4.2.1为什么函数的返回值会被外部拿到呢?
        • 1.4.2.2系统怎么知道我们的进程当前执行到哪行代码了呢
        • 1.4.2.3在CPU中寄存器扮演什么角色呢?
        • 1.4.2.4为什么要保存进程的上下文数据呢?
        • 1.4.2.5进程数据上下文保存在哪里呢?
  • 二、环境变量
    • 2.1基本概念
    • 2.2环境变量PATH
    • 2.3环境变量HOME
    • 2.4获取环境变量env&&getenv
    • 2.4环境变量USER
  • 三、命令行参数
    • 3.1命令行参数作用
    • 3.3main函数的第三个参数
    • 3.4验证环境变量的继承
  • 四、本地变量&&内建命令
    • 4.1常规命令&&内建命令
  • 🍀小结🍀

在这里插入图片描述
在这里插入图片描述

🎉博客主页:小智_x0___0x_

🎉欢迎关注:👍点赞🙌收藏✍️留言

🎉系列专栏:Linux入门到精通

🎉代码仓库:小智的代码仓库


一、进程优先级

1.1优先级VS权限

优先级(对资源的访问,谁先访问,谁后访问)和权限看起来很像,但实际上它们有一些区别。权限决定的是能否进行某种操作,比如读取、写入或执行某个文件。优先级则是在你已经具备权限的情况下,决定谁先谁后地访问资源。比如在学校食堂排队时,你的优先级决定了你是先吃饭还是后吃饭。如果资源无法提供,或者你没有权限访问,那就是你没有这个权限。而优先级是用来决定当前的某个进程先享受还是后享受某种资源。

1.2为什么要有进程优先级?

在计算机系统中,进城有很多个,而CPU资源是有限的。而进程之间是要互相竞争对应的资源的。操作系统必须保证大家良性竞争,就必须确认优先级,优先级的存在就是为了更好地利用资源,解决不良竞争问题。
如果大家都不排队,都去抢资源,那么就会导致计算机的使用率不高,任务得不到合理分配,排队的本质就是确认优先级,通过设定优先级,让不同的进程能够按照一定的顺序获取资源,避免混乱和无序竞争。如果优先级设计不合理或者调度算法不科学,就可能导致一些进程长时间得不到CPU的资源,该进程的代码长时间得无法推进,就会造成该进程的饥饿问题。

1.3具体Linux中的优先级

1.3.1查看进程优先级

我们先来写一段代码:

#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    while(1)
    {
        cout<<"i am a process"<<endl;
        sleep(1);
    }

    return 0;
}

跑起来之后我们可以使用这段指令来查询进程的状态:

ps -al | head -1 && ps -al | grep myproc

在这里插入图片描述

  • PRI :进程可被执行的优先级,其值越小越早被执行
  • NI :进程的nice值(进程优先级的修正数据)

1.3.2 PRI and NI

  • PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高
  • NI就是进程的nice值,表示进程可被执行的优先级的修正数值
  • PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
  • 当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
  • 所以,调整进程优先级,在Linux下,就是调整进程nice值
  • nice其取值范围是[-20,19],一共40个级别

1.3.3 PRI VS NI

  • 进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。
  • 可以理解nice值是进程优先级的修正修正数据。

1.3.4 修改进程优先级

我们普通用户是无法给进程提高优先级的,只能减小进程优先级,所以要提升进程优先级必须使用root用户
修改方法:

top
#进入top后按“r”–>输入进程PID–>输入nice值

【注意】: 我们每次修改nice值的时候PRI都是从80开始±的。

1.3.5优先级队列实现原理

在这里插入图片描述
我们所对应的优先级[60,99]在运行时会转换成[100,139]。
进程在进程优先级队列当中是从上往下,从左往右进行调度的,当runing中的进程被调度完之后,通过指针交换来继续调度waiting中的进程,以此循环,就构成了我们所看到的优先级队列。

1.4拓展小知识

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

1.4.1并发

我们的CPU在一定的时间内只能运行一个进程(多个CPU除外),因为我们操作系统中的进程不止一个,那么这些进程都想要被CPU调度运行,那就不得不进行进程切换,每个进程在CPU上运行一段时间再切换到下一个进程运行,我们把进程在CPU上运行的时间称为进程的时间片,进程切换是基于时间片轮转的调度算法。因为CPU速度很快,所以我们日常使用上感觉不到进程是被不断切换的。

1.4.2几个小问题

1.4.2.1为什么函数的返回值会被外部拿到呢?

这是因为我们CPU上有很多的寄存器,我们平时函数返回的时候会将返回数据,写入到寄存器中,外部再通过读取寄存器中的值来获取函数返回值。

return a -> mov eax a //返回值a会转化成mov指令,将变量a中的值保存在eax寄存器中
1.4.2.2系统怎么知道我们的进程当前执行到哪行代码了呢

在我们计算机的CPU中有一个程序计数器PC指针,或者eip,这两个都是用来记录当前进程正在执行的下一行指令的地址。
程序计数器通常被存储在寄存器中,这样可以让CPU在读取指令时更快地访问。由于CPU是按照顺序执行指令的,因此程序计数器的主要功能就是告诉CPU下一个要执行的指令在哪里。

1.4.2.3在CPU中寄存器扮演什么角色呢?

在我们CPU中有很多的寄存器例如,

  • 通用寄存器:eax,ebx,ecx,edx等等。通用寄存器从字面意思来理解就是没有什么用的寄存器,只要你需要,我就可以来供你使用,保存一些数据了什么的。
  • 栈帧寄存器:ebp,esp,eip等等。用来维护函数栈帧结构的寄存器。
  • 状态寄存器status。是一个包含有关处理器状态信息的寄存器。它通常包含一些标志位,例如:溢出标志,进位标志,奇偶标志等等。

CPU中有大量的寄存器主要是为了提高效率,进程的高频数据会被放入寄存器中,寄存器中保存了进程的相关数据,以方便进行对数据的访问或者修改。

cpu寄存器中保存的进程的临时数据,也包含进程的上下文数据,进程上下文包括执行该进程有关的各种寄存器(例如通用寄存器、程序计数器PC、程序状态字寄存器PS等)的值。

1.4.2.4为什么要保存进程的上下文数据呢?

所有的保存都是为了恢复,如果我们不保存进程的上下文数据,那么进程再被切换出去之后,再被切换回来的时候,CPU就不知道该从哪里开始运行,所以我们进程在被切换的时候会将自己的上下文保存好甚至带走,等到再次被调度的时候,首先做的第一件事就是恢复上下文,随后再接着执行代码。

1.4.2.5进程数据上下文保存在哪里呢?

一般情况下我们把进程的上下文是以结构体形式保存在进程的PCB数据结构(task_struct)里的。

struct reg_info
{
	int eax;
	int ebc;
	int eip;
	.......
}

二、环境变量

2.1基本概念

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
  • 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。

在Windows中我们可以通过设置->系统设置->高级系统设置来查看我们Windows中定义的环境变量。
在这里插入图片描述

2.2环境变量PATH

  • PATH : 指定命令的搜索路径

在我们平时想要运行编译好的可执行程序就必须带上./来表示当前目录下的可执行程序,那么我们平时用的pwd,ls指令为什么不用输入路径呢,这是因为系统中存在环境变量PATHPATH里面保存了我们指令的搜索路径,并且这个环境变量是我们打卡开一个终端以生具来的,默认就有的,那么可以使用下面这段指令来查看系统的PATH环境变量:

echo $PATH

在这里插入图片描述
这里是我自己Linux上面配置的环境变量,里面的内容是通过:来分隔开每一个路径的。上面的每一条路径就是我们每执行一条指令,系统查找指令的路径,比如我们想要执行ls指令,系统就会在PATH里的路径中查找ls指令,找到了就正确执行,没有找到就会给我们报错bash:xxx:command not found,报了这个错误表示没有找到指令,证明了我们在执行我们自己的程序的时候如果没有带路径,系统也会给我们在环境变量中查找,只不过没有找到。

所以我们想要将我们当前所处的路径添加到环境变量里,是不是就可以不用带路径呢?
我们来试一试,使用下面指令添加环境变量:

PATH=$PATH:/home/xz/xz_-linux/csdn_2023_12_10
#/home/xz/xz_-linux/csdn_2023_12_10是我自己的当前目录
# 如果只用PATH=/home/xz/xz_-linux/csdn_2023_12_10的话就会直接覆盖这个整个PATH

在这里插入图片描述
添加成功之后我们再来不带./来执行一下我们自己的可执行程序>
在这里插入图片描述
我们可以看到程序没有./也是可以正确执行的。

实际上,我们刚刚修改的PATH环境变量是一种在内存中的环境变量,所以无需担心。如果不小心改错了,只需关闭Xshell并重新登录即可。这个PATH环境变量是在shell中保存的。然而,当shell尚未存在时,即在系统启动时,环境变量是从哪里来的呢?实际上,这些环境变量预先存储在我们系统的一些配置文件中。当系统启动时,它们会被加载到内存中。因此,现在你不必担心你的环境变量被错误修改,只需重新启动一下,我们的环境就会恢复。

2.3环境变量HOME

  • HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录。

在我们平是登录xshell的时候普通用户就会直接进入自己的家目录/home/xxx而root用户会进入自己家目录/root ,那么系统是怎么知道我们的工作目录的呢?
主要原因就是因为当我们在登录时,shell就会直接识别到当前登陆账户是谁,然后给当前用户填充$HOME环境变量,当我们登录时,此时默认就直接cd到了$HOME目录下。这就是我们每次登录之后都会处于自己对应的家目录的原因。

2.4获取环境变量env&&getenv

bash中我们可以使用env命令来获取bash从系统中继承下来的所有环境变量。
在这里插入图片描述
也可以使用getenv来获取某一个环境变量。

#include <iostream>
#include <unistd.h>
using namespace std;
int main()
{
    cout<<"PATH="<<getenv("PATH")<<endl;
    return 0;  
}

在这里插入图片描述

2.4环境变量USER

USER环境变量用来标识当前登录的用户。在终端中输入命令echo $USER,可以查看当前登录用户的用户名。这个环境变量是bash/shell在启动时自动加载的,它记录了当前登录的用户。
我们再来写一段demo代码:

#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    cout<<"USER="<<getenv("USER")<<endl;
    return 0;  
}

我们在普通用户下执行这个程序会打印我们的用户名,用root账户执行则会打印root:
在这里插入图片描述
在这里插入图片描述
了解了上面内容,我们就可以模拟一下系统权限对普通用户和root用户的判定方式:

#include <iostream>
#include <unistd.h>
#include <cstring>
using namespace std;

int main()
{
    char who[32];
    strcpy(who,getenv("USER"));
    if(strcmp(who,"root")==0)
        cout<<"root用户不受条件约束"<<endl;
    else 
        cout<<"普通用户受权限约束"<<endl;
    cout<<"USER:"<<getenv("USER")<<endl;

    
    return 0;  
}

在这里插入图片描述
因为有环境变量的存在,我们的系统就已经具备了能够认识你这个人是谁的能力,只要能认识你是谁,就可以和文件属性当中文件的拥有者所属组和文件所对的权限所对比,进而判定出你有没读写权限。

三、命令行参数

我们C/C++中的main函数其实是可以传参的,这两个参数我们称之为命令行参数:

int main(int argc,char *argv[])
{
	return 0;
}

其中argv是一个指针数组,里面保存了字符串的地址,argc决定了argv中的元素个数,我们来尝试打印一下argv中的内容:

#include <iostream>
#include <unistd.h>
#include <cstring>
using namespace std;
int main(int argc,char *argv[])
{
	for(int i = 0;i<argc;i++)
    {
        printf("argv[%d]->%s\n",i,argv[i]);
    }
	return 0;
}

在这里插入图片描述
这时候我们发现里面内容只有一个就是./myproc,我们再来给可执行程序后面加一些选项来运行一下看看:
在这里插入图片描述
我们的main函数也是可以被调用的,main函数时程序被执行调用的第一个函数,调用main函数之前,bash会将我们在命令行输入的./myproc -a -b -c -d以空格分隔开分割成argc个字符串。
并保存在argv中其中argv[argc]=NULL,最终再传递给main函数。

3.1命令行参数作用

#include <iostream>   
#include <cstring>  
using namespace std;  
int main(int argc,char *argv[])  
{  
	if(argc!=2)  
	{  
	   printf("Usage:%s -[a|b|c|d]\n",argv[0]);                                           
	   return 0;                                                          
	}                                                                      
	if(strcmp(argv[1],"-a")==0)                                            
	{                                   
	   printf("功能1\n");              
	}                                   
	else if(strcmp(argv[1],"-b")==0)    
	{                                   
	   printf("功能2\n");              
	}                                   
	else if(strcmp(argv[1],"-c")==0)    
	{                                   
	   printf("功能3\n");              
	}                                   
	else if(strcmp(argv[1],"-d")==0)    
	{                                   
	   printf("功能4\n");              
	}
	else
	{
		printf("defalut功能\n");
	}
	return 0;
}             

在这里插入图片描述
命令行参数可以通过输入不同的选项,来控制程序执行不同的功能代码。
命令行参数为指令,工具,软件等提供命令行选项的支持!

3.3main函数的第三个参数

main函数除了上面那两个参数,还有一个叫做char *env[]的参数;

int main(int argc,char *argv[],char *env[])
{
	return 0;
}

我么也可以来打印一下env中的内容:

#include <iostream>
#include <unistd.h>
#include <cstring>
using namespace std;
int main(int argc,char *argv[],char* env[])
{
	for(int i = 0;env[i];i++)
    {
        printf("env[%d]->%s\n",i,env[i]);
    }
	return 0;
}

还可以通过第三方变量environ获取

#include <stdio.h>
int main(int argc, char *argv[])
{
	extern char **environ;
	int i = 0;
	for(; environ[i]; i++){
	printf("env[%d]->%s\n",i,environ[i]);
	}
	return 0;
}

在这里插入图片描述

argv和env的结构一模一样,所以我们的C/C++代码一共会有两张核心向量表,一张叫做命令行参数表,一张叫做环境变量表。环境变量表会从父进程中继承下来。
在这里插入图片描述
我们所运行的进程,都是子进程, bash本身在启动的时候,会从操作系统的配置文件中读取环境变量信息,子进程会继承父进程交给我的环境变量!

3.4验证环境变量的继承

我们可以自己定义一个环境变量导入系统中的环境变量表当中,我们想要增加一个环境变量可以使用下面命令:

export MY_VALUE=666666666666

在这里插入图片描述
可以看到我们自己定义的环境变量已经被导入到环境变量表当中。
我们接下来再去之心我们刚刚的代码:
在这里插入图片描述
可以发现它里面也有 MY_VALUE 这个环境变量,说明子进程 myproc 继承了父进程 bash 的环境变量。
删除一个环境变量可以使用unset 环境变量命令。

unset MY_VALUE

四、本地变量&&内建命令

本地变量指的就是我们可以在命运行当中直接定义,比如a=1,b=2,c=3。
在这里插入图片描述
定义的本地变量是不会被写入环境变量表的,所以我们使用env命令也是不会显示我们刚刚定义的那些变量,我们可以使用set命令来查看当前系统所定义的所有环境变量和本地变量。
在这里插入图片描述
此时我们就可以查出来我们刚刚定义的本地变量。
本地变量是不会被子进程进程的,只会在本地bash中有效。
我们再来通过一段代码验证一下:

#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    printf("MY_VALUE=%s\n",getenv("MY_VALUE"));  
    return 0;  
}

在这里插入图片描述
我们可以通过export将本地变量写入环境变量中

export MY_VALUE
将本地变量MY_VALUE导入到系统环境变量

在这里插入图片描述
此时就可以打印出来我们刚刚添加的环境变量了。

4.1常规命令&&内建命令

我们再来看这个图中,我们定义了本地变量MY_VALUE,我们的可执行程序(bash的子进程)都读不到这个变量,为什么echo可以读取到呢?
在这里插入图片描述
其实我们命令行上执行的指令不一定都要创建子进程,就好比王婆说媒一样,一些有任务特别难的或者风险的,王婆就会找别人去帮忙说媒。如果是一些很有把握的事情,那王婆还是愿意自己去做的。

由此可以推出我们指令是有区别的:

  • 常规命令:通过创建子进程完成的
  • 内建命令:bash不创建子进程,而是有自己亲自执行,类似于bash调用了自己写,或者系统提供的函数。

所以echo是一个内建命令,它是由bash自己执行的,与此同时我们的cd命令也是一个内建命令,我们可以通过调用chdir来改变当前工作目录。

#include <iostream>
#include <unistd.h>
#include <cstring>
using namespace std;
int main(int argc,char *argv[])
{
    sleep(30);
    printf("change begin\n");
    if(argc==2)
    {
        chdir(argv[1]);
    }
    printf("change end\n");
    sleep(30);
    return 0;
}

在这里插入图片描述
在命令行中输入 cd 命令的时候,bash 并不会创建子进程,而是去判断命令行参数是否为 cd,如果是就直接去调用 chdir 系统接口来切换bash的工作目录。

🍀小结🍀

今天我们学习了"【Linux】探索Linux进程优先级 | 环境变量 |本地变量 | 内建命令"相信大家看完有一定的收获。种一棵树的最好时间是十年前,其次是现在! 把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波💕💕~~~,本文中也有不足之处,欢迎各位随时私信点评指正!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1307300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低成本物联网安全芯片ACL16_S 系列,可应用物联网认证、 SIM、防抄板和设备认证等产品上

ACL16_S 芯片是针对物联网认证、 SIM、防抄板和设备认证需求推出的高安全芯片。芯片采用 32 位 ARMCortex™-M0 系列内核&#xff0c;片内集成多种安全密码模块&#xff0c;包括 RSA/ECC DES/TDES、 SHA-1/-256、 AES-128/-192/-256 等国际安全算法&#xff0c;支持真随机数发…

AtCoder Beginner Contest 332 A~F

A.Online Shopping(计算) 题意&#xff1a; 需要购买 N N N种物品&#xff0c;第 i i i种物品的价格为 P i P_i Pi​&#xff0c;且第 i i i件物品需买 Q i Q_i Qi​件。 商店满 S S S元包邮&#xff0c;不满则需支付 K K K元邮费&#xff0c;问需支付多少钱。 分析&#x…

『 Linux 』进程地址空间存在的意义

文章目录 前言&#x1f995;&#x1f996; 防止进程对物理内存的非法(危险)访问&#x1f996; 进程管理模块与内存管理模块的解耦合&#x1f996; 实现进程间的独立性 前言&#x1f995; 在文章『 Linux 』进程地址空间概念中提到了进程地址空间的部分概念; 这部分概念主要围绕…

设计模式—观察者模式

观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;使得当一个对象的状态发生变化时&#xff0c;所有依赖于它的对象都会得到通知并自动更新。 在观察者模式中&#xff0c;有两个核心角色&#xf…

vue-如何实现带参数跳转页面

文/朱季谦 在vue框架的前端页面上&#xff0c;若要实现页面之间的带参数跳转&#xff0c;可参考以下实现过程&#xff1a; 例如&#xff0c;点击截图中的“查看试卷”&#xff0c;可实现带参跳转到相应的试卷页面&#xff0c;该功能类似查看试卷的详情页面&#xff1a; 假如以…

C#多线程总结

目录 前言 一、异步线程 使用async和await关键字 基于委托实现 二、同步线程 三、Thread线程 开启线程 设置线程优先级 Thread拓展封装 四、ThreadPool线程池 常规使用 设置线程数 线程等待 Thread和ThreadPool比较 通过线程池做一些扩展&#xff08;定时器类&am…

解析视频美颜SDK的算法:美肤、滤镜与实时处理

如今&#xff0c;美颜技术在视频处理中扮演着关键的角色&#xff0c;为用户提供更加精致的视觉体验。本文将深入探讨视频美颜SDK的算法&#xff0c;聚焦于美肤、滤镜与实时处理等方面&#xff0c;揭示背后的科技奥秘。 一、美肤算法的魅力 视频美颜的一个核心功能就是美肤&am…

被央视报道过的AIGC产品-贝塔创作(BetaCreator)使用指南

产品地址&#xff1a;betacreator.com 真人图 人台图 商品图 商品变色 建议使用浅色服装进行变色&#xff0c;效果更好 如果没有浅色服装&#xff0c;可以先把服装颜色变为白色

redis-学习笔记(Jedis 前置知识)

自定义的 Redis 客户端 咱们可以实现编写出一个自定义的 Redis 客户端 因为 Redis 公开了自己使用的自定义协议 ---- RESP 协议清楚了, 那么通信数据格式就清除了, 就能完成各层次之间的数据传输, 就能开发服务器和客户端 RESP — Redis 的 序列化 协议 特点: 简单好实现快读进…

App防止恶意截屏功能的方法:iOS、Android和鸿蒙系统的实现方案

防止应用被截图是一个比较常见的需求&#xff0c;主要是出于安全考虑。下面将分别为iOS&#xff08;苹果系统&#xff09;、Android&#xff08;安卓系统&#xff09;及HarmonyOS&#xff08;鸿蒙系统&#xff09;提供防止截屏的方法和示例代码。 在企业内部使用的应用中&…

python学习:浅拷贝与深拷贝详解

copy 一、 & is二、浅拷贝 & 深拷贝(一)、浅拷贝(二)、深拷贝 三、问题 一、’ ’ & ‘is’ ’ 和is是python对象比较常用的两种方式,简单来说,‘ ‘操作符比较对象之间的值是否相等,如 a b 而’is’操作符比较的是对象的身份标识是否相等,即它们是否是同一个…

HNU数据库大作业-世界杯比赛系统

前言 之前做的那个版本bug较多&#xff0c;后进行了大量优化。 此项目是一个前后端分离的项目&#xff0c;前端主要使用htmlcssjs搭建&#xff0c;使用的是layui框架 后端使用php语言&#xff0c;仅实现了简单的查询数据库功能&#xff0c;无法实现多并发查询等复杂情况 数…

jetpack compose 学习(-)

年底了,无聊的时间总是缓慢的,找个事情做一做,打发打发时间,刚好看到jetpack compose 学习学习,毕竟androidStudio 默认创建的项目都带上了这个,学习网站:https://developer.android.com/jetpack/compose/modifiers?hlzh-cn 1. 首先androidStudio创建一个新项目 喜欢kotlin的,…

亚马逊、速卖通自养号测评的安全稳定性与成本优势分析

在跨境电商平台的运营中&#xff0c;买家评价的重要性不言而喻。很多买家在购买产品前都会查看评论&#xff0c;比较同类产品的买家口碑&#xff0c;以做出更明智的购买决策。 因此&#xff0c;测评一直是各大跨境电商平台的一种重要推广方式&#xff0c;测评同时也是很多卖家…

BugKu-Web-Simple_SSTI_1Simple_SSTI_2(浅析SSTI模板注入!)

何为SSTI模块注入&#xff1f; SSTI即服务器端模板注入&#xff08;Server-Side Template Injection&#xff09;&#xff0c;是一种注入漏洞。 服务端接收了用户的恶意输入以后&#xff0c;未经任何处理就将其作为Web应用模板内容的一部分&#xff0c;模板引擎在进行目标编译渲…

TCP/IP详解——网络基本概念

文章目录 一、网络基本概念1. OSI 7层模型1.1 每层对应的协议1.2 每层涉及的设备1.2.1 物理层设备1.2.2 数据链路层设备1.2.3 网络层设备1.2.4 传输层设备1.2.5 交换机和路由器的应用1.2.6 问题 2. TCP/IP 4层模型3. 物理层传输介质3.1 冲突域 4. 数据链路层4.1 以太网帧结构4.…

socket 套接字

1、套接字介绍 socket起源于Unix&#xff0c;遵循“一切皆文件”出发点&#xff0c;都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。 在设计模式中&#xff0c;Socket把复杂的TCP/IP协议族隐藏在Socket接口后面&#xff0c;Socket去组织数据&#xf…

Godot导出Android包报错:无效的包名称

问题描述 使用Godot为项目导出Android平台包时报错&#xff0c;提示&#xff1a;“无效的包名称&#xff1a;项目名称不符合包名格式的要求。请显式指定包名。” 解决办法 修改导出配置项“包->唯一名称”。 该项缺省值“org.godotengine.$genname”不能直接使用&#x…

36V/48V转12V 10A直流降压DC-DC芯片-AH1007

AH1007是一款36V/48V转12V 10A直流降压&#xff08;DC-DC&#xff09;芯片&#xff0c;它是一种高性能的降压变换器&#xff0c;常用于工业、汽车和电子设备等领域。 AH1007采用了先进的PWM调制技术和开关电源控制算法&#xff0c;能够高效地将输入电压从36V/48V降低到12V&…

SSM整合——Springboot

1.0 概述 1.1 持久层&#xff1a; DAO层&#xff08;mapper&#xff09; DAO层&#xff1a;DAO层主要是做数据持久层的工作&#xff0c;负责与数据库进行联络的一些任务都封装在此 DAO层的设计首先是设计DAO的接口&#xff0c; 然后在spring-mapper.xml的配置文件中定义此接…