LINUX基础 [二] - 进程概念
目录
前言
什么是进程
如何管理进程
描述进程
组织进程
如何查看进程
通过 ps 命令查看进程
通过 ls / proc 命令查看进程
通过系统调用 获取进程标示符
前言
在学习了【Linux系统编程】中的 操作系统 和 冯·诺依曼体系结构 之后,我们已经对系统应该有了不错的了解,接下里我们将继续深入的了解操作系统最重要的的功能之一:进程
什么是进程
首先我们来看一个问题:
操作系统能不能一次运行多个程序呢?
答案是当然可以的!!因为运行的程序有很多,所以 OS 需要将这些运行的程序管理起来。
我们将这些正在运行的程序称之为进程。(注意:是正在运行的程序叫进程,而不是程序本身)
【课本概念】:程序的一个执行实例,正在执行的程序等
【内核观点】:担当分配系统资源(CPU时间,内存)的实体
对于课本中的观点大家可能会觉得难以理解,为何正在执行的程序就是一个进程呢。我们可以在Windows下按[Ctrl + shift + ESC]打开任务管理器查看一下:

这也就表明了在一个操作系统中不仅只能运行一个进程,还可以运行多个进程
但是呢,进程不仅仅可以像上面这样去理解。我们来思考一个问题
程序是文件吗?
相信读者肯定很清楚,文件是存放在磁盘中的,磁盘呢则是属于外设。这一块我们在 冯·诺依曼体系结构 有讲得很清楚,对于CPU来说,它是只会和内存打交到的,所以磁盘中的数据需要先加载到内存中才可以被执行
那么,当可执行文件被加载到内存中时,该程序就成为了一个【进程】

总结:进程 = 程序(代码 + 数据) + 内核申请的与该进程对应的数据结构(PCB)。
如何管理进程
你说正在运行的程序叫做进程,那进程可以同时进行吗?
- 我们可以发现当你在听网易云的时候你也可以登录微信聊天,也可以刷抖音 所以进程是可以同时进行的。是因为操作系统把这些进程给管理起来了。也就是先描述再组织
- 操作系统会创建一个描述和控制该进程的结构体。这个结构体称之为进程控制块(PCB,Processing Control Block),里面包含了该进程几乎所有的属性信息,同时通过进程控制块也可以找到该进程的代码和数据。
- 在 Linux 中,进程控制块就是 struct task_struct 结构体。
- 描述好所有进程了,还需要将所有进程的 PCB 给组织起来(通过双链表的方式),此时操作系统只需要拿到双链表的头指针,就可以找到所有进程的 PCB。
- OS 把对进程的管理就转换成了,对数据结构中 PCB 的管理,即对双链表的增删查改操作。
假设这里有一个可执行程序 test,它存储在磁盘上,就是一个普通文件,当我们 ./test 运行此程序,操作系统会做以下事情:将该程序从磁盘加载到内存中,并为该程序创建对应的进程,申请进程控制块(PCB)。

描述进程
先思考:人是如何辨别事物或者对象的??
比如你在放学路上见到一个女生一见钟情,于是你记住了他的样貌,开始像别人打听这个女生,因为你不认识这个女生,所以你会对他进行描述,比如说长得很漂亮、水灵的眼睛、瓜子脸……当你提供的特征越来越多的时候,认识她的人或许就能通过你的描述找到这个女生。而这个过程中,这个女生的各种特征其实就是他的属性,所以我们可以得出一个结论:人是通过属性去辨别事物和对象的,当属性足够多的时候,这一堆属性的集合,就是目标对象!!
所以我们推断出,任何一个进程加载到内存时,OS需要创建一个描述进程的结构体对象——PCB(process ctrl block进程控制块) ,而他的本质就是对进程属性集合的描述!!
- 课本中的叫法是:PCB(Process Control Block)
- Linux操作系统下的PCB是:task_struct
这个结构体呢就是组织了各种各样的属性,才可以去很好地描述一个进程
task_struct的内容:
标示符: 描述本进程的唯一标示符,用来区别其他进程。(有点类似学校里每个学生的学号,是一个唯一标识,方便我们通过标示符来管理进程)
状态: 任务状态,退出代码,退出信号等。(OS中同时存在多个进程,所以可能有的进程正在运行、有的正在休眠、有的在正在待定、有的即将销毁……也就是说每个进程当前可能都处于某一种状态)
优先级: 相对于其他进程的优先级。(OS中有多个进程,所以先执行谁肯定是要有一个标准的,所以进程之间可能存在对应的优先级关系)
程序计数器: 程序中即将被执行的下一条指令的地址。(以前我们在学习函数栈帧的时候,我们知道代码是从上往下运行的,但是这个过程中可能会遇到出现某个函数需要我们进行跳转,这个时候当前的栈帧会暂时保存着,然后当跳转过去的相关代码执行结束后再返回之前栈帧的位置继续运行。但是由于OS中不仅仅只有一个进程,所有有可能这个进程在执行的时候可能会被一些切换给中断,转而去执行别的进程,然后该进程可能会进入休眠模式,而后期我们可能还会去唤醒这个进程,这个时候由于之间的栈帧被销毁了,所以已经不记得执行到哪句代码了,因此程序计数器存在的意义就是帮助没我们记住即将被执行的下一条指令的地址!举个更好理解的例子就是,比方说你正在数一堆书,当你数到50的时候,这个时候突然一个电话告诉你外卖到了,为了不让外卖员等太久,你需要暂停当前的工作马上下去,但是你又怕你数过的数字忘记了,所以你就把他记在本子上,当你取完外卖后,你就可以通过从本子上的数字继续往下数!)
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针(我们一个可执行程序要运行还需要有对应的数据和代码,所以PCB对象必然需要有一个指针指向这块空间,当进程响应的时候能够及时找到,另一方面可能会存在多种数据类型的指针,为了满足不同场景下的需求——通过数据结构和算法)
上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。(可能会包含进程的一些运行时间,其实对进程的调度来说是有作用的,因为在多个进程的情况下,只有一个CPU,所以先将哪个进程放到CPU里其实是由调度器决定的,而调度器除了考虑进程状态和一些优先级之外,他会尽可能秉持着公平的原则,比如说有尽可能地优先让执行时间短的进程优先去调度。)
其他信息
转换为代码形式的话就可以是下面这样
struct PCB{进程的编号进程的状态进程的优先级...相关的指针信息
};
既然知道了如何去描述一个PCB结构体,我们就要来知道操作系统对一个进程总共会做哪些事情
- 为该进程创建对应的PCB对象
- 将该进程的代码和数据加载到内存中

所以,很多教科书在介绍进程的时候只会说它在计算机内部是一个PCB对象,其实对于一个进程来说:应该是由操作系统为其创建出来的 PCB对象 + 其数据代码 组成的
组织进程
我们知道 进程=内核PCB数据结构对象+你自己的代码和数据。
- 但是OS本质上是对PCB做管理,他并不关心你的代码和数据,因为他只要能找到PCB,就可以通过他里面的一个相关的指针去找到对应的代码和数据,然后再交给CPU去运行!!
- 举个例子就比如HR对人才的管理本质上就是对简历进行管理,然后安排面试的时候再通过简历来找到你的相关信息。
但是PCB特别多,所以我们需要想办法管理起来。
其实在我们的Linux中task_struct主要是以双链表的形式组织起来。
你可能会疑惑,使用一个顺序表来存储不是更好吗??其实在OS内部对于进程的管理方式并没有像我们以前学的数据结构那么纯粹,他的场景会更加复杂,也就是说该进程可能会需要根据不同的需求被存储在队列中、双链表中、二叉树中、栈中……
所以将进程按照节点的方式链接起来其实会更方便我们将这个进程放在不同的数据结构中,然后我们可以通过对应的指针信息来讲他们更好地管理起来。
举个例子,比如说我在当前进程中有一个队列指针。因为在OS中可能会有一些存储进程指针的运行队列和等待队列,如果你想让这个进程去哪个队列,你就可以通过修改队列指针的链接队形做到,从而实现更加灵活的管理。
所以对进程管理工作取决于你把他放入哪个正在被组织的数据结构中,因为不同的数据结构有不同的特点,所以背后对应的就是不同的算法,而不同的算法对应的就是不同的应用场景。
如何查看进程
现在我们明白了操作系统如何去描述并组织进程,接下去我们就切身地来看一看进程长什么样吧
下面呢是我们要进行测试的代码:
#include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <sys/types.h>5 int main()6 {7 // 死循环8 while(1)9 {10 pid_t id = getpid();11 //pid_t fid = getppid();12 //printf("I am a process! pid : %d, ppid : %d\n",id,fid);13 printf("I am a process! pid : %d\n",id);//程序停留一秒在输出 14 sleep(1);15 }16 17 return 0;18 }
通过 ps 命令查看进程
查看当前我们正在运行的进程
此时我们来查看以下当前运行程序的进程
ps ajx | head -1 && ps ajx | grep mytest
ps ajx—— 查看当前系统中所有进程head -1—— 获取第一行grep mytest—— 过滤只带【mytest】的进程
那有同学可能会问:为什么在过滤进程的时候会有 grep --color=auto mytest 这个东西呢?
当grep在进行过滤的时候自己也要变成一个进程,也可以看到他们使用grep命令的时候也带【mytest】关键字的,所以在过滤的时候把自己也过滤出来了。
这也侧面证明了所有指令在运行的时候都是进程

但如果我们不想看到这个也是有办法的,那就是在 grep 命令后面加个-v grep把其过滤掉即可
ps ajx | head -1 && ps ajx | grep mytest | grep -v grep

通过 ls / proc 命令查看进程
我们都清楚根目录下有很多的路径:

注意上面的proc目录,它是一个内存文件系统,里面放的是当前系统实时的进程信息。我们进入此目录看看:

但是呢,上面这些呢是全部的进程,若我们只是想要查看某个进程的话就要根据其PID值去进行对应的查找。这个PID呢就是我们在上面在介绍task_struct这个Linux下的PCB结构体的时候所讲到的【标识符】这个东西,它是 描述本进程的唯一标示符,用来区别其他进程

但是这么看不够清晰,我们以列表的形式来进行查看。这里我们主要关注两个:一个是cwd目录,另一个则是exe

首先我们来看到的是这个【exe】,很明显它是一个可执行文件,那就是我们在当前目录下的mytest这个可执行文件
接下去的话就是这个【cwd】了,其意思为current work directory当前进程的工作目录
接下来,我们来详细说一这个 cwd
看以下的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(){printf("我的PID:%d\n",getpid()); FILE* fp = fopen("log.txt","w"); if(fp==NULL){return 1;}fclose(fp);printf("新建文件完成\n");sleep(50);return 0;}
在当前的 proc.c 程序中,创建一个log.txt 的文件,创建好后,大家觉得这个文件会出现在哪里呢? 我们运行以下看看

我们发现在 proc.c 程序中创建的 log.txt 文件出现在当前目录下,这是为什么呢?
我们来根据程序中的进程标识符来检查一个这个进程

此时我们发现进程中的存有cwd---当前工作目录,所以导致在此程序中创建的任何文件,在没有指定放在哪里的时候,常见的文件会默认放在进程指定的cwd----当前工作目录下
通过系统调用 获取进程标示符
上面我们有讲到了这个PID进程标示符,是通过ps这个命令来查看的,那我们能否直接获取这个PID呢?
- 在上面我们使用
ps ajx查看到了当前进程所对应的 PID,但是呢这相当于是遍历操作,如果我没有加grep mytest的话出来的进程数就会很多了
- 那现在我们所要做到的就是对一个单独的进程去获取其 PID,此时我们能想到的就是通过库函数来实现。在之前的文章中我们又说到过对于操作系统而言它是不会相信任何人的,所以会提供给用户一些系统调用(库函数),那我们只需要通过这个系统调用即可获取到当前进程的 PID 值

- 那首先呢,我们先要去查询一下这个
getpid()怎么使用,那还是使用到我们的老朋友man
man 2 getpid
进去之后看到,有两个库函数,那如果要使用这两个库函数的话就需要引入对应的头文件

下面我给出一段命令,它可以实时监控当前系统的进程
while :;do ps ajx | head -1 && ps ajx | grep mytest | grep -v grep; echo "------------------------------------------------------------"; sleep 1; done;
- 然后就让我们来观察一下其是否真的可以获取到当前进程的PID,首先运行上面的这段指令,我们看到了当前系统中并不存在有关mytest的进程,但是呢在我们把mytest这个可执行程序运行起来的时候,右侧就突然就多出了一条进程的相关信息
- 后一核对相关的PID值就发现确实是当前运行起来的这个进程

- 但是呢当我在将当前这个进程给结束之后再去把它起起来的时候,就发现当前这个进程的
PID值发生了变化

其实的话,这个现象是很正常的,每次重新启动进程其 PID 值是会出现不同的情况
举个很简单的例子来说吧,小王在高考结束完后上了一所不是很理想的大学🏫,在开学前两天时学习为其分配了对应的学号。但是呢小王却并不满意自己所待的这个学校,所以就退了学继续参加高考,在又一次的高考结束后他还是被原来的这所学校给录取。但是呢我们可以知道,即使你进了一个学校两次,但是学号却不一定是一样的
这也就是为什么一个进程在启动两次后会出现不同PID值的原因
刚才我们在通过【man】手册查看getpid()这个函数的时候,还看到了getppid()这个函数,它是获取当前进程的父进程的 PID
- 这个
PPID呢就在PID的左边

下面是改进的测试代码
printf("I am a process, my id is: %d, parent is: %d\n", getpid(), getppid());
- 马上来看一下是否真的可以获取到

- 接下去我们再来观察一下现象:通过3次结束子进程,我们观察到了子进程确实每次都会发生变化,但是呢对于父进程而言却不会发生任何的变化,这是为什么呢?

- 我们可以先去查看一下这个父进程到底是什么鬼…(((m -__-)m
ps ajx | head -1 && ps ajx | grep 18866

原因解析:
每次在登录XShell的时候,系统会为我们单独再创建一个Bash进程,即命令行解释的进程,帮我们在显示器中打印出对话框终端
[XAS@iZf8z3lh8un7rc5rk1ney3Z lesson13]$ ----- 【父进程----ppid】
我们在命令行中输入的所有指令都是Bash进程的子进程,Bash进程只负责命令行的解释,具体执行出问题的时候只会影响它的子进程
ls /proc/18866 -- 子进程【PID】
上面这样解释可能还是比较抽象,一样来举个例子
- 还记得,我们在讲解shell运行原理的时候曾经说到过王婆是一位资本家,她为了不损坏自己的名声呢,在别人找她说媒的时候会派遣一些实习生去,即使实习生出了问题她的名誉也不会受到影响
这就可以对照到父进程与多个子进程,可以有多个子进程在这个父进程上面运行,即使某一个子进程突然出问题终止了,还有其他子进程在运行,此时父进程也是有保障的,所以子进程每次都会发生变化,但是父进程永远都不会变化
相关文章:
LINUX基础 [二] - 进程概念
目录 前言 什么是进程 如何管理进程 描述进程 组织进程 如何查看进程 通过 ps 命令查看进程 通过 ls / proc 命令查看进程 通过系统调用 获取进程标示符 前言 在学习了【Linux系统编程】中的 操作系统 和 冯诺依曼体系结构 之后,我们已经对系统应该有…...
浏览器自动携带cookie注意事项
文章目录 浏览器自动携带与目标域相关的 cookie 是由 HTTP 协议规范和浏览器设计共同决定的一、Cookie 携带的基本规则同源策略下的自动携带跨域请求的受限携带一、服务器端配置二、客户端配置三、 常见错误及注意事项 二、Cookie 属性的筛选逻辑 三、浏览器携带cookie的准则1.…...
同旺科技USB to I2C 适配器 ---- 指令循环发送功能
所需设备: 内附链接 1、同旺科技USB to I2C 适配器 1、周期性的指令一次输入,即可以使用 “单次发送” 功能,也可以使用 “循环发送” 功能,大大减轻发送指令的编辑效率; 2、 “单次发送” 功能,“发送数据…...
算法及数据结构系列 - 滑动窗口
系列文章目录 算法及数据结构系列 - 二分查找 算法及数据结构系列 - BFS算法 算法及数据结构系列 - 动态规划 算法及数据结构系列 - 双指针 算法及数据结构系列 - 回溯算法 算法及数据结构系列 - 树 文章目录 滑动窗口框架思路经典题型76. 最小覆盖子串567. 字符串的排列438. …...
AI密码学
嗯,用户给了一个需要破译的密码文档:“Uif qjh jt po uif usff.”,提示是用字母往前推移1的凯撒密码。首先,我得确认自己是否正确理解提示。凯撒密码通常是将字母按照一定位移来替换,这里的提示是往前推1位,…...
关于VSCode使用过程中的一些问题记录(持续更新)
1. VSCode更新拒绝访问 VSCode安装更新的时候出现: D:\Program Files\Microsoft VS Code\tools\inno_updater.exe 尝试在目标目录创建文件时发生一个错误:拒绝访问。 解决方法: 1. 禁止VSCode的自动检查更新,操作方法ÿ…...
重新复活的(手机端)一站式应用管理与下载平台
应用乐园(安卓) 应用乐园作者去年3月表示,由于精力问题,要停止维护奇妙搜索、应用乐园、奇妙影视这些软件了。 然而最近,令人意外的是,应用乐园竟然“复活”了!更准确地说,它进行了…...
Vue3前端开发:组件化设计与状态管理
Vue3前端开发:组件化设计与状态管理 一、Vue3组件化设计 组件基本概念与特点 是一款流行的JavaScript框架,它支持组件化设计,这意味着我们可以将页面分解成多个独立的组件,每个组件负责一部分功能,通过组件的嵌套和复用…...
失物招领|校园失物招领系统|基于Springboot的校园失物招领系统设计与实现(源码+数据库+文档)
校园失物招领系统目录 目录 基于Springboot的校园失物招领系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、 管理员功能实现 (1) 失物招领管理 (2) 寻物启事管理 (3) 公告管理 (4) 公告类型管理 2、用户功能实现 (1) 失物招领 (2) 寻物启事 (3) 公告 …...
嵌入式硬件工程师从小白到入门-原理图(三)
原理图绘制从小白到入门:知识点速通与注意事项 一、原理图绘制基础概念 什么是原理图? 原理图(Schematic)是电子电路的图形化表示,展示元器件之间的电气连接关系,是硬件设计的蓝图。 核心元素 元器件符号&…...
Pear Admin Flask 开发问题
下载代码请复制以下命令到终端执行 git clone https://gitee.com/pear-admin/pear-admin-flask 于是我下载git 完成安装后: 安装 Git 后出现的页面是 “Git for Windows 的版本发布说明(Release Notes)”,通常会在安装完成后自动弹…...
Collectors.toMap / list 转 map
前言 略 Collectors.toMap List<User> userList ...; Map<Long, User> userMap userList.stream().collect(Collectors.toMap(User::getUserId, Function.identity()));假如id存在重复值,则会报错Duplicate key xxx, 解决方案 两个重复id中&#…...
1996-2023年各省公路里程数据(无缺失)
1996-2023年各省公路里程数据(无缺失) 1、时间:1996-2023年 2、来源:国家统计局、统计年鉴 3、指标:公路里程(万公里) 4、范围:31省 5、指标解释:公路里程指报告期末…...
量化研究---可转债量化交易系统上线快速服务器
现在可转债交易系统使用的人多,服务器比较小,今天对服务器进行了升级,提供快速的数据支持,同时我也给了服务器的源代码,支持自定义服务器数据支持,不通过我服务器,可以挂在服务器上面24小时快速…...
用ArcGIS做一张符合环评要求的植被类型图
植被类型图是环境影响评价(环评)中的重要图件,需满足数据准确性、制图规范性和信息完整性等要求。本教程将基于ArcMap平台,从数据准备到成果输出,详细讲解如何制作符合环评技术规范的植被类型图。 ArcGIS遥感解译土地…...
Java 双端队列实战 实现滑动窗口 用LinkedList的基类双端队列Deque实现 洛谷[P1886]
集合 关系 介绍 Deque 是一个接口 LinkedList 是这个接口的实现类 题目 输入输出 滑动窗口 基于双端队列实现 Deque<Integer> deque new LinkedList<>(); 滑动窗口代码 洛谷 public static List<Integer> maxSlidingWindow(int[] nums, int k) {List&l…...
【商城实战(54)】解锁商城国际化密码:内容管理全攻略
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配…...
AI代码编辑器:Cursor和Trae
Cursor 定义:Cursor 是一款基于AI的代码编辑器,它继承了VS Code的核心功能,并在此基础上增加了深度AI支持。它支持代码生成、优化、重构以及调试等功能,提供直观的Diff视图和自动补全功能,是一款功能强大的编程工具。…...
[学习笔记] VM虚拟机安装Ubuntu系统
前言 我现在装的Ubuntu总是死机,经常黑屏,所以我决定换个版本,顺便写一下笔记,给大家分享如何安装虚拟机 下载 这里我选择的是Ubuntu 22.04.5 LTS,下载链接:Ubuntu 22.04.5 LTS 如果访问不了网站的话&…...
统计学重要概念:自由度
在统计学中,自由度(degrees of freedom,简称df)是一个重要的概念,它表示在计算某个统计量时可以自由变化的值的数量。对于一个样本量为n的样本,自由度通常为n-1,这是因为我们需要用样本数据来估…...
3.22模拟面试
前端模拟面试(1 年经验) 面试时长:40-60 分钟 面试难度:初中级 技术栈:Vue 3、TypeScript、微前端(qiankun)、Webpack/Rspack、Ant Design、组件库迁移 一、基础知识 HTML & CSS 介绍一下…...
汇编语言习题笔记——第1章 汇编语言基础
第1章 汇编语言基础 1. IA-32处理器有哪三类基本段,各是什么用途? 段类型寄存器主要用途特点代码段 (CS)CS存储可执行指令执行权限,通常只读,与 IP/EIP/RIP 配合,确定指令地址数据段 (DS, ES, FS, GS)DS, ES, FS, GS存储程序数据 (变量, 数据结构等)读写权限,多个寄存器…...
为扣子智能体接入 DeepSeek
扣子现已推出满血版 DeepSeek 全家桶,支持免费体验 R1、V3 模型。除此之外,扣子支持 DeepSeek 思维链(Chain-of-Thought,CoT)和 Function Calling 能力,为你的智能体添加私有知识和多种技能,拓展…...
3.22日西南竞篮,NBA勇士VS老鹰,赛前数据前瞻
3.22日NBA勇士VS老鹰赛前数据前瞻 关键要点 明天(3月22日)的NBA比赛是金州勇士对阵亚特兰大老鹰,盘口为勇士让2.5分,大小分预设为230.5。 勇士目前战绩41胜29负,西部第六;老鹰战绩33胜36负,东部…...
C语言:循环控制结构习题
1水仙花数是指各个位数的立方和等于本身的三位数。例如:153是水仙花数,因为1531的立方5的立方3的立方。 编程计算并输出所有的水仙花数。 第一种做法 思路: 1三位数:百位,十位和个位,除了百位是1-9&#…...
Dear ImGui for Unity 常见问题解决方案
Dear ImGui for Unity 常见问题解决方案 dear-imgui-unity Unity package for Dear ImGui 项目地址: https://gitcode.com/gh_mirrors/de/dear-imgui-unity 1. 项目基础介绍 Dear ImGui for Unity 是一个开源项目,旨在将Dear ImGui库整合到Unity游戏引擎中。…...
【Unity3D】摄像机适配场景以及Canvas适配
目录 宽度不变策略 高度不变策略 宽度不变策略 开发分辨率 750*1334 (宽高比:0.56) 真机分辨率 1170*2532 (宽高比:0.46) 真机宽高比<开发宽高比,采用宽度不变策略 理由:小于代表真机高度比开发高度更大,因此不需要担心高度上…...
盛铂科技国产SLMF315超低相位噪声频率综合器介绍
SLMF315频率综合器简介: 盛铂科技SLMF315超低相位噪声频率综合器的频率范围覆盖200MHz至15GHz。频率的最小步进仅为0.1Hz,在不考虑频率精度的情况下频率步进可达0.04Hz。SLMF315内部采用多环路设计从而获得极优秀的相位噪声特性,频率输出为1…...
一个简单的人脸识别demo
使用face_recognition和OpenCV库完成人脸检测和识别任务: # 导入必要的库 import cv2 # OpenCV库,用于图像处理 import face_recognition # 人脸识别库 import numpy as np # 数值计算库# 步骤1:加载已知人脸的图片并编码 # 加载乔布斯的…...
SpringDoc和Swagger使用
目录 一、SpringDoc 1.添加依赖 2.配置代码 配置解释 (1)springdoc.api-docs.path (2)springdoc.swagger-ui.path (3)springdoc.swagger-ui.operationsSorter (4)springdoc.…...
