【Linux】冯诺依曼体系结构、操作系统、进程概念、进程状态、环境变量、进程地址空间

目录

  • 一、冯诺依曼体系结构
  • 二、操作系统(OS)
    • 1. 操作系统是什么
    • 2. 操作系统如何做管理
    • 3. 系统调用和库函数概念
  • 三、进程
    • 1. 进程是什么?
    • 2. 描述进程-PCB
    • 3. 查看进程的方法
  • 四、进程状态
    • 1 运行、阻塞和挂起状态
    • 2 Linux中的进程状态
  • 五、进程优先级
    • 1. 什么是优先级
    • 2.查看优先级
    • 3. 修改优先级
  • 六、其他概念
  • 七、环境变量
    • 1.引入
    • 2.环境变量和本地变量的关系
    • 3.命令行参数表和环境变量表
    • 4.子进程获取环境变量的方式
  • 八、进程地址空间
    • 1.虚拟地址空间的引入
    • 2.虚拟地址空间布局
  • 3.为什么要存在虚拟地址空间?

一、冯诺依曼体系结构

冯诺依曼思想包括:存储程序、程序控制和计算机的五大功能部件。
存储程序:将程序存放在计算机的存储器中。
程序控制: 按指令地址访问存储器并取出指令,经译码依次产生指令执行所需的控制信号,实现对计算的控制,完成指令的功能。
五大功能部件:控制器、运算器、存储器、输入设备、输出设备。
其中,运算器完成算术运算、逻辑运算,
控制器控制指令的执行, 根据指令功能给出实现指令功能所需的控制信号;
控制器和运算器构成了中央处理器CPU。
存储器就是内存,存放程序和数据,带电存储,具有掉电易失的特性。
输入设备能够输入操作者提供的原始信息,并将其转化为机器能识别的,如键盘、鼠标等。
输出设备将计算机处理的结果用人们或其他机器能够接受的方式输出,如显示屏。
在这里插入图片描述

  • 在不考虑缓存的情况下,CPU只能对内存进行读写,不能直接访问其他设备。
  • 外设(输入设备或输出设备)想要输入或输出数据,也只能写入内存或从内存中读取。

二、操作系统(OS)

1. 操作系统是什么

操作系统是一个进行软硬件资源管理的软件。
操作系统包括:内核(进程管理、内存管理、文件管理、驱动管理)、其他程序(如函数库,shell程序等等)
操作系统为什么对软硬件资源进行管理呢? 操作系统通过管理好软硬件资源(手段),给用户提供良好(安全、稳定、高效、功能丰富)的执行环境(目的)。

2. 操作系统如何做管理

先描述,在组织。将需要管理的对象用结构体描述,再将每个结构体进行连接,形成链表一样的数据结构。
当操作系统下达命令后,驱动程序就会对这些结构进行增删查改等操作。
计算机的层状结构:
在这里插入图片描述

3. 系统调用和库函数概念

  • 系统调用:在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。在执行一段程序时,比如printf(“hello world”)时,实际上进行了系统调用,但我们并不知道,因为编译器帮你做了。
  • 库函数:系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。

三、进程

1. 进程是什么?

进程是程序的一个执行实例,是正在执行的程序。
以上是书本中的概念,一句话来概括:进程=内核描述进程的数据结构+当前进程的代码和数据。
当我们写好一段代码经过编译、链接等过程后生成了可执行程序,此时的可执行程序是一个文件,存储在磁盘中。当我们运行该程序时,该程序的代码和数据就会被加载到内存中。此时操作系统会将进程的各种属性放在一个叫做PCB的结构体中,并将PCB用链表等数据结构管理起来,方便进行增删查改。

2. 描述进程-PCB

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
  • 课本上称之为PCB(process control block),Linux操作系统下的PCB是:task_struct。

Linux中描述进程的结构体叫做task_struct,它会被装载到RAM(内存)里并且包含着进程的信息。
task_struct内容分类

  • 标示符:描述本进程的唯一标示符,用来区别其他进程。
  • 状态:任务状态,退出代码,退出信号等。
  • 优先级:相对于其他进程的优先级。
  • 程序计数器:程序中即将被执行的下一条指令的地址。
  • 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
  • 上下文数据:进程执行时处理器的寄存器中的数据。
  • I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  • 其他信息。

3. 查看进程的方法

进程的信息可以通过/proc系统文件夹查看

  • 要获取PID为1的进程信息,需要查看/proc/1这个文件夹。
    在这里插入图片描述
  • 大多数进程信息同样可以使用top和ps这些用户级工具来获取。在这里插入图片描述
    当我们执行上述程序,便可以通过以下指令查询到该进程的信息。
    在这里插入图片描述
    通过系统调用查看进程PID
  • 进程id:PID,通过getpid()获取
  • 父进程id:PPID,通过getppid()获取
    在这里插入图片描述
    在这里插入图片描述
    当我们多次执行程序,能够发现每次启动时进程id都不同,但父进程id都相同
    在这里插入图片描述
    这是因为这些进程有共同的父进程bash——命令行解释器。在这里插入图片描述

通过系统调用创建进程
创建进程需要用到fork,先通过man手册来了解一下fork。在这里插入图片描述
fork能够创建子进程,在父进程中,返回值为子进程id,在子进程中返回值为0。
在这里插入图片描述
在这里插入图片描述
显然,fork调用后的内容打印了两边,原因是fork()创建了子进程,父子进程都打印了fork后。

我们还可以通过搭配if-else来进行分流,利用fork的返回值进行区分
在这里插入图片描述

在这里插入图片描述
fork之后执行流会变成两个执行流,当有一个执行流尝试修改数据时,操作系统会为该进程将代码和数据拷贝一份,再进行修改,我们称之为写时拷贝。

四、进程状态

1 运行、阻塞和挂起状态

程序在运行时,需要CPU读取程序的数据并进行计算,但进程的数量一般会多于CPU,所以操作系统采用了运行队列来对进程进行管理。进程入队列,等待CPU资源。CPU调度进程就是从运行队列中,找到进程PCB,并执行进程对应的代码和数据。
进程的运行状态并不是指进程正在运行,而是指这个进程的PCB在CPU的运行队列中。
进程还会占用外设资源,但外设的运行速度很慢,也会出现多个进程访问一个硬件的情况,所以这里进程也需要排队。当CPU调度的某个进程需要访问外设时,操作系统就会把这个进程放到硬件的等待队列中,直到硬件准备就绪,此时这个进程的状态就是阻塞状态
当多个进程状态都是阻塞时,这些进程无法被CPU立即在执行,需要排队很长时间,进程的代码和数据始终占用着内存,操作系统为了避免这样的浪费,会将这些进程的代码和数据暂时保存在磁盘上,但保留进程的PCB在内存里,这样的进程,称之为挂起进程。等到进程需要的硬件资源准备就绪后,操作系统会将进程的代码和数据唤回内存。

2 Linux中的进程状态

运行状态:并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列
里。
在这里插入图片描述
在这里插入图片描述
只要执行一个死循环程序,即可观察到运行状态。

休眠状态:当我们像上述代码中添加一个printf语句,观察现象。
在这里插入图片描述
观察到此时状态变成了S,这就是休眠状态。
因为我们的代码访问了显示器,显示器是外设,速度很慢,99%的时间都是进程等待显示器就绪,1%的时间是CPU在运行,所以查看到进程是休眠状态,是阻塞状态的一种。

停止状态:当进程被停止时,也是阻塞状态的一种。

kill -19 + 进程id --- 停止运行进程
kill -18 + 进程id --- 继续运行进程

在这里插入图片描述
可以看见当我们输入kill -19后,进程的状态从R+变成了T,也就是停止了。
这里的+是用来标志这个进程是前台还是后台进程,状态后面带+,表示该进程在前台,不带+则是后台进程。
后台进程在运行时,shell命令行可以使用,但无法使用ctrl+C将后台进程终止,需要使用kill -9来杀掉进程。
磁盘休眠状态:有时候也叫不可中断睡眠状态,在这个状态的进程通常会等待IO的结束。
当阻塞进程太多,内存空间不足,操作系统会将一些进程挂起,但如果依旧无法解决问题,OS就会将进程杀死,但杀死进程可能会导致数据的丢失,造成巨大损失,所以就提供了磁盘休眠状态,用D来表示,这样的进程无法被OS杀掉,只能等IO结束进程自己醒来。但这种状态一般情况下不会出现,只有在高IO的情况下才可能会出现。
跟踪状态:当我们调试某个可执行程序时,如果打了断点,当进程运行到断点就会停下来,等待我们的下一步操作,此时查看进程的状态就是跟踪状态,用小写字母 t 表示。在这里插入图片描述
僵死状态
一个进程在完成任务之后,其父进程或操作系统需要知道该任务完成的结果,所以当进程终止时,OS的机制是不立即释放该进程的内存资源的,要保存到其父进程来读取进程的结果。
但如果某个进程退出后,没有被父进程或OS回收,这样的进程就是僵尸进程。
下面用一段代码演示僵尸进程的产生,首先创建一个子进程,让子进程在父进程之前退出,此时子进程就会处于僵死状态。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{pid_t id = fork();if (id == 0){printf("我是子进程,pid:%d, ppid:%d\n", getpid(), getppid());sleep(5);exit(0);}else if (id > 0){int count = 10;while (count--){printf("我是父进程,pid:%d, ppid:%d\n", getpid(), getppid());sleep(1);}}return 0;
}

在这里插入图片描述

可见当程序执行五秒之后子进程退出但父进程不回收,子进程的状态变为Z+僵死状态。
当父进程运行结束,操作系统会将父进程和子进程一起回收,避免内存泄漏。
进程的退出状态也属于进程的基本信息,会被保存在进程PCB中,也就是说如果父进程一直不读取子进程的退出状态,那么PCB就要一直维护这种状态,这是就会产生内存泄露的问题。
僵尸进程无法被杀死,因为它已经死了。
死亡状态:当进程死亡后,操作系统会很快的回收进程的所有的资源和数据,以至于我们无法观察到X状态。它的PCB和对应的代码和数据都被释放,不再占用内存资源。
孤儿进程:如果一个程序运行时,父进程先退出,那么子进程就变成了孤儿进程,此时1号init进程就会回收它。
在这里插入图片描述
当我们用刚才的程序,提前杀死父进程,可以看到子进程的PPID变成了1,并且该进程变成了后台进程。
作为操作系统是必须要领养这个孤儿进程的,为了防止内存泄漏!

五、进程优先级

1. 什么是优先级

cpu资源分配的先后顺序,就是指进程的优先权(priority)。
优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

2.查看优先级

在这里插入图片描述
通过ps -l指令可以查看进程的信息,其中PRI和NI组合起来用来表示进程的优先级。
PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。
那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为: PRI(new)=PRI(old)+nice。
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行。
所以,调整进程优先级,在Linux下,就是调整进程nice值。
nice其取值范围是-20至19,一共40个级别。

3. 修改优先级

想要修改优先级,需要使用top指令,并且需要管理员身份,这个指令用来修改nice值,范围是-20到19,如果输入范围以外的数,也不会获得更大或者更小的数值,因为OS不会让我们过度修改nice值。
方法:进入top后按“r”–>输入进程PID–>输入nice值

六、其他概念

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

七、环境变量

1.引入

我们平时使用的Linux指令其实是可执行程序,但我们自己创建的可执行程序在运行时需要加上./,而系统提供的指令不需要,这是为什么呢?
要执行一个程序需要先找到它,这也是为什么我们要在前面加上./,指的是当前目录,而系统指令的位置在/usr/bin目录下,想要让我们创建的可执行程序不用加上./可以将其拷贝到/usr/bin目录下,但不建议这样做,因为自己创建的程序未经过严格的测试,会污染系统的指令池。
那为什么在/usr/bin目录下系统就能够找到呢?
因为系统中存在环境变量PATH,操作系统在启动时会定义一个PATH变量,可以利用echo $PATH指令进行查看。
在执行系统指令时,操作系统会默认在PATH环境变量里面的路径查找我们输入的指令,所以想要不带./运行自己的程序可以将程序所在路径添加进环境变量PATH中。在这里插入图片描述
我们可以随意的修改PATH,因为只要重新登陆,PATH就会恢复。
使用export指令来修改环境变量。
export PATH=路径 这种操作会覆盖原有的内容不建议使用
export PATH=$PATH:路径 建议使用
当修改成功之后,就可以不加./执行自己的程序了。
不过重新登陆后环境变量就会恢复到默认,所以不加./执行自己的程序也只限定在本次登录。

2.环境变量和本地变量的关系

父进程的本地变量不会被子进程继承,但环境变量会被继承下去。

#include <stdio.h>
#include <stdlib.h>#define MY_ENV "myval"int main()
{char* myenv = getenv(MY_ENV);if (myenv == NULL){printf("%s:not found\n", MY_ENV);return 1;}printf("%s=%s\n", MY_ENV, myenv);return 0;
}

在这里插入图片描述
使用set指令可以显示所有本地变量,使用env指令可以显示所有环境变量。
取消本地变量:unset+变量名

在定义环境变量时可以带双引号也可以不带,但如果环境变量带有空格就要加上双引号了。

3.命令行参数表和环境变量表

在main函数中有几个隐藏的参数,平时在做OJ题的时候有可能会注意到。

int main(int argc, char* argv[])

不过我们平时并不使用这些参数,但在系统编程中这些参数比较常用。

int main(int argc, char* argv[])
{int i = 0;for (; i < argc; ++i){printf("argv[%d]->%s\n", i, argv[i]);}return 0;
}

在这里插入图片描述
通过上面的例子可以看出,main函数中的第一个参数argc是命令行中运行程序的时候以空格为分隔符字符串的个数,而argv指针数组中的指针,指向的就是这些字符串。
系统提供的各种指令能够通过带-a、-l等实现不同的功能就是这样实现的

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    
#include <string.h>    
void Usage(const char* name)    
{    printf("\nUsage: %s -[a|b|c]\n\n", name);                                                                                                              exit(0);    
}    int main(int argc, char* argv[])    
{    if (argc != 2) Usage(argv[0]);    if (strcmp(argv[1], "-a")) printf("打印当前目录下的文件名\n");    else if (strcmp(argv[1], "-b")) printf("打印当前目录下文件的详细信息\n");    else if (strcmp(argv[1], "-c")) printf("打印当前目录下的文件名(包含隐藏文件)\n");    else printf("更多功能待开发\n");    return 0;    
}

利用这两个参数可以实现一个如上所示的进程。

4.子进程获取环境变量的方式

在前面我们知道了可以通过getenv()系统调用可获得环境变量的值。
下面介绍的一种方式,也是通过main函数的参数:char* env[]

int main(int argc, char* argv[], char* env[])
{int i = 0;for (; env[i]; ++i){printf("env[%d]->%s\n", i, env[i]);}return 0;
}

在这里插入图片描述
通过上面这段代码我们打印出了所有的环境变量。

C语言提供了一个第三方的指针变量environ,在调用main函数时,系统就把这个变量传给了main,environ就相当于指针数组env[]的另一个数组名,environ指向的就是env的第一个元素。environ是一个二级指针,下面用environ打印环境变量

int main()
{extern char** environ;int i = 0;for (; environ[i]; ++i){printf("environ[%d]->%s\n", i, environ[i]);}return 0;
}

八、进程地址空间

1.虚拟地址空间的引入

#include <stdio.h>
#include <unistd.h>int global_val = 100;int main()
{pid_t id = fork();if (id == 0){int cnt = 0;while (1){printf("我是子进程, pid:%d, ppid:%d, global_val:%d, &global_val:%p\n", getpid(), getppid(), global_val, &global_val);sleep(1);++cnt;if (cnt == 3){global_val = 300;printf("子进程已经更改了global_val的值了!\n");}}}while (1){printf("我是父进程, pid:%d, ppid:%d, global_val:%d, &global_val:%p\n", getpid(), getppid(), global_val, &global_val);sleep(1);}return 0;
}

在这里插入图片描述
从上面程序的结果来看,一个全局变量在地址并未改变的情况下,竟然出现了不同的值,这是为什么呢?首先一个变量肯定是只能有一个值的,但地址只有一个,这就说明现在内存中应该出现了两个变量。而一个变量在内存中只能有一个地址,那么我们打印出来的一定不是真实的地址,,也就是说现在的内存中有两个全局变量,分别属于父子进程,并且他们都拥有自己的物理内存地址,只是他们共用了一个虚拟地址。之前在学习C和C++时所看到的其实都是虚拟地址,真正的物理地址,用户看不到,统一由操作系统保管。

2.虚拟地址空间布局

在这里插入图片描述
代码段:存放函数体的二进制代码,代码段是只读的,可以防止其他进程恶意修改正在运行的进程的二进制指令,程序的执行就是从代码段中的main函数开始执行,程序运行结束后由操作系统回收。
初始化数据段:用于存储初始化的全局变量、static变量、对象、字符串、数组等常量。但基本类型常量不在这里,它们在代码段。
未初始化数据段:包含所有未初始化的全局变量和static变量,此段中所有变量由0或NULL初始化。
堆区:堆区时向上增长的,程序运行时动态申请的内存空间就是在堆上开辟的,由开发人员手动申请释放,。
映射段:也称共享区,存储动态链接库、以及共享文件等。
栈区:栈时向下增长的,函数的局部变量、返回值、形参等都在栈区上,函数调用时的栈帧就在栈上。

mm_struct就是操作系统描述虚拟空间所构造的结构体。

3.为什么要存在虚拟地址空间?

虚拟内存是计算机系统内存管理的一种技术,它让进程认为它拥有连续可用的内存,实际上它通常被分割成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,需要时才进行数据交换。
进程在和外设IO的过程,所占内存大小为4KB,即4096个连续的物理地址,这部分区域被称为页。
进程无法直接接触物理内存,只能通过虚拟地址依靠页表映射物理地址的方式,来间接访问物理内存。因为页表的存在,进程在访问不属于当前进程的地址时,页表就会拦截进程非法访问地址的请求。

在这里插入图片描述
如上面的例子,当子进程修改global_val时,操作系统会先拷贝这个变量,更改页表映射,最后让子进程对数据进行修改,这样的技术被称为写时拷贝。这样保证了进程的独立性,通过虚拟地址空间和页表,让不同的进程使用同一个虚拟地址,能够映射到不同的物理内存。

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

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

相关文章

仅从个人的角度,聊聊年底的程序员招聘与入职情况

Hello&#xff0c;大家好&#xff0c;我是 Sunday。 一般到了年底&#xff0c;招聘的 HC 都会大规模的缩减。特别是在今年这样的一个行情之下&#xff0c;很多公司因为不确定明年的项目情况&#xff0c;都会开始大规模的停止招聘甚至是开始裁员。 所以&#xff0c;从理论上来…

2023第十七届中国品牌节 | 每日互动刘宇分享大模型创新应用AITA智选人群工具

11月18日-20日&#xff0c;2023第十七届中国品牌节在杭州市云栖小镇国际会展中心盛大举行。本次活动以“复苏与腾飞”为主题&#xff0c;来自政、商、产、学、媒等各界嘉宾6000余位济济一堂&#xff0c;共同见证民族品牌的崛起&#xff0c;携手奉献一场史无前例的“品牌人的亚运…

亚马逊防关联如何做?看这一篇就够了

我们都知道亚马逊在众多跨境电商平台里属于严格的那个&#xff0c;商家们常常调侃亚马逊死法千万种&#xff0c;但最惨的还是账户被平台关联封号。有的新手刚注册还没开始就被关联封号了&#xff0c;有的业绩不错的店铺操作没注意&#xff0c;在别的地方登录了一下就被封了&…

【Flink】核心概念:任务槽(Task Slots)

任务槽 每个 worker&#xff08;TaskManager&#xff09;都是一个 JVM 进程&#xff0c;可以在单独的线程中执行一个或多个 subtask。为了控制一个 TaskManager 中接受多少个 task&#xff0c;就有了所谓的 task slots&#xff08;至少一个&#xff09;。 每个任务槽&#xf…

MongoDB随记

MongoDB 1、简单介绍2、基本术语3、shard分片概述背景架构路由功能chunk&#xff08;数据分片&#xff09;shard key&#xff08;分片键值&#xff09; 4、常用命令 1、简单介绍 MongoDB是一个分布式文件存储的数据库&#xff0c;介于关系数据库和非关系数据库之间&#xff0c…

SpringDoc基础配置和集成OAuth2登录认证教程

本期内容 学会通过注解和Java代码的方式添加SpringDoc配置。在swagger-ui提供的页面上提供OAuth2登录认证&#xff0c;在集成Security的情况下便捷获取access_token并在请求时按照OAuth2规范携带。 为什么集成OAuth2登录认证&#xff1f; 现在大部分教程是在swagger-ui页面添…

系列十、ReentrantReadWriteLock

一、概述 ReentrantReadWriteLock是ReadWriteLock的一个子类&#xff0c;具有读锁和写锁的双重功能&#xff0c;通常用于做缓存。 二、案例代码 2.1、ReentrantReadWriteLockCache /*** Author : 一叶浮萍归大海* Date: 2023/11/20 17:57* Description: 使用ReentrantReadWri…

学习笔记5——对象、直接内存、执行引擎,string

学习笔记系列开头惯例发布一些寻亲消息 链接&#xff1a;https://baobeihuijia.com/bbhj/contents/3/192486.html 创建对象的步骤 对象对应的类是否被加载&#xff0c;链接&#xff08;链接到真实的内存地址&#xff09;&#xff0c;初始化&#xff08;类初始化&#xff09;…

Linux常见命令手册

目录 文件命令 文件和目录命令 文件的权限命令 文件搜索命令 进程命令 查看进程命令 关闭进程命令 用户和群组命令 网络命令 firewall-cmd 网络应用命令 高级网络命令 网络测试命令 网络安全命令 网络配置命令 软件管理命令 系统信息命令 vi编辑器 关机命令…

【android】install android NDK

目录 1 下载NDK 2 解压 3 android-ndk的配置 1 下载NDK 下载网址&#xff1a;NDK 下载 | Android NDK | Android Developers 如果没有所需要的版本&#xff0c;则点击页面下面 不受支持的 NDK 下载需要的版本。 2 解压 将压缩文件&#xff08;例如 android-ndk-r25c-…

webpack 中,filename 和 chunkFilename 的区别

filename filename 是一个很常见的配置&#xff0c;就是对应于 entry 里面的输入文件&#xff0c;经过webpack打包后输出文件的文件名。比如说经过下面的配置&#xff0c;生成出来的文件名为 index.min.js。 chunkFilename chunkFilename 指未被列在 entry 中&#xff0c;却…

使用 Splashtop 的开放 API 简化 IT 工作流程

我们的工作方式在不断变化&#xff0c;IT 技术人员必须迅速适应时代的变化。越来越多的公司正在转向混合和远程策略&#xff0c;这为那些在服务台或IT技术人员工作的人增加了额外的工作层。对于系统管理员来说&#xff0c;管理一切都可能变得更加复杂。 找到合适的软件来管理多…

Stable Diffusion - StableDiffusion WebUI 软件升级与扩展兼容

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/134463035 目前&#xff0c;StableDiffusion WebUI 的版本是 1.6.0&#xff0c;同步更新 controlnet、tagcomplete、roop、easy-prompt-selector等…

JDY蓝牙注意事项

波特率设置&#xff1a;9600&#xff0c;不接受115200&#xff0c;或者38400. 不同于WiFi测试&#xff0c;jdy蓝牙不接受AT"指令&#xff0c;可以使用“ATVERSION"指令测试 安信可公司的那个蓝牙指令在这里没有用&#xff0c;不知道是不是生产的公司不一样

9 Redis的发布和订阅

127.0.0.1:6379> publish topic1 jack (integer) 0 #表示此时没有被订阅&#xff0c;消息丢了发布订阅&#xff1a;发送即忘的原则&#xff0c;发了就不管了&#xff0c;没有人订阅&#xff0c;就丢了。 127.0.0.1:6379> subscribe topic1 Reading message ... #表示开…

【LeetCode】每日一题 2023_11_20 最大子数组和(dp)

文章目录 刷题前唠嗑题目&#xff1a;最大子数组和题目描述代码与解题思路 刷题前唠嗑 LeetCode? 启动&#xff01;&#xff01;&#xff01; 今天是一道 LeetCode 的经典题目&#xff0c;如果是 LeetCode 老手&#xff0c;估计都刷过&#xff0c;话是这么说&#xff0c;但咱…

Python 自动化(十八)admin后台管理

admin后台管理 什么是admin后台管理 django提供了比较完善的后台数据库的接口&#xff0c;可供开发过程中调用和测试使用 django会搜集所有已注册的模型类&#xff0c;为这些模型类提供数据管理界面&#xff0c;供开发使用 admin配置步骤 创建后台管理账号 该账号为管理后…

简单回顾矩阵的相乘(点乘)230101

[[1 0 1][1 1 0]] [[3 0 0 3][2 2 1 3][1 3 1 1]] [[4. 3. 1. 4.][5. 2. 1. 6.]]乘以 c11 a11*b11 a12*b21 a13*b31 1*3 0*2 1*1 4 c12 a11*b12 a12*b22 a13*b32 1*0 0*2 1*3 3 c13a11*b13 a12*b23a13*b33 c14a11*b14 a12*b24a13*b34 c21a21*b11 a22*b21 a23*b…

《QT从基础到进阶·三十五》QT插件实现侧边工具栏tabBar

tabBar是用QT插件实现的一个dll&#xff0c;对于插件的使用可以参考文章&#xff1a; 《QT从基础到进阶三十三》QT插件开发QtPlugin 源码放在文章末尾 该功能类似侧边工具栏&#xff0c;可以在该标签栏上添加自己开发的界面&#xff0c;实现代码如下&#xff1a; 1、所有功能…

Tomcat无法映射到activiti-app导致activiti无法启动页面

原因之一&#xff1a;JDK版本与Tomcat版本不匹配&#xff0c;jdk8 yyds 我使用的是JDK11&#xff0c;Tomcat是9.0的&#xff0c;都是最新的&#xff0c;但还是不行&#xff0c;最后JDK改为8&#xff0c;tomcat的cmd后台没有报错&#xff0c;activiti-pp也可以正常访问了,很神奇…