Linux 入门:操作系统进程详解(上)
目录
一.冯诺依曼体系结构
一). 软件运行前为什么要先加载?程序运行之前在哪里?
二).理解数据流动
二.操作系统OS(Operator System)
一).概念
二).设计OS的目的
三).如何理解操作系统OS的“管理”
四).系统调用和库函数概念
三.进程
一).进程基本概念与基本操作
1.描述进程-PCB
2.task_ struct
3.查看进程
1). 进程的信息可以通过 /proc 系统文件夹查看
2). 大多数进程信息同样可以使用top和ps这些用户级工具来获取
4.通过系统调用获取进程标示符
5.通过系统调用创建进程-fork初识
1).认识fork
2).父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
3).fork有两个返回值
4).fork 之后通常要用 if 进行分流
二).进程状态
1.Linux内核源代码怎么说
2.运行 && 阻塞 && 挂起
3.进程状态查看
4.Z(zombie)-僵尸进程
5.孤儿进程
三).进程优先级
1.基本概念
2.查看系统进程
3.查看修改进程优先级
4.补充概念---竞争、独立、并行、并发
四).进程切换
1.死循环进程如何运行
2. CPU和寄存器
3.如何切换
五).Linux真实的调度算法
1.优先级
2.活动队列
3.过期队列
4.active指针和expired指针
一.冯诺依曼体系结构
这里我们讨论学习的是红色的数据信号。
我们所认识的计算机,都是由一个个的硬件组件组成
- 输入单元:包括键盘, 鼠标,扫描仪, 写板,磁盘等
- 中央处理器(CPU):含有运算器和控制器等
- 输出单元:显示器,打印机,磁盘等
- 存储器:内存
关于冯诺依曼,必须强调几点:
1.这里的存储器指的是内存。
2.不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)。
3.外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
4.一句话,所有设备都只能直接和内存打交道。
那为什么有这些设定呢?速度差距大。
我们设计出不同存储速度的内存进行存储。当代计算机是性价比的产物。
我们从两个问题开始详细认识这个体系。
一). 软件运行前为什么要先加载?程序运行之前在哪里?
二).理解数据流动
请解释,从你登录上qq开始和某位朋友聊天开始,数据的流动过程。从你打开窗口,开始给他发消息,到他的到消息之后的数据流动过程。如果是在qq上发送文件呢?
二.操作系统OS(Operator System)
一).概念
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS),操作系统是一款进行软硬件管理的软件。笼统的理解,操作系统包括:
• 内核(进程管理,内存管理,文件管理,驱动管理)
• 其他程序(例如函数库,shell程序等等)
二).设计OS的目的
对下,与硬件交互,管理所有的软硬件资源(目的)
对上,为用户程序(应用程序)提供一个良好的执行环境(手段)
对于操作系统我们要认识以下几点:
1.软硬件体系结构------>层状结构
2.访问操作系统,必须使用系统调用------其实就是函数,不过是系统提供的
3.我们的程序,只要你判断出它访问了硬件,那么它必须贯穿整个软硬件体系结构。比如:printf的本质:是你把你的数据写到了硬件里。
4.库可能在底层封装了系统调用
在整个计算机软硬件架构中,操作系统的定位是:一款纯正的“搞管理”的软件
三).如何理解操作系统OS的“管理”
对于OS的管理,我们使用生活中的例子来进行描述。对于一件事情我们分为两个步骤1.决策2.执行
管理的例子 ----- 学生,辅导员,校长。
加速理解:
1.对于校长管理学生,我们可以知道,我们一学期甚至大学四年都见不到校长几次 ,而对于校长的决策,比如:什么时候举办运动会,将全校最高的几个男生组成篮球队打比赛,我们都是要去执行的。
2.对于选全校身高最高的学生这个决策如何进行呢?校长一个一个的找同学去问吗?并不是,而是通过学生的身高数据去筛选。
3.那么,身高数据从哪来?那当然是辅导员统计上交的啦。
那么,我们可以得到几个结论:
1.要管理,管理者和被管理者,可以不需要见面
2.管理者怎么管理被管理者,根据“数据”进行管理
3.不需要见面,如何得到数据?由中间层获取。
那么校长对于学生数据就可以进行数据建模,使用结构体来描述一个学生的信息
校长进行数据建模的行为,我们可以认为是先描述,再组织。
操作系统对于计算机管理硬件
1. 描述起来,用struct结构体。
2. 组织起来,用链表或其他高效的数据结构。
四).系统调用和库函数概念
在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
三.进程
操作系统是怎么管理进行进程管理的呢?很简单,先把进程描述起来,再把进程组织起来!
一).进程基本概念与基本操作
课本概念:程序的一个执行实例,正在执行的程序等
内核观点:担当分配系统资源(CPU时间,内存)的实体
加速理解:
我们可以简单的形容为我们找工作的过程:内存中的代码和数据就是“我们”,进程控制块就是“我们的简历”,CPU就是“面试官”,进程列表就是“我们的简历在排队”,我们在等待面试官筛选的过程本质上是我们的简历在等待被筛选,也就是进程控制块在被读取而不是我们的代码和数据,而进程控制块上的代码和数据地址就是“我们的电话号码和居住地址”。这样应该就能稍微理解进程了。
1.描述进程-PCB
task_struct ---- PCB的一种
在Linux中描述进程的结构体叫做task_struct。
task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息
总结:
进程 = 内核数据结构对象 + 自己的代码和数据
在这里就是:进程 = PCB(task_struct) + 自己的代码和数据
2.task_ struct
内容分类
- 标示符: 描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
- 上下文数据: 进程执行时处理器的寄存器中的数据。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息。
组织进程
可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里
3.查看进程
1). 进程的信息可以通过 /proc 系统文件夹查看
如:要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹。
2). 大多数进程信息同样可以使用top和ps这些用户级工具来获取
我们历史上执行的所有的指令,工具,自己的程序,运行起来,全部都是进程。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{while(1){sleep(1);printf("我是一个进程pid: %d\n",getpid());}return 0;
}
getpid() 的作用
查看运行程序的进程 ps axj | grep code
添加属性列:ps axj | head -1;ps axj | grep code
杀掉进程 ctrl + c 或 kill -9 pid
4.通过系统调用获取进程标示符
- 进程id(PID)
- 父进程id(PPID)
1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/types.h>4 5 int main()6 {7 while(1)8 {9 sleep(1);10 printf("我是一个子进程pid: %d,我的父进程:%d\n",getpid(),getppid());11 } 12 }
那么这个135370进程是什么呢?
操作系统会给每一个用户分配一个bash
查看bash:while :; do ps axj |head -1;ps axj | grep 'bash' | grep -v grep ; sleep 1 ; done
5.通过系统调用创建进程-fork初识
1).认识fork
运行 man fork
1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/types.h>4 5 int main()6 {7 8 printf("父进程开始运行,pid: %d\n", getpid());9 pid_t id = fork();10 printf("进程开始运行,pid: %d\n", getpid());11 }
2).父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
3).fork有两个返回值
返回值中子进程为0,父进程为子进程的pid
4).fork 之后通常要用 if 进行分流
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{printf("父进程开始运行,pid: %d\n", getpid());pid_t id = fork();if(id < 0){perror("fork");return 1;}else if(id == 0){// childwhile(1){sleep(1);printf("我是一个子进程 !, 我的pid: %d, 我的父进程id: %d\n", getpid(), getppid());}} else{ //fatherwhile(1){ sleep(1);printf("我是一个父进程 !, 我的pid: %d, 我的父进程id: %d\n", getpid(), getppid());} }printf("进程开始运行,pid: %d\n", getpid());
}
那么我们会产生下面几个问题
1.fork为什么会有两个返回值?
因为 父进程 :子进程 == 1 :n 父进程可能有多个子进程,父进程需要管理子进程,所以需要得到子进程的pid,所以父进程的返回值为子进程的pid,而子进程只需要管理好自己,子进程pid可以通过getpid得到,所以返回0。
2.为什么一个函数会被返回两次?
fork语句后创建了子进程且被调度了,父进程执行一次return,子进程也执行一次return
3.一个变量怎么能让 if 和 else if 同时成立?这个问题需要在后面才能解释清楚。
首先我们要知道一个前提:进程具有独立性。也就是父进程挂掉了子进程也无影响。
代码测试:
#include <stdio.h> #include <unistd.h> #include <sys/types.h>int gval=100; int main() {printf("父进程开始运行,pid: %d\n", getpid());pid_t id = fork();if(id < 0){perror("fork");return 1;}else if(id == 0){printf("我是一个子进程 !, 我的pid: %d, 我的父进程id: %d, gval: %d\n", getpid(), getppid(), gval);sleep(5);// childwhile(1){sleep(1);printf("子进程修改变量: %d->%d", gval, gval+10);gval+=10; // 修改printf("我是一个子进程 !, 我的pid: %d, 我的父进程id: %d\n", getpid(), getppid());}}else{//fatherwhile(1){sleep(1);printf("我是一个父进程 !, 我的pid: %d, 我的父进程id: %d, gval: %d\n", getpid(), getppid(), gval); }}printf("进程开始运行,pid: %d\n", getpid()); }
二).进程状态
1.Linux内核源代码怎么说
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
下面的状态在kernel源代码里定义:
*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/
static const char *const task_state_array[] = {"R (running)", /*0 */"S (sleeping)", /*1 */"D (disk sleep)", /*2 */"T (stopped)", /*4 */"t (tracing stop)", /*8 */"X (dead)", /*16 */"Z (zombie)", /*32 */
}
进程状态就是一个整数
2.运行 && 阻塞 && 挂起
挂起:将进程交换到磁盘的swap分区
运行:进程在调度队列中,进程的状态都是running
阻塞:等待某种设备或资源就位(键盘,显示器,网卡....)
进程状态的变化表现之一:就是要在不同的队列中进行流动,本质都是数据结构的增删查改
3.进程状态查看
循环查看进程状态:while :; do ps axj |head -1; ps axj | grep code ;sleep 1; done
a:显示一个终端所有的进程,包括其他用户的进程。
x:显示没有控制终端的进程,例如后台运行的守护进程。
j:显示进程归属的进程组ID、会话ID、父进程ID,以及与作业控制相关的信息
u:以用户为中心的格式显示进程信息,提供进程的详细信息,如用户、CPU和内存使用情况等
我们通过代码来具体查看进程状态
R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
这个状态很少见,当磁盘老化,内存严重不足时才有可能出现
T/t停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
小 t 状态,程序被debug,断点,程序被暂停了
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
4.Z(zombie)-僵尸进程
僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(僵尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
我们使用下面这段代码查看僵尸状态
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t id = fork();if(id == 0){//childint count = 5;while(count) //5次后退出{printf("我是子进程,我正在运行: %d\n", count);sleep(1);count--;}}else {while(1){printf("我是父进程,我正在运行...\n");sleep(1);}}return 0;
}
僵尸进程危害
- 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!那么就会造成内存泄漏。
- 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护?是的!
- 那⼀个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存。
5.孤儿进程
父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
父进程先退出,子进程就称之为“孤儿进程”
孤儿进程被1号systemd进程领养,当然要有systemd进程回收喽。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t id = fork();if(id == 0){// childwhile(1){printf("我是一个子进程, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);}}else{// fatherint cnt = 5;while(cnt){printf("我是一个父进程, pid: %d, ppid: %d\n", getpid(), getppid());cnt--;sleep(1);}} return 0;
}
那么这个1号进程是什么呢? 为什么要领养呢?
1号进程就是操作系统。
如果不领养,子进程退出,进入僵尸状态后就无法回收,造成内存泄漏。
三).进程优先级
1.基本概念
- cpu资源分配的先后顺序,就是指进程的优先权(priority)。
- 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
- 还可以把进程运行到指定的CPU上,这样⼀来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能
当然,这么看还是很陌生,我们从三个方向认识。
是什么?
是进程得到cpu资源的先后顺序。
为什么?
目标资源稀缺,导致要通过优先级确认谁先谁后的问题。
怎么办?
也是一种数字。值越低,优先级越高,反之,优先级越低。基于时间片的分时操作系统,考虑公平性,优先级可能变化,但是变化幅度不能太大。
2.查看系统进程
ps -al | head -1 && ps -al |grep code
- UID : 代表执行者的身份
- PID : 代表这个进程的代号
- PPID :代表这个进程是由哪个进程发展衍⽣而来的,亦即父进程的代号
- PRI :代表这个进程可被执行的优先级,其值越小越早被执行
- NI :代表这个进程的nice值
注意:
1.nice其取值范围是-20⾄19,一共40个级别 。
2.当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行。
3.程真实的优先级=PRI(默认优先级80)+NI。
3.查看修改进程优先级
用top命令更改已存在进程的nice:
- top
- 进入top后按“r”‒>输⼊进程PID‒>输入nice值。注意是输入nice值。
命令 | 用途 |
---|---|
nice | 启动时设置Nice值 |
renice | 修改运行中进程的Nice值 |
chrt | 查看/设置实时优先级 |
ps -o pid,ni,pri,rtprio,comm | 查看各种优先级 |
top | 交互式查看和修改优先级 |
注意:优先级设立不合理,会导致优先级低的进程长时间得不到CPU资源,进而导致:进程饥饿
4.补充概念---竞争、独立、并行、并发
竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
并发: 多个进程在⼀个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。
四).进程切换
CPU上下文切换:其实际含义是任务切换, 或者CPU寄存器切换。当多任务内核决定运行另外的任务时, 它保存正在运行任务的当前状态, 也就是CPU寄存器中的全部内容。这些内容被保存在任务自己的堆栈中, 入栈工作完成后就把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU寄存器, 并开始下一个任务的运行, 这一过程就是context switch。
当然这么看还是不理解,我们先认识下几个问题 。
1.死循环进程如何运行
- 一旦一个进程占有CPU,会把自己的代码执行完吗?不会,只执行一段时间片的东西。
- 死循环进程不会一直占有CPU。
2. CPU和寄存器
3.如何切换
加速理解:
可以理解为我们进入大学后去服两年兵役,此时我们需要向导员报告,学校需要保存我们的学籍信息。两年后,我们回来继续上学,那么我们要提前通知导员,让学校恢复我们的学籍信息。我们可以粗略的认为:学校-----CPU;导员-----调度器;我们-----进程;学籍-----进程运行的临时数据,CPU内寄存器里面的内容(当前进程的上下文数据);保留学籍-----保存进程上下文数据,CPU内寄存器里面的内容保存起来;恢复数据-----恢复进程上下文数据,恢复到CPU内寄存器里;去服兵役-----进程从CPU上剥离下来。
时间片:当代计算机都是分时操作系统,没有进程都有它合适的时间片(其实就是⼀个计数器)。时间片到达,进程就被操作系统从CPU中剥离下来。
五).Linux真实的调度算法
图是Linux2.6内核中进程队列的数据结构
1.优先级
- 普通优先级:100〜139(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)
- 实时优先级:0〜99(不关心)
2.活动队列
- 时间片还没有结束的所有进程都按照优先级放在该队列
- nr_active: 总共有多少个运行状态的进程
- queue[140]: 一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!
- 从该结构中,选择一个最合适的进程,过程是怎么的呢?
1. 从0下表开始遍历queue[140]
2. 找到第一个非空队列,该队列必定为优先级最高的队列
3. 拿到选中队列的第一个进程,开始运行,调度完成!
4. 遍历queue[140]时间复杂度是常数!但还是太低效了 - bitmap[5]:一共140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5*32个比特位表示队列是否为空,这样,便可以大大提高查找效率!
3.过期队列
- 过期队列和活动队列结构一模一样
- 过期队列上放置的进程,都是时间片耗尽的进程
- 当活动队列上的进程都被处理完毕之后,对过期队列的进程进行时间片重新计算
4.active指针和expired指针
- active指针永远指向活动队列
- expired指针永远指向过期队列
- 可是活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间片到期时⼀直都存在的。
- 没关系,在合适的时候,只要能够交换active指针和expired指针的内容,就相当于有具有了一批新的活动进程!
那么我们理解了这算法,我们也就知道了为什么要有 PRI和NI两个值了,如果没有NI,那当我们修改进程的优先级时,是在活动队列直接将进程的优先级修改然后再排序吗?不,那会大大增加时间成本;而是将修改的结果计算好,当进程在活动队列运行结束后进入过期队列后直接链接,不用排序。
- PRI :代表这个进程可被执行的优先级,其值越小越早被执行
- NI :代表这个进程的nice值
总结: 在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法!
相关文章:
Linux 入门:操作系统进程详解(上)
目录 一.冯诺依曼体系结构 一). 软件运行前为什么要先加载?程序运行之前在哪里? 二).理解数据流动 二.操作系统OS(Operator System) 一).概念 二).设计OS的目的 三).如何理解操作系统…...
5.7/Q1,GBD数据库最新文章解读
文章题目:Global, regional, and national burden and trends of rheumatoid arthritis among the elderly population: an analysis based on the 2021 Global Burden of Disease study DOI:10.3389/fimmu.2025.1547763 中文标题:全球、区域…...
[pdf,epub]292页《分析模式》漫谈合集01-59提供下载
《分析模式》漫谈合集01-59的pdf、epub文件提供下载,地址: umlchina.com/url/ap.html,或查看本账号的CSDN资源。 已排版成适合手机阅读,pdf的排版更好一些。...
Spring MVC的工作流程, DispatcherServlet 的工作流程
Spring MVC 是一种基于Java的模型-视图-控制器(MVC)Web框架,它通过清晰的角色划分简化了Web应用开发。下面是Spring MVC的工作流程以及DispatcherServlet的具体工作流程。 Spring MVC 工作流程 请求到达:客户端发起一个HTTP请求…...
【Godot】使用 Shader 实现可配置圆角效果
文章目录 效果预览实现原理完整Shader代码关键参数详解1. 半径参数(radius)2. 角开关参数(hide_*)数学原理圆形区域判定公式坐标映射性能优化使用示例编辑器操作代码控制进阶技巧1. 添加抗锯齿2. 外发光效果3. 动画效果常见问题解决方案问题1:圆角边缘锯齿问题2:圆形变形…...
【翻译、转载】MCP 提示 (Prompts)
原文地址:https://modelcontextprotocol.io/docs/concepts/prompts#python 提示 (Prompts) 创建可重用的提示模板和工作流 提示 (Prompts) 使服务器能够定义可重用的提示模板和工作流,客户端可以轻松地将其呈现给用户和 LLM。它们提供了一种强大的方式来…...
论快乐的学习和学习的快乐
目录 一、背景二、过程1.快乐的学习:理念与实践快乐学习的理念溯源快乐学习在教育实践中的体现 2.学习的快乐:内涵与价值学习的快乐的多维内涵学习的快乐对个人成长的价值 3.快乐的学习与学习的快乐的相互关系快乐的学习是学习快乐的重要前提学习的快乐是…...
Git 命令
参考文献: Git 教程 | 菜鸟教程Git 使用教程:最详细、最正宗手把手教学(万字长文)git忽略某个目录或文件不上传 文章目录 工作原理基本命令配置使用 其他命令日志分支回退标签 忽略指定文件远程仓库 工作原理 Git 是由 Linus To…...
365打卡第R6周: LSTM实现糖尿病探索与预测
🍨 本文为🔗365天深度学习训练营中的学习记录博客 🍖 原作者:K同学啊 🏡 我的环境: 语言环境:Python3.10 编译器:Jupyter Lab 深度学习环境:torch2.5.1 torchvision0…...
新能源实验室电磁兼容设计优化方案论述
摘要:本文旨在进行新能源核心部件/系统测试实验室电磁兼容情况设计及优化方案进行论述,通过系统化梳理实验室的主流设备仪器,试验搭建典型方案。识别不同设备的电磁兼容现状,实验室基于设备布局常见设计方案不足点,故障…...
计算机图形学中的深度学习
文章目录 零、前言0.课程考核1.课程大纲2.前置知识3.教材4.课程大纲5.相关课程 Relevant Courses 一、计算机图形学1.本章学习目标2.图形学的应用3.SIG Graph papers 二、基本图形生成算法1.本章学习目标2.图形API3.OpenGL(1)什么是OpenGL(2)OpenGL 的基本组件:顶点…...
RockyLinux9.3-24小时制
在 RockyLinux 9.3 中,默认时间格式为 12 小时制,调整为 24 小时制 案例一:在 RockyLinux 9.3 中,默认时间格式为 12 小时制,调整为 24 小时制案例二:时间显示英文调整为中文endl 案例一:在 Roc…...
25.2linux中外置RTC芯片的PCF8563实验(测试)_csdn
1、硬件原理图分析 知道了这些引脚我们还是按照老习惯! 配置镜像和设备树文件! 2、修改设备树 2.1、添加或者查找 PCF8563 所使用的 IO 的 pinmux 配置 打开stm32mp15-pincrtl.dtsi 文件,查找节点I2C4: 也就是中断引脚并不需要配置pinctrl…...
高性能 WEB 服务器 Nginx:多虚拟主机实现!
Nginx 配置多虚拟主机实现 多虚拟主机是指在一台 Nginx 服务器上配置多个网站 在 Nginx 中,多虚拟主机有三种实现方式: 基于IP地址实现多虚拟主机 基于端口号实现多虚拟主机 基于域名实现多虚拟主机 1 基于域名实现多虚拟主机 在 Nginx 中配置多个…...
C++ 的类型排序
0.前言 在 C 中,我编写了一个 tuple-like 模板,这个模板能容纳任意多且可重复的类型: template<typename... Ts> struct TypeList {};// usage: using List1 TypeList<int, double, char, double>; using List2 TypeList<…...
[计算机网络]拓扑结构
拓扑结构一般会在计网教材或课程的第一章计网的分类那里接触到,但实际上计网的拓扑结构并不只是第一章提到的总线型、星型、树型、网状、混合型那几种类型那么简单,学完了后面的数链层以后对拓扑结构会有新的体会,所以特别单独总结成一篇博客…...
C#方法返回值全解析:从基础语法到实战技巧
摘要:方法返回值是C#编程的核心概念之一。本文将带你彻底掌握返回值声明、void方法特性,以及如何通过返回值实现优雅的流程控制(文末附完整示例代码)。 返回值的基础法则 类型声明原则 有返回值:必须在方法名前声明…...
修复笔记:SkyReels-V2 项目中的 torch.cuda.amp.autocast 警告和错误
#工作记录 一、问题描述 在运行项目时,出现以下警告和错误: FutureWarning: torch.cuda.amp.autocast(args...) is deprecated. Please use torch.amp.autocast(cuda, args...) instead.with torch.cuda.amp.autocast(dtypepipe.transformer.dtype), …...
【TF-BERT】基于张量的融合BERT多模态情感分析
不足:1. 传统跨模态transformer只能处理2种模态,所以现有方法需要分阶段融合3模态,引发信息丢失。2. 直接拼接多模态特征到BERT中,缺乏动态互补机制,无法有效整合非文本模态信息 改进方法:1. 基于张量的跨模…...
SONiC-OTN代码详解(具体内容待续)
SONiC-OTN代码详解 (具体内容待续) 基于AI的源代码解析工具的产生使得代码阅读和解析变得越来越高效和简洁,计划通过这样的工具对SONiC在OTN领域的应用做一个全自动的解析,大部分内容会基于AI工具的自动解析结果。这样做的目的是…...
牛客周赛90 C题- Tk的构造数组 题解
原题链接 https://ac.nowcoder.com/acm/contest/107500/C 题目描述 解题思路 数组a是不可以动的,所以我们可以把a[i]*b[i]*i分成两组,分别为a[i]*i以及b[i] 然后策略就很明显了,让更大的b[i]匹配更大的a[i]*i 详细实现见代码。 代码&am…...
[ML]通过50个Python案例了解深度学习和神经网络
通过50个Python案例了解深度学习和神经网络 摘要:机器学习 (Machine Learning, ML)、深度学习 (Deep Learning, DL) 和神经网络 (Neural Networks, NN) 是人工智能领域的核心技术。Python 是学习和实践这些技术的首选语言,因为它提供了丰富的库(如 scikit-learn、Te…...
vue3 - keepAlive缓存组件
在Vue 3中,<keep-alive>组件用于缓存动态组件或路由组件的状态,避免重复渲染,提升性能。 我们新建两个组件,在每一个组件里面写一个input,在默认情况下当组件切换的时候,数据会被清空,但…...
自由学习记录(58)
Why you were able to complete the SpringBoot MyBatisPlus task smoothly: Clear logic flow: Database → Entity → Service → Controller → API → JSON response. Errors are explicit, results are verifiable — you know what’s broken and what’s fixed. Sta…...
短信侠 - 自建手机短信转发到电脑上并无感识别复制验证码,和找手机输验证码说再见!
自建手机短信转发到电脑上并无感识别复制验证码 一、前言 项目开发语言:本项目使用PythonRedisC#开发 你是否也遇到过这样的场景: 正在电脑上操作某个网站,需要输入短信验证码手机不在身边,或者在打字时来回切换设备很麻烦验证码…...
课程10. 聚类问题
课程10. 聚类问题 聚类此类表述的难点K 均值法让我们推广到几个集群的情况如果我们选择其他起始近似值会怎样? 结论在 sklearn 中的实现 如何处理已发现的问题?层次聚类Lance-Williams 算法Lance-Williams 公式在Scipy中实现 示例DBSCANDBSCAN 算法 聚类…...
深度学习中的数据增强:提升食物图像分类模型性能的关键策略
深度学习中的数据增强:提升食物图像分类模型性能的关键策略 在深度学习领域,数据是模型训练的基石,数据的数量和质量直接影响着模型的性能表现。然而,在实际项目中,获取大量高质量的数据往往面临诸多困难,…...
QT设计权限管理系统
Qt能够简单实现系统的权限设计 首先我们需要一个登陆界面 例如这样 然后一级权限,可以看到所有的内容,不设置菜单栏的隐藏。 然后其他权限,根据登陆者的身份进行菜单栏不同的展示。 菜单栏的隐藏代码如下: ui->actionuser-…...
从上帝视角看文件操作
1.为什么使用文件? 如果没有文件,我们写的程序中的数据是存储在电脑的内存中,当程序退出时,内存被回收后,数据就丢失了,等下次运行程序,是无法看到上次程序的数据的。(比如我们在程序中写通讯录时,联系人的相关数据都是放在内存中的,当程序退出时,这些数据也会随之消…...
【51单片机6位数码管显示时间与秒表】2022-5-8
缘由数码管 keil proteus 为什么出现这种情况呢?-编程语言-CSDN问答 #include "reg52.h" unsigned char code smgduan[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0,64}; //共阴0~F消隐减号 unsigned char cod…...
从头训练小模型: 4 lora 微调
1. LoRA (Low-Rank Adaptation) LoRA是一种高效的参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)方法,原理是通过低秩分解的方式对预训练模型进行微调。 相比于全参数微调(Full Fine-Tuning),LoRA…...
前端开发,文件在镜像服务器上不存在问题:Downloading binary from...Cannot download...
问题与处理策略 问题描述 在 Vue 项目中,执行 npm i 下载依赖时,报如下错误 Downloading binary from https://npm.taobao.org/mirrors/node-sass//v4.14.1/win32-x64-72_binding.node Cannot download "https://npm.taobao.org/mirrors/node-sa…...
Debezium Binlog协议与事件转换详解
Debezium Binlog协议与事件转换详解 1. MySQL Binlog通信机制 1.1 连接建立流程 #mermaid-svg-eE88YFqcTG9kUWaZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eE88YFqcTG9kUWaZ .error-icon{fill:#552222;}#mer…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.1 日期时间标准化(时区转换/格式统一)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL数据分析实战:数据清洗之日期时间标准化(时区转换/格式统一)4.1 日期时间标准化:从混乱到有序4.1.1 数据乱象&…...
基于Hive + Spark离线数仓大数据实战项目(视频+课件+代码+资料+笔记)
精品推荐:基于Hive Spark离线数仓大数据实战项目,共23节课,供学习参考。 项目介绍项目中 docker 使用项目环境搭建项目数仓分层项目业务分析sqoop 数据采集python 数据采集项目 ODS 层创建DWD 层构建DWS 层构建项目回顾(一&…...
【深入浅出MySQL】之数据类型介绍
【深入浅出MySQL】之数据类型介绍 MySQL中常见的数据类型一览为什么需要如此多的数据类型数值类型BIT(M)类型INT类型TINYINT类型BIGINT类型浮点数类型float类型DECIMAL(M,D)类型区别总结 字符串类型CHAR类型VARCHAR(M)类型 日期和时间类型enum和set类型 …...
从入门到登峰-嵌入式Tracker定位算法全景之旅 Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地
Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地 本章聚焦 ESP32-S3 平台上如何利用 LSM6DS3 IMU 实现 死算(Dead Reckoning),并结合 零速更新(ZUPT) 或 磁力计辅助 进行 漂移校正,最终通过 EKF/UKF 融合提升定位精度。 一、传感器简介与校准 LSM6DS3 主要参数 加速…...
【iOS】 方法交换
【iOS】 方法交换 method-swizzling 文章目录 【iOS】 方法交换 method-swizzling前言什么是method-swizzling相关API方法交换的风险在load方法中保证只加载一次要在当前类的方法中进行交换如果方法依赖于cmd 方法交换的应用 前言 之前看过有关于消息转发的内容,这里我们可以简…...
PostgreSQL 的 ANALYZE 命令
PostgreSQL 的 ANALYZE 命令 ANALYZE 是 PostgreSQL 中用于收集数据库对象统计信息的关键命令,这些统计信息对于查询优化器生成高效执行计划至关重要。 一 ANALYZE 命令 1.1 基本语法 ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ] ANALYZE [ …...
初识 iOS 开发中的证书固定
引言 在移动应用安全领域,HTTPS/TLS 是数据传输的第一道防线,但仅依赖系统默认的证书验证仍有被中间人(MITM)攻击的风险。Certificate Pinning(证书固定)通过将客户端信任“钉”在指定的服务器证书或公钥上…...
2025 年如何使用 Pycharm、Vscode 进行树莓派 Respberry Pi Pico 编程开发详细教程(更新中)
micropython 概述 micropython 官方网站:https://www.micropython.org/ 安装 Micropython 支持固件 树莓派 Pico 安装 Micropython 支持固件 下载地址:https://www.raspberrypi.com/documentation/microcontrollers/ 选择 MicroPython 下载 RPI_PIC…...
设计模式每日硬核训练 Day 17:中介者模式(Mediator Pattern)完整讲解与实战应用
🔄 回顾 Day 16:责任链模式小结 在 Day 16 中,我们学习了责任链模式(Chain of Responsibility Pattern): 将请求沿链传递,节点可选择处理或传递下一节点。实现了请求发送者与多个处理者的解耦…...
文章记单词 | 第63篇(六级)
一,单词释义 vegetable [ˈvedʒtəbl] n. 蔬菜;植物人;生活单调乏味的人;adj. 蔬菜的;植物的faint [feɪnt] adj. 模糊的;微弱的;虚弱的;v. 昏倒,昏厥;n. 昏…...
ES类的索引轮换
通过以下请求方法创建一个名为 “tiered-storage-policy” 的 ISM policy: PUT _plugins/_ism/policies/tiered-storage-policy {"policy": {"description": "Changes replica count and deletes.","schema_version": 1,…...
小白机器人假想:分布式关节控制——机器人运动的未来模式?
引言 在机器人技术快速发展的今天,控制架构的创新往往能带来突破性进展。作为一名机器人爱好者,我最近思考了一个大胆的设想:如果机器人的每个关节都配备独立的动作存储器和处理器,并通过高速光纤网络与中央"驱动总脑"…...
LangChain4j +DeepSeek大模型应用开发——9 优化硅谷小鹿
1.预约业务的实现 这部分我们实现硅谷小鹿的查询订单、预约订单、取消订单的功能 创建MySQL数据库表 CREATE DATABASE xiaolu; USE xiaolu; -- 创建预约表 appointment CREATE TABLE appointment (id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键ID,自增, -- 主…...
Oracle VirtualBox 在 macOS 上的详细安装步骤
Oracle VirtualBox 在 macOS 上的详细安装步骤 一、准备工作1. 系统要求2. 下载安装包二、安装 VirtualBox1. 挂载安装镜像2. 运行安装程序3. 处理安全限制(仅限首次安装)三、安装扩展包(增强功能)四、配置第一个虚拟机1. 创建新虚拟机2. 分配内存3. 创建虚拟硬盘4. 加载系…...
Day110 | 灵神 | 二叉树 | 根到叶路径上的不足节点
Day110 | 灵神 | 二叉树 | 根到叶路径上的不足节点 1080.根到叶路径上的不足节点 1080. 根到叶路径上的不足节点 - 力扣(LeetCode) 思路: 笔者一开始没看懂,只能通过部分的例子,原因是把路径和小于limit的都给删了…...
超详细讲解C语言转义字符\a \b \r \t \? \n等等
转义字符 C语言有一组字符很特殊,叫做转义字符,顾名思义,改变原来的意思的字符。 1 \? ??)是一个三字母词,在以前的编译器它会被编译为] (??会被编译为[ 因此在以前输入(are you ok ??)就会被编译为are you ok ] 解决这个…...
TensorFlow 多卡训练 tf多卡训练
目录 export TF_GPU_ALLOCATORcuda_malloc_async 🔧 具体作用 优势 🧩 依赖条件 ✅ 设置方式(Linux/macOS) export TF_GPU_ALLOCATORcuda_malloc_async 是设置 TensorFlow 使用 CUDA 异步内存分配器 的环境变量。这个设置可…...