Linux | 进程相关概念(进程、进程状态、进程优先级、环境变量、进程地址空间)
文章目录
- 进程概念
- 1、冯诺依曼体系结构
- 2、进程
- 2.1基本概念
- 2.2描述进程-PCB
- 2.3组织进程
- 2.4查看进程
- 2.5通过系统调用获取进程标识符
- 2.6通过系统调用创建进程-fork初识
- fork の 头文件与返回值
- fork函数的调用逻辑和底层逻辑
- 3、进程状态
- 3.1状态
- 3.2进程状态查看命令
- 3.2.1 ps命令
- 3.2.2 top命令
- 3.2.3 htop命令
- 3.2.4 pidof命令
- 3.2.5pgrep命令
- 3.2.6 /proc文件系统:
- 3.3僵尸进程(Z状态)
- 3.4孤儿进程
- 4、进程优先级
- 4.1基本概念
- 4.2查看系统进程
- 4.2.1 ps -l
- 4.2.2 PRI & NI
- 4.3用top命令更改已存在进程的nice:
- 5、环境变量
- 5.1常见环境变量
- 5.2查看环境变量
- 5.3测试PATH
- 配置环境变量
- 5.4代码中获取环境变量
- 6、进程地址空间
- 6.1程序地址空间
- 6.2进程地址空间
进程概念
1、冯诺依曼体系结构

简单来说,计算机中是由一个个硬件构成
- 输入单元:键盘、鼠标、写字板等
- 中央处理器(CPU):含有运算器和控制器等
- 输出单元:显示器,打印机等
对于冯诺依曼一些结构,有以下几点注意:
- 存储器指的是内存
- 不考虑缓存情况,这里的CPU能且只能对内存进行读写, 不能访问外设
- 外设(输入设备或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取
- 总结就是:所有设备只能直接和内存打交道
2、进程
2.1基本概念
程序的一个执行实例,正在执行的程序等。担当分配系统资源(CPU时间,内存)的实体。
2.2描述进程-PCB
进程信息被放在进程控制块(一个数据结构),叫做PCB,Linux操作系统下的PCB是task_struct
进程 = 内核数据结构(PCB) + 程序段 + 数据段
task_struct内容分类
- 标识符:描述本进程的唯一标识符,用来区别其他进程
- 状态:任务状态,推出代码,推出信号
- 优先级:相对于其他进程的优先级
- 程序技术器:程序中即将被执行的下一条指令的地址
- 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据:进程执行时处理器的寄存器中的数据
- io状态信息:包括显示器的io请求,分配给进程的io设备和被进程使用的文件列表
- 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记帐号等
2.3组织进程
可以在内核源代码里找到,所有运行系统里的进程都以task_struct链表的形式存在内核里
2.4查看进程
如:要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹。
大多数进程信息同样可以使用top和ps这些用户级工具来获取

2.5通过系统调用获取进程标识符
- 进程id(PID)
- 父进程id(PPID)
获取进程识别码(getpid函数与getppid函数)
-
函数原型:
pid_t getpid(void) pid_t getppid(void)其中返回值类型pid_t是一种有符号整型,也可以使用整形int类型变量来接收
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{printf("pid: %d\n", getpid());printf("ppid: %d\n", getppid());return 0;
}
2.6通过系统调用创建进程-fork初识
- 使用man手册运行man fork认识fork函数
- fork有两个返回值
- 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
fork の 头文件与返回值
-
头文件:
unistd.h -
函数原型:
pid_t fork(void); -
父进程中,fork返回新创建子进程的进程ID
-
子进程中,fork返回0
fork函数的调用逻辑和底层逻辑
在上文介绍PCB的时候有提到过,进程由内核数据结构和代码、数据两部分组成。因此每个进程都会有自己的PCB即task_struct结构体。当调用了fork函数后,系统创建子进程,即创建一个属于子进程的task_struct,将父进程的大部分属性拷贝过去(不在内的如pid、ppid),由于父子进程属于同一个程序,他们的代码是共用的,但是两个进程同时访问一个变量的时候会出现冲突问题,因此子进程会将它将要访问的数据做一份额外的拷贝,也就是子进程访问拷贝出来的数据,然后父子进程就有了属于各自的数据,对变量的操作也是独立的。
fork函数创建子进程过程
- 创建子进程PCB
- 填充PCB对应的内容属性
- 让子进程和赴京城指向同样的代码
- 父子进程都是有独立的task_struct,已经可以被CPU调度运行了
问:为什么fork函数调用完后会返回两个值,这和寻常的函数不是不一样么?
在fork函数中,创建子进程的步骤完成后,在return返回之前,父子进程已经可以被CPU调度运行了,也就是说,在return前fork函数执行了父子两个进程,return是作为父子进程的共有程序,他们都会各自返回一个值,因此整体看fork函数会返回两个值,分别属于调用fork函数中父子进程的返回值。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{int ret = fork();printf("hello proc : %d!, ret: %d\n", getpid(), ret);sleep(1);return 0;
}
-
由于父子进程的代码是一样的,因此如果需要使得父子进程执行不一样的代码,可以使用if加上返回值的条件限定来进行父子进程分流
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() {int ret = fork();if(ret < 0){perror("fork");return 1;}else if(ret == 0){ //childprintf("I am child : %d!, ret: %d\n", getpid(), ret);}else{ //fatherprintf("I am father : %d!, ret: %d\n", getpid(), ret);}return 0; }
3、进程状态
在程序运行的时候,如果遇到一个scanf等语句,进程会暂停知道输入相应的数据,才继续运行,由此可见进程需要有不同的状态(例如运行、阻塞、挂起等),不然进程无法按照预期正常执行。
3.1状态
-
R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里
-
S睡眠状态(sleeping): 可中断睡眠状态,意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠 (interruptible sleep))
-
**D磁盘休眠状态(Disk sleep):**不可中断睡眠状态,在这个状态的 进程通常会等待IO的结束。
-
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可 以通过发送 SIGCONT 信号让进程继续运行。
-
**X死亡状态(dead):**这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
-
z僵尸状态(zombie): 进程结束运行后大部分资源被回收,但进程描述符仍保留,直到父进程获取其退出状态。处于该状态的进程已死亡却占据一定系统资源,会在任务列表里显示为
Z,过多僵尸进程会造成系统资源浪费。
运行队列
进程需要执行的时候,会被加入到运行队列中,并由调度器对队列进行调度,在CPU中执行运行的进程,无论是在运行中的还是在运行队列中的进程都是在R运行状态。示意图如下:

3.2进程状态查看命令
3.2.1 ps命令
用于查看当前系统中的进程状态。
- 语法:
ps [选项] - 常用选项:
- -a:显示所有与终端相关的进程,包括其他用户的进程。
- -u:以用户格式显示进程信息,包括用户名、启动时间等。
- -x:显示所有进程,包括没有控制终端的进程。
- -ef:显示所有进程的详细信息,包括进程ID(PID)、父进程ID(PPID)等。
- -j: 会以作业格式显示进程信息,这种格式输出的内容比默认格式更丰富,会额外展示一些进程的上下文信息,常见的有:
- PPID:父进程 ID,用于表明该进程是由哪个进程创建的。
- PGID:进程组 ID,它将相关的进程组织在一起形成一个进程组。
- SID:会话 ID,代表进程所属的会话,有助于对进程进行更宏观的管理和分类。
例如,想要查看常用的指令可以使用:
ps ajx | head -1; ps axj | grep test1来查看test1可执行程序的进程相关信息,如下:

当执行
ps axj | grep test1时,你可能会看到输出结果中包含一个grep进程,这是因为grep命令本身也是一个进程,并且它在执行搜索时,ps axj的输出中也包含了grep test1这个命令行字符串,所以grep会把自身这个进程也匹配出来并显示在结果中。
3.2.2 top命令
动态地显示系统中各个进程的资源占用情况,如CPU使用率、内存使用率等。
- 语法:
top [选项] - 常用选项:
- -d:指定更新间隔时间,单位为秒。例如,
top -d 5表示每5秒更新一次显示内容。 - -b:以批处理模式运行,可用于将输出重定向到文件。
- -n:指定显示的次数。例如,
top -n 3表示只显示3次更新后的结果。
- -d:指定更新间隔时间,单位为秒。例如,
在top命令的交互界面中,还可以使用一些按键进行操作,如按M键可以按照内存使用量对进程进行排序,按P键可以按照CPU使用率进行排序等。
3.2.3 htop命令
是top命令的增强版,提供了更友好的交互式界面,支持鼠标操作,并且可以更直观地显示进程树等信息。
- 语法:
htop
直接在终端输入htop即可启动该命令,使用方法与top类似,但界面更加丰富和易于操作。
3.2.4 pidof命令
用于查找指定名称的进程的PID。
- 语法:
pidof [进程名称]
例如,要查找名为nginx的进程的PID,可以使用命令:pidof nginx。
3.2.5pgrep命令
根据进程名称或其他条件查找进程的PID。
- 语法:
pgrep [选项] [进程名称] - 常用选项:
- -l:显示进程名称和PID。
- -u:指定用户,只查找该用户的进程。
例如,要查找用户ubuntu下名为python的进程的PID,并显示进程名称和PID,可以使用命令:pgrep -lu ubuntu python。
- ps -l 列出与本次登录有关的进程信息;
- ps -aux 查询内存中进程信息;
- ps -aux | grep + 程序名字 查询该程序进程的详细信息;
- top 查看内存中进程的动态信息;
- kill -9 + pid 杀死进程。
举例如下图:


其中,在使用ps -l命令时,注意到几个信息,有下:
- UID : 代表执行者的身份
- PID : 代表这个进程的代号
- **PPID :**代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
- **PRI :**代表这个进程可被执行的优先级,其值越小越早被执行
- **NI :**代表这个进程的nice值
3.2.6 /proc文件系统:
-
Linux的
/proc文件系统包含了大量关于系统和进程的信息。-
每个进程都有一个以其PID命名的目录,如
/proc/1234,其中包含了该进程的详细信息。 -
可以查看
/proc/[PID]/status文件来获取进程的状态信息。
-
例如执行
ls /proc/45311 -dl:
/proc/45311是目标路径,其中/proc是系统中用于反映进程运行状态的虚拟文件系统,45311代表特定进程的 ID,此路径指向该进程对应的目录;-dl是选项组合,-d使ls仅列出目录本身而非其内部内容,-l让ls以长格式输出详细信息
3.3僵尸进程(Z状态)
- 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用) 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
- 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码
- 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
下面是一个僵尸进程例子:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(){pid_t ret = fork();if(ret == 0){ printf("child process exit\n");exit(0);} else{while(1){} } return 0;
可以复制一个当前会话便于观察进程信息,下图一为上面代码运行效果,下图二为运行中的进程信息,可以看到由于子进程代码中有exit(0)而提前退出,而父进程一直等待子进程的反馈未果,因而子进程处于z状态。想要结束程序可以使用Ctrl + c 退出或使用kill命令。


进程一般退出的时候,如果父进程没有主动回收子进程信息,子进程会一直让自己处于Z状态,进程的相关资源尤其是
task_struct结构体不能被释放
僵尸进程的危害
- 进程的退出状态必须被维持下去。父进程如果一直不读取,那子进程就一直处于Z状态
- 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话 说,Z状态一直不退出,PCB一直都要维护
- 那一个父进程创建了很多子进程,就是不回收,会造成内存资源的浪费。因为数据结构 对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间的,不会受会造成内存泄漏
3.4孤儿进程
- 父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
- 父进程先退出,子进程就称之为“孤儿进程”
- 孤儿进程被1号systemd进程”领养“,当然要有systemd进程回收。
下面是一个孤儿进程的例子。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(){pid_t ret = fork();if(ret == 0){ for(int i=0;i<60;i++){ printf("chile process %d \n",getpid());sleep(1);} } else{for(int i=0;i<8;i++){printf("father process %d\n",getpid());sleep(1);} exit(0);} return 0;
}
可以看到父进程提前退出,子进程继续执行,如果观察进程信息会发现子进程在父进程提前退出后它的PPID变成了1。使用ps ajx | grep systemd会发现PID是1,即1号进程就是操作系统本身。我们把这种子进程称为孤儿进程。
为什么孤儿进程的PPID会变成1?
因为子进程将来需要被释放,原来的父进程提前退出,因此子进程被系统进程”领养“,在结束后进程后释放掉子进程。
4、进程优先级
4.1基本概念
- cpu资源分配的先后顺序,就是进程的优先权
- 优先权高的进程有优先执行权,配置进程优先权对多任务环境的linux很有用,可以改善系统性能
- 还可以把进程运行到指定的CPU上,把不重要的进程安排到某个CPU,可以大大改善系统整体性能
4.2查看系统进程
4.2.1 ps -l

在使用ps -l命令时,注意到几个信息,有下:
- UID : 代表执行者的身份
- PID : 代表这个进程的代号
- **PPID :**代表这个进程是由哪个进程发展衍生而来的,即父进程的代号
- PRI :代表这个进程可被执行的优先级,其值越小越早被执行
- **NI :**代表这个进程的nice值,nice值:进程优先级的修正数据(可以用来改)
4.2.2 PRI & NI
- PRI,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高
- NI就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
- PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
- 这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
- 所以,调整进程优先级,在Linux下,就是调整进程nice值
- nice其取值范围是**-20至19**,一共40个级别。
- 需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进 程的优先级变化。
- 可以理解nice值是进程优先级的修正修正数据
4.3用top命令更改已存在进程的nice:
- top
- 进入top后按 “r“ -> 输入进程PID -> 输入nice值
5、环境变量
5.1常见环境变量
- PATH : 指定命令的搜索路径
- HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
- SHELL : 当前Shell,它的值通常是/bin/bash。
5.2查看环境变量
环境变量相关命令
echo $NAME显示某个环境变量的值,其中NAME是环境变量名称- export: 设置一个新的环境变量
- env: 显示所有环境变量
- unset: 清除环境变量
- set: 显示本地定义的shell变量和环境变量
5.3测试PATH
- 举一个简单的例子
#include<stdio.h>int main()
{int i;for(i=0;i<5;i++){printf("I am a process\n");} return 0;
}
我们将他编译为叫process的可执行程序,当需要执行这个程序的时候我们应该使用./process来执行,直接输入process会显示”command not found“。但是在执行命令的时候比如touch命令、ls命令等,我们只需要输入命令名字即可,如果我们想让process这个程序像命令一样执行,即输入process就能执行,那么可以将程序所在路径加入到环境变量PATH当中
配置环境变量
PATH=$PATH:/root/workspace/Linux将当前程序所在的路径加入到环境变量PATH当中PATH=/root/workspace/Linux将当前程序所在的路径覆盖至环境变量PATH当中,相当于把PATH当中全部覆盖掉,然后ls等指令就会失效了。
执行完后,我们就可以直接输入process来执行程序,不需要带上路径了,甚至用mv将process改名后也能正常运行。使用which process也能找到~/root/workspace/Linux。
5.4代码中获取环境变量
getnev函数
-
函数声明:
char *getenv(const char *name)其中name是需要获取的环境变量名 -
使用举例:
#include<stdio.h> #include<stdlib.h>int main() {printf("PATH:%s\n",getenv("PATH"));return 0; }
6、进程地址空间
6.1程序地址空间
地址空间一共有如下的几个区域,从下到上地址逐渐增加,其中栈区的空间是从上往下使用,即从高地址往低地址增长;堆区的空间是从下往上使用,即从低地址往高地址增长,需要注意的是,在不同位操作系统下或者不同编译器下,内存的分配规则都可能是不同的,这里以linux为例,也是最经典的一种。
我们平时敲代码使用程序地址空间的时候,当我们定义一个局部变量,它的空间就是在栈区上开辟的,有临时性;当我们使用malloc申请空间的时候,是在堆区开辟的空间;当我们定义一个全局变量的时候,它的空间就是在全局变量中开辟的,其中也分为未初始化全局变量和已初始化全局变量。在32位系统下的寻址空间是4GB

为了直观地体现出地址分配的规则,我们使用一些例子来做演示:
#include<stdio.h>
#include<stdlib.h>int val1 = 10;
int val2;int main() {//以下均为存储在各区地址空间中的实例printf("代码区: %p\n", main);const char* str = "helllo linux";printf("字符常量区: %p\n", str);printf("已初始化全局变量区: %p\n", &val1);printf("未初始化全局变量区: %p\n", &val2);char* a = (char*)malloc(sizeof(char));printf("堆区: %p\n", a);printf("栈区: %p\n", &str);return 0;
}
运行结果如下图所示:

通过运行结果会发现打印出来的地址从代码区到栈区依次递增。
6.2进程地址空间
当我们使用fork()函数生成一个子进程的时候,子进程会对将要访问的父进程的内容进行写时拷贝,但是会发现子进程和父进程对于同一个全局变量进行访问更改等操作的时候,这个变量的地址是不变的,也就是说同一个地址可能会有两个值,因为这里的地址并不是物理地址,而是虚拟地址(我们平时写程序用到的地址相关的内容一般都是虚拟地址)。如果是物理地址,这是绝对不可能的,可以配合下面案例理解:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int val = 0;
int main()
{pid_t id = fork();if(id < 0){perror("fork");return 0;}else if(id == 0){ //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取val=100;printf("child: %d : %p\n", val, &val);}else{ //parentsleep(3);printf("parent: %d : %p\n", val, &val);}sleep(1);return 0;
}
运行结果如图

会发现前文所说的现象,同一个变量,子进程对其将要访问的变量进行写时拷贝,但是父子进程中的val确是同一个地址,因此这里的地址是虚拟地址而非物理地址。他们地址上的逻辑应该对应下图(简化):


- 当父进程创建出来,系统创建了父进程的PCB和父进程的进程地址空间,PCB指向进程地址空间
- 这里创建的进程地址空间是虚拟地址,虚拟地址和物理内存是通过页表来映射的
- 当访问某个地址时,页表通过映射关系,查找到物理地址,并读取存在当中的数据
- 当父进程创建子进程的时候,系统也根据父进程为模板创建子进程对应的PCB和进程地址空间
- 由于子进程时以父进程为模板创建的,因此他们页表是一样的,因此子进程和父进程能够共享代码
- 对于同一个全局变量,当子进程需要对其进行写入等操作时,由于父子进程的虚拟地址对应同一块物理地址,为保证独立性,系统会在物理内存中额外开辟一块空间
- 至此,父子进程各自页表中对于此全局变量的虚拟地址是相同的,但是对应的物理地址是不同的。
相关文章:
Linux | 进程相关概念(进程、进程状态、进程优先级、环境变量、进程地址空间)
文章目录 进程概念1、冯诺依曼体系结构2、进程2.1基本概念2.2描述进程-PCB2.3组织进程2.4查看进程2.5通过系统调用获取进程标识符2.6通过系统调用创建进程-fork初识fork の 头文件与返回值fork函数的调用逻辑和底层逻辑 3、进程状态3.1状态3.2进程状态查看命令3.2.1 ps命令3.2.…...
$ npx electron-forge import 一直报权限问题 resource busy or locked,
jackLAPTOP-7DHDAAL0 MINGW64 /e/project/celetron-project/my-electron-app (master) $ npx electron-forge import > Checking your system > Checking git exists > Checking node version > Checking packageManager version √ Found node22.14.0 √ Found gi…...
sqli-labs靶场实录(四): Challenges
sqli-labs靶场实录: Challenges Less54确定字段数获取数据库名获取表名获取列名提取密钥值 Less55Less56Less57Less58爆库构造爆表构造爆列构造密钥提取构造 Less59Less60Less61Less62爆库构造 Less63Less64Less65免责声明: Less54 本关开始上难度了 可以看到此关仅…...
HTML,API,RestFul API基础
一文搞懂RESTful API - bigsai - 博客园 1. API 路径 开头必须 /,表示绝对路径,不支持 . 或 ..(相对路径)。API 结尾 / 通常不需要,但部分框架会自动处理 / → 无 /。 ✅ 推荐 GET /api/v1/products # 资源集合…...
Spring框架中都用到了哪些设计模式?
大家好,我是锋哥。今天分享关于【Spring框架中都用到了哪些设计模式?】面试题。希望对大家有帮助; Spring框架中都用到了哪些设计模式? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Spring框架中使用了大量的设计模…...
ubuntu服务器部署
关闭欢迎消息 服务器安装好 ubuntu 系统后,进行终端登录,会显示出很多的欢迎消息 通过在用户的根目录下执行 touch .hushlogin 命令,再次登录终端就不会出现欢迎消息 修改hostname显示 修改 /etc/hostname 文件内容为主机名,保…...
Centos7虚拟机安装及网络配置(二)
#二、centos7的网络配置-Nat模式 NAT模式也是VMware创建虚拟机的默认网络连接模式。使用NAT模式网络连接时,VMware会在主机上建立单独的专用网络,用以在主机和虚拟机之间相互通信。虚拟机向外部网络发送的请求数据"包裹",都会交由…...
关于视频去水印的一点尝试
一. 视频去水印的几种方法 1. 使用ffmpeg delogo滤镜 delogo 滤镜的原理是通过插值算法,用水印周围的像素填充水印的位置。 示例: ffmpeg -i input.mp4 -filter_complex "[0:v]delogox420:y920:w1070:h60" output.mp4 该命令表示通过滤镜…...
maven-antrun-plugin插件的用法
maven-antrun-plugin 是 Maven 中一个非常强大的插件,它允许你在 Maven 构建过程中运行 Apache Ant 任务。通过这个插件,你可以在 Maven 构建的各个阶段(如 compile、package 等)中执行自定义的 Ant 任务,比如复制文件…...
twisted实现MMORPG 游戏数据库操作封装设计与实现
在设计 MMORPG(大规模多人在线角色扮演游戏)时,数据库系统是游戏架构中至关重要的一部分。数据库不仅承担了游戏中各种数据(如玩家数据、物品数据、游戏世界状态等)的存储和管理任务,还必须高效地支持并发访…...
Java知识速记:Exception与Error的区别
Java知识速记:Exception与Error的区别 在Java编程中,异常处理是一个重要的概念。程序员需要了解如何有效识别和处理不同类型的错误,以提升程序的健壮性和可维护性。 什么是异常(Exception)? 异常是程序在运…...
CTF-web:java-h2 堆叠注入rce -- N1ctf Junior EasyDB
代码存在sql注入 // 处理登录表单的POST请求PostMapping({"/login"})public String handleLogin(RequestParam String username, RequestParam String password, HttpSession session, Model model) throws SQLException {// 验证用户凭据if (this.userService.valid…...
GDB 使用心得
一、 入门篇 理解 GDB 的作用: GDB 是 GNU 调试器的缩写,用于调试 C、C 等编程语言的程序。它可以帮助你: 跟踪程序执行流程设置断点,暂停程序执行查看和修改变量值分析程序崩溃原因 掌握基本命令: 启动 GDB: gdb <可执行文件>运行程序…...
电脑端调用摄像头拍照:从基础到实现
文章目录 1. 了解navigator.mediaDevices.getUserMedia API2. 创建 HTML 结构3. 编写 JavaScript 代码3.1 打开摄像头3.2 拍照 4. 完整代码5. 测试6. 注意事项及部署 在现代 Web 开发中,调用摄像头进行拍照是一个常见的功能,尤其是在需要用户上传头像、进…...
部署 DeepSeek R1各个版本所需硬件配置清单
DeepSeek-R1 通过其卓越的推理性能和灵活的训练机制,在 2025 年的春节期间受到了广泛关注。 DeepSeek-R1 是一款高性能的 AI 推理模型,主要通过强化学习技术来增强模型在复杂任务场景下的推理能力。 在本地部署 DeepSeek-R1 时,尤其是完整的…...
Java面试题——事务
65. Spring事务的实现方式和实现原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring是无法提供事务功能的。Spring事务实现主要有两种方法:编程式:beginTransaction()、commit()、rollback()等事务管理相关的方法࿰…...
算法18(力扣136)只出现一次的数字
1、问题 给你一个 非空 整数数组 nums,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 2、示例 (1&…...
SiliconCloud 支持deepseek,送2000w token
SiliconCloud SiliconCloud 邀请奖励持续进行,2000 万 Tokens 送不停! 邀请好友赚 2000 万 Tokens:每成功邀请一位新用户通过手机号码注册,您将获得 2000 万 Tokens;注册即送 2000 万 Tokens:受邀好友作为…...
在nodejs中使用RabbitMQ(六)sharding消息分片
RabbitMQ 的分片插件(rabbitmq_sharding)允许将消息分布到多个队列中,这在消息量很大或处理速度要求高的情况下非常有用。分片功能通过将消息拆分到多个队列中来平衡负载,从而提升消息处理的吞吐量和可靠性。它能够在多个队列之间…...
STM32 I2C通信协议说明
目录 背景 I2C协议 数据的有效性 I2C通信开始和停止条件 I2C数据传输 发送 响应 正常情况: 异常情况: 主机结束接收 写寄存器的标准流程 读寄存器的标准流程 仲裁机制 时钟同步 SDA线的仲裁 程序 背景 对单片机的三大通信中的I2C通信进…...
git bash在github的库中上传或更新本地文件
一、将本地文件上传到 GitHub 仓库 1. 创建 GitHub 仓库 如果你还没有在 GitHub 上创建仓库,首先需要创建一个新的仓库: 登录到 GitHub。点击右上角的 按钮,选择 New repository。给你的仓库起个名字,并选择 Public 或 Privat…...
Keysight E5071C (Agilent) 网络分析仪的特性和规格
安捷伦E5071C网络分析仪 Keysight E5071C网络分析仪 Keysight E5071C (Agilent) 网络分析仪的其他特性和规格包括: 宽动态范围:测试端口动态范围 > 123 dB(典型值) 快速测量速度:41 ms 全 2 端口校准,…...
总结:如何在SpringBoot中使用https协议以及自签证书?
总结:如何在SpringBoot中使用https协议以及自签证书? 前提一:什么是http协议?前提二:什么是https协议?一生成自签证书二 将证书转换为PKCS12格式三 配置SpringBoot(1)修改配置文件&a…...
Golang学习历程【第七篇 闭包type defer panic recover了解time包】
Golang学习历程【第七篇 闭包&type defer panic recover了解】 1. 闭包1.1 闭包的定义1.2 闭包的特点1.3 闭包的示例 2. 类型(type)2.1 自定义类型2.2 类型示例 3. 延迟执行(Defer)3.1 defer 的用法3.2 defer 示例 4. 恐慌(Panic…...
基于SSM+uniapp的数学辅导小程序+LW示例参考
1.项目介绍 系统角色:管理员、普通用户功能模块:用户管理、学习中心、知识分类管理、学习周报管理、口算练习管理、试题管理、考试管理、错题本等技术选型:SSM,Vue(后端管理web),uniapp等测试环…...
利用AI智能体创建云端文档知识库并集成第三方数据源(上)
许多开发者在管理和集成多种云端的数据源时经常面对各种各样的困难,所以希望能够构建一个聊天机器人来协调这些数据源,针对业务问题并提供全面的答案。本文介绍了一种解决方案,帮助大家开发一个能够从文档和数据库中回答查询的聊天机器人&…...
聚铭网络入围2025年度江苏省政府采购信息安全设备协议供货名单
近日,2025年度江苏省党政机关、事业单位及团体组织信息安全设备框架协议采购项目入围结果公布。聚铭网络凭借自身专业实力和技术优势脱颖而出,成功入围22个分包。 此次采购项目是江苏省政府采购领域级别最高、覆盖面最广的项目之一。从资格评选到后期材料…...
vue+springboot+webtrc+websocket实现双人音视频通话会议
前言 最近一些时间我有研究,如何实现一个视频会议功能,但是找了好多资料都不太理想,最终参考了一个文章 WebRTC实现双端音视频聊天(Vue3 SpringBoot) 只不过,它的实现效果里面只会播放本地的mp4视频文件&…...
2025年单片机毕业设计选题物联网计算机电气电子通信类
当然,以下是基于物联网技术设计的20个单片机类题目,旨在考察学生在物联网环境下单片机应用、系统设计、数据传输与处理等方面的能力: 基于物联网的智能家居温度湿度控制系统设计:利用单片机和传感器实现室内环境的温湿度监测&…...
堡垒机调用xshell 无反应
安装sso_client 确认db_path.ini xhsell路径 如图调整为本机安装的路径即可。 实战问题: 操作完成之后 Chrome还是无法调用,使用360浏览器没问题。...
