操作系统之进程状态、优先级和切换与调度
文章目录
- 1. 进程状态
- 1.1 课本名词提炼
- 1.2 运行&阻塞&挂起
- 1.2.1 运行
- 1.2.2 阻塞
- 1.2.3 挂起
- 1.3 理解内核链表
- 1.4 Linux中的内核解释
- 1.5 进程状态的查看
- 1.6 Z(zombie)——僵尸进程
- 1.6.1 创建僵尸进程
- 1.6.2 僵尸进程的危害
- 1.7 孤儿进程
- 2. 进程优先级
- 2.1 基本概念
- 2.2 查看优先级
- 2.3 PRI和NI
- 2.4 手动更改进程的优先级
- 2.5 竞争、独立、并行与并发
- 3. 进程切换与调度
- 3.1 基本概念
- 3.2 Linux中真实的调度算法:O(1)调度算法(重点)
- 3.2.1 初步了解
- 3.2.2 详细介绍
- 3.2.3 总结
1. 进程状态
1.1 课本名词提炼
1.2 运行&阻塞&挂起
1.2.1 运行
我们知道,CPU的资源是有限的,但每个进程都需要CPU来进行处理数据的操作,于是CPU会在其内部维护一个叫做调度队列的数据结构,每个进程按照一定的顺序依次排列在一起,CPU根据先来先服务的算法,依次从头至尾遍历执行这个调度队列中的所有进程,这种调度算法也叫做:FIFO。于是笼统的讲,进程在调度队列中,其状态就是运行状态。更细致的讲,正在被CPU处理的进程叫做正在运行态,在调度队列中等待的进程叫做就绪(等待)运行态。
1.2.2 阻塞
拿上图来说,当1号进程被CPU执行的时候,其内部进行了I/O申请,于是1号进程就会去等待对应的I/O硬件资源设备就绪,此时它会被链接到一个叫做等待队列的数据结构中,此时我们把在等待队列中进程的状态叫做阻塞状态。
1.2.3 挂起
- 所谓挂起,就是当前的系统内存资源非常紧张不足的时候,此时操作系统会把对应一部分进程的代码和数据放入磁盘的交换分区内(swap分区),以此来调解缓和内存资源不足的问题。挂起分为:1. 阻塞挂起 ,2. 就绪挂起。
- 阻塞挂起顾名思义就是把在阻塞状态的进程的代码和数据放入swap分区内,来缓解内存不足问题,就绪挂起是在阻塞挂起后,依然出现内存资源不足,此时会把就绪状态的一部分的进程的代码和数据也给放入swap交换分区内。
- 阻塞挂起
- 就绪挂起
1.3 理解内核链表
进程状态的变化,表现之一,就是在不同的队列之间进行流动,也就是对应数据结构的增删查改。那怎么能做到这种流动的呢?也就是说进程是怎么做到既属于这个数据结构,又属于另外一个数据结构的呢?
这得涉及到具体的操作系统内核中进程的设计,以Linux内核为例,其在进程PCB(task_struct)的设计中,采用了增加 struct list_head* 结构体指针变量的形式,其结构如下所示:
struct list_head {struct list_head* prev, *next;
};
具体的来说,在 struct task_struct 结构体内部,采用组合的方式,增加了struct list_head* 结构体指针作为成员变量,其内部是两个指针,可以指向前驱与后继进程结点,对应着上述就绪队列就可以取名为,struct list_head* run_queue,同理,等待队列就是,struct list_head* wait_queue。于是,判断一个进程到底属于哪个队列,就可以看其task_struct内对应哪个list_head*的指向不为空即可。这也是一个先描述,再组织的过程,如下图所示:
1.4 Linux中的内核解释
- 为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
- 体现在具体的代码中,也就是Linux中的task_struct(PCB)中,所谓的进程状态就是task_struct中的一个整型变量。可以对该整型变量进行数值判断,来判断该进程此时位于什么状态。
进程状态在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 */
};
- R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- S睡眠(阻塞)状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
- D磁盘休眠状态(disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
- T停止状态(stopped):可以通过发送SIGSTOP信号给进程来停止进程。这个被暂停的进程可以通过发送SIGCONT信号让进程继续运行。
- X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
下一小节是具体的实践操作观察。
1.5 进程状态的查看
具体的进程查看可以使用 ps aux / ps ajx 命令来查看
• a:显示一个终端所有的进程,包括其他用户的进程。
• x:显示没有控制终端的进程,例如后台运行的守护进程。
• j:显示进程归属的进程组ID、会话ID、父进程ID,以及与作业控制相关的信息。
• u:以用户为中心的格式显示进程信息,提供进程的详细信息,如用户、CPU和内存使用情况等。
区别:
ps aux
ps ajx
ps命令查看的时候是静态查看的,也就是说,它查看的当前进程状态的一个快照。为了方便观察与述说,我们可以使用以下脚本命令(grep test是筛选含test的字段进行打印,test是可执行程序名)来实施每隔一秒进行自动监测:
while :; do ps ajx |head -1; ps ajx | grep test; sleep 1; done
查看运行状态——R:
输入以下代码:
#include<stdio.h>
int main()
{while (1) ;return 0;
}
查看:
查看阻塞状态——S:
输入以下代码:
#include<stdio.h>
int main()
{int x = 0;scanf("%d", &x); // 进行I/O申请,所以是阻塞return 0;
}
查看:
测试printf:
#include<stdio.h>
int main()
{while(1)printf("hello shuaiming\n");return 0;
}
查看:
分析:对上面情况其实很好理解,申请I/O时,是阻塞状态,当申请I/O完了之后就是运行状态。打个比方,程序每打印一条语句呈现在窗口上,所花费的时间是1秒,这其中I/O操作是占了大头,可能占到了百分之80的比例,其中只有20的比例是在运行程序,而我们设置的脚本命令是每隔1秒监测一次,也就是说,我们的进程是不断的在运行队列和阻塞队列之间来回的进行切换的,即存在一定的运气成分,能让我们监测时同时监测到R和S状态,这与我们的理论并不冲突。
对于其中状态后跟的+号解释,如R+:其实+就是表示它是在前台运行,没有+就是在后台运行,我们可以手动让程序在后台运行,只需运行时最后跟上&即可,如:
./test &
查看:
其余状态:
- T,当程序一直在窗口中跑时,我们输入ctrl+z 就可以停止程序,此时对应的状态就是T状态
- t,程序进行调试时,对应的状态
- D,不可进行杀死的阻塞状态,这个状态是必须会得到某种硬件资源后,方可解除D状态继续运行。其中在等待硬件资源时,是不可被杀死,而S状态在等待硬件资源时,是可以被杀死
- X,是一种返回状态,不能被观察到
- Z,僵尸状态,具体见下小节
1.6 Z(zombie)——僵尸进程
一个人离奇死亡,法医会对他进行抽样检测获取死亡信息,警察会将法医获取的死亡信息告知家属,然后再处理尸体。其中人在死亡,直至法医获取死亡信息的这一时间段内,我们称这人为僵死(僵尸)状态。同理在计算机的世界内,有个神奇的进程,叫作僵尸进程,它是子进程在已经完成所有的任务后,将要退出销毁了,此时它需要将自己完成任务的情况信息返回给父进程,也就是等待着父进程给他“验尸”,在父进程收集完它所有的信息后,子进程才会被完全销毁。在完成所有任务后,等待“验尸”的这一时间过程中,我们称该进程为僵尸进程。 有僵尸进程的概念就是为了获取子进程退出的信息。
1.6.1 创建僵尸进程
如下代码,我们创建一个维持30秒的僵尸进程:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id > 0) { //parentprintf("parent[%d] is sleeping...\n", getpid());sleep(30);}else {printf("child[%d] is begin Z...\n", getpid());sleep(5);exit(EXIT_SUCCESS);}return 0;
}
查看:
1.6.2 僵尸进程的危害
- 如果父进程一直不管,不进行回收,那么Z状态一直存在,这种情况势必会造成内存资源浪费,也就是内存泄漏
- 此外,Z状态也是状态,也需要操作系统去维护,这也会造成时间资源上的浪费
1.7 孤儿进程
当父进程提前退出,但此时子进程却没有退出,此时子进程就成了 “孤儿”,等到子进程退出时,会变成僵尸进程,此时如果没有父进程来“验尸”的话,那么又会造成资源的浪费。为了避免这种情况的发生,Linux中引入了孤儿进程的概念,即父进程提前退出,对应的子进程会被1号进程给领养,同时退出时,会由1号进程来进行回收。 此时被领养后的孤儿进程会由前台进程变成后台进程。
代码样例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{while (1){pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id == 0) {//childprintf("I am child, pid : %d\n", getpid());sleep(1);}else {//parentprintf("I am parent, pid: %d\n", getpid());sleep(1);exit(0);}}return 0;
}
查看:
2. 进程优先级
一个计算机系统中的CPU的资源是有限的,而某个时间段要执行很多的进程任务,这些进程任务中,有的很重要,有的又相对不是那么重要,如果不对这些进程任务进行合理的安排去让CPU执行的话,那么那些急需响应的进程任务就不能及时响应,达不到用户所期待的效果,用户的使用感就会下降,于是在具体的Linux操作系统中引入了优先级的概念。
2.1 基本概念
- CPU资源分配的先后顺序,就是指进程的优先级(priority)。
- 优先级高的进程有优先执行权利。配置进程优先级对多任务环境的linux很有用,可以改善系统性能。
- 还可以把进程运行到指定的CPU上,这样⼀来,把不重要的进程安排到某个CPU,可以大大改善系统整体的性能。
注意:优先级与权限是两种概念,优先级是指能得到资源的先后顺序,而权限是指是否能得到该资源。
2.2 查看优先级
输入ps -l 命令:
注意到一些重要信息:
- UID:执行者的身份
- PID:进程的唯一标识符
- PPID:该进程对应父进程的标识符
- PRI:代表这个进程可被执行的优先级,值越小优先级越高
- NI:代表这个进程的nice值,也就是对应优先级的修正值
2.3 PRI和NI
- PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
- 当nice值为负值的时候,那么该程序的优先级值将变小,即其优先级会变高,则其越快被执行,反之相反
- 在Linux下,调整进程优先级,就是调整进程nice值
- Linux操作系统是基于时间片的分时操作系统,为了考虑公平性,优先级可能变化,但变化的幅度不能太大
- nice其取值范围是-20至19,一共40个级别。
需要强调的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正数据。
2.4 手动更改进程的优先级
使用top命令更改已存在进程的nice值,具体操作如下:
- top
- 进入top后按“r”‒>输入进程PID‒>输入nice值
进入top:
输入r:
输入对应要修改的进程PID按下回车:
最后输入nice修正值:
查看结果:
注意:优先级设置的不合理,会导致优先级低的进程长时间得不到CPU资源,从而造成进程饥饿。
2.5 竞争、独立、并行与并发
- 竞争性:系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
- 独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰
- 并行:多个进程在多个CPU下分别运行,即在同一时刻内,是有多个进程在同时执行任务,这便称之为并行
- 并发:多个进程在一个CPU下采用进程切换的方式,即在一个时间段之内,让多个进程都得以推进,称之为并发。从微观时间上来看,依旧是一个进程执行完再执行下一个进程,从宏观时间上来看,则像是多个进程在同时运行一样
3. 进程切换与调度
3.1 基本概念
简单来说:
Linux操作系统是基于时间片的分时操作系统,也就是说一个进程的时间片用完了,它就不会再占用CPU了,那么它就会被CPU给替换出来,让下一个新的进程进入CPU工作,这一过程就叫做进程切换。
这个过程也叫做CPU上下文切换,更加专业详细一点来说:
CPU上下文切换:其实际含义是任务切换,或者CPU寄存器切换。当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态,也就是CPU寄存器中的全部内容。这些内容被保存在任务自己的堆栈中,入栈工作完成后就把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU寄存器, 并开始下一个任务的运行,这一过程就是context switch。
参考一下Linux内核0.11代码:
注意:
时间片:当代计算机都是分时操作系统,它保证了进程运行的公平性,每个进程都有它合适的时间片(其实就是一个计数器)。时间片用完,进程就被操作系统从CPU中剥离下来。 所以一个死循环程序,它并不会一直占用CPU,它的时间片用完了,也自然就会停止运行,只不过我们看它似乎一直在运行的原因就是,时间片设计的时间间隔很小,操作系统进行进程切换的速度又很快,导致人为的认为它一直在运行。
3.2 Linux中真实的调度算法:O(1)调度算法(重点)
3.2.1 初步了解
下图是Linux2.6内核中调度队列的数据结构,先整体认识下之间的关系,后续会有更全面讲解:
3.2.2 详细介绍
一个CPU拥有一个runqueue(就绪队列),runqueue内部含有一个存放两个元素的优先级数组(prio_array_t),这两个元素是一个结构体类型,分别表示活动队列与过期队列,这两个队列的结构是一致的。
更具体的来看:
- active指针永远指向活动队列
- expired指针永远指向过期队列
- nr_active表示当前活动队列中的进程数,在活动队列中,这些进程就是活跃的,是时间片还没有用完,将要准备执行的。过期队列中就是过期的,是当前一个调度内时间片用完了,但本身任务还没有完全执行完的。
- 具体的进程是存放在一个叫做queue的指针数组中的,其数组大小是140,正好一一对应140个优先级,这个指针数组实际上就是一个开散列的哈希表,采用了链地址法的形式,根据每个进程的优先级,对应映射在其对应的数组下标。注意:不是说进程的数量是只有140个,是说优先级位数是140个。也就是说一个数组下标对应一个优先级的进程队列。
- bitmap[5]其实就是另一个数据结构——位图。其内部存在5个32位的int整型变量,5*32=160,也就是说用了160个比特位去对应记录每个优先级的进程队列中是否有进程,比特位数值为1表示当前比特位对应的进程队列有数据,为0则表示没有。于是就可以通过进行一系列位运算,来判断哪个优先级的进程队列中还有进程。然后运用哈希表的哈希函数进行快速索引找到对应不为空的进程队列去拿进程进行切换与调度。注意:不是说有160个比特位就要全部用到,只是用其中的140个即可。
对于140个优先级的进程队列,实质我们关心的只有后40个,也就是对应下标范围[100,139],这个也叫做普通优先级,正好对应了上面所说的nice值的范围[-20,19]。其余100个都叫做实时优先级,实时优先级的优先顺序又是高于普通优先级的,正如它的名字一样,它是实时的,动态的,这个归系统调度管理。
- 普通优先级:100~139(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)
- 实时优先级:0~99(不关心)
对于为什么要划分实时与普通优先级?我的理解是:
Linux内核设计为了兼顾全面性,在整体基调是分时系统的前提下,内部又引入了实时系统,实时系统是为了应对那些强制性和高响应硬实施的进程任务而设计的,可以在一个调度内动态的插入进程任务于实时优先级的队列中,也就是重要的先来,直接插队。而后40个普通优先级的进程队列则是静态的,基于时间片的公平调度,一个进程时间片完成了,但还有任务没完全完成就会放入过期队列中,同时在一个调度循环内,如果有更高优先级的进程来了,它不会像实时优先级那样直接插队,而是直接按照优先级去入到过期队列中,等待下一个调度循环的到来。
具体如下图:
当然随着时间的推移,进程会根据优先级的顺序挨个执行,然后时间片完了的但还没完全执行完的进程任务就会放入过期队列中,同时在这段执行的时间段内,也会有新的进程加入进来,于是便有了下图:
时间向前流动,那么活动队列中的进程数会越来越少,过期队列中的进程数会越来越多,直至活动队列没有进程数时,也就是nr_active==0时,此时意味着一个调度循环执行完成,需要执行下一个调度循环,也就是要执行过期队列中还没执行完的进程,此时只需交换runqueue中的active与expired指针的指向即可完成过期队列向活动队列的切换,如下图:
思考:为什么非要加上bitmap[5]来进行对应的映射,然后找非0值的比特位进行索引,我的优先级运行队列(queue[140])的长度也是固定的,挨个进行遍历查找也能做到O(1)的时间复杂度?
回答:
即使你的queue的长度时固定,但从局部时间开销来看,每次都去遍历140单位的长度,可能有些下标对应的优先级有很多进程,也可能有些连续很长下标范围内没有进程。从整体来看,我们只是需要去访问那些有进程的下标,那些没有进程的下标我们不用关心。如果挨个遍历的,从局部来看就是个O(N),而且你的前100个长度是动态的,实时的,可能会有新进程进行插队,这样挨个进行遍历的操作就不能很好的处理实时性的要求。注意:我们把位运算看成是原子操作,也就是说,位运算非常的快。
3.2.3 总结
通过active指针永远指向活动队列这一特性,我们只需判断活动队列中的nr_active值是否为0即可,不为0,就去通过对应的bitmap[5](位图)进行一系列位运算操作,得到不为空的对应下标,然后通过哈希函数进行快速索引,进而依次得到优先级从高到低排列的进程,不断的进行切换与调度,直至nr_active的值为0,此时,一个调度循环就算完成了,接着我们再交换active与expired指针的指向,进行下一个循环,周而复始。从时间上来看,每次切换与调度一个进程进出CPU的时间消耗就是O(1)。这就是Linux中的O(1)调度算法。
相关文章:

操作系统之进程状态、优先级和切换与调度
文章目录 1. 进程状态1.1 课本名词提炼1.2 运行&阻塞&挂起1.2.1 运行1.2.2 阻塞1.2.3 挂起 1.3 理解内核链表1.4 Linux中的内核解释1.5 进程状态的查看1.6 Z(zombie)——僵尸进程1.6.1 创建僵尸进程1.6.2 僵尸进程的危害 1.7 孤儿进程 2. 进程优先级2.1 基本概念2.2 查…...

[免费]微信小程序(图书馆)自习室座位预约管理系统(SpringBoot后端+Vue管理端)(高级版)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序(图书馆)自习室座位预约管理系统(SpringBoot后端Vue管理端)(高级版),分享下哈。 项目视频演示 【免费】微信小程序(图书馆)自习室座位预约管理系统(SpringBoot后端Vue管理端)(高级版…...

你使用过哪些 Java 并发工具类?
你的回答(口语化,面试场景) 面试官:你使用过哪些 Java 并发工具类? 你: 好的,我结合项目经验来说说常用的并发工具类: CountDownLatch 作用:等所有线程就绪后再触发任务…...

模板方法模式的C++实现示例
核心思想 模板方法设计模式是一种行为设计模式,它定义了一个算法的框架,并将某些步骤的具体实现延迟到子类中。通过这种方式,模板方法模式允许子类在不改变算法结构的情况下重新定义算法的某些步骤。 模板方法模式的核心在于: …...

国产编辑器EverEdit - 脚本(解锁文本编辑的无限可能)
1 脚本 1.1 应用场景 脚本是一种功能扩展代码,用于提供一些编辑器通用功能提供不了的功能,帮助用户在特定工作场景下提高工作效率,几乎所有主流的编辑器、IDE都支持脚本。 EverEdit的脚本支持js(语法与javascript类似)、VBScript两种编程…...

越早越好!8 个反直觉的金钱真相|金钱心理学
很多人都追求财富自由,但成功的人少之又少。 这可能是因为,人们往往忽略了一些金钱的真相和常识。 01 金钱常识 & 真相 为了构建健康的金钱观,我读了一本有点反直觉,有点像鸡汤,但都是财富真相的书。 来自 Morg…...

linux docker相关指令
1、镜像操作 0)、搜索:docker search 镜像名称 1)、拉取:docker pull 2)、推送:docker push 3)、查看:docker images 4)、查看所有镜像ID:d…...

实时采集到的语音进行语音识别
要在.NET Framework 4.8中使用C#实现离线实时语音识别,可以使用开源库Vosk(支持离线ASR)配合音频处理库NAudio。 步骤 1:安装依赖库 1.1. 安装NuGet包: - Install-Package NAudio(处理音频输入)…...

Ollama 本地部署 DeepSeek R1 及 Python 运行 open-webui 界面(windows)
DeepSeek R1 ollama open-webui 本地部署(windows) DeepSeek-R1本地部署配置要求 Github地址:https://github.com/deepseek-ai/DeepSeek-R1?tabreadme-ov-file 模型规模最低 GPU 显存推荐 GPU 型号纯 CPU 内存需求适用场景1.5B4GBRTX 3…...

牛客周赛:84:C:JAVA
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 \hspace{15pt}本题为《D.小红的陡峭值(三)》的简单版本,两题的唯一区别在于本题的数据范围更小。 \hspace{15pt}小红定义一个字符串的陡峭值为&a…...

5. 前后端实现文件上传与解析
1. 说明 在实际开发中,比较常见的一个功能是需要在前端页面中选择系统中的某个文件上传到服务器中进行解析,解析后的文件内容可以用来在服务器中当作参数,或者传递给其它组件使用,或者需要存储到数据库中。所以本文就提供一种方式…...

SpringBoot 接入 豆包 火山方舟大模型
火山方舟控制台 开通模型推理、知识库 应用入口; 文档中心 各类接口说明及SDK 获取; 向量数据库VikingDB 文档 下翻找到有java操作案例; 实现目标功能效果: 通过SDK调用 豆包大模型,在代码内实现问答的效果…...

IDEA接入阿里云百炼中免费的通义千问[2025版]
安装deepseek 上一篇文章IDEA安装deepseek最新教程2025中说明了怎么用idea安装codeGPT插件,并接入DeepSeek,无奈接入的官方api已经不能使用了,所以我们尝试从其他地方接入 阿里云百炼https://bailian.console.aliyun.com/ 阿里云百炼是阿…...

下载kali linux遇到的一些问题
kali官网:kali官网跳转 问题一:未启动VM Service VMware Workstation 未能启动 VMware Authorization Service。您可以尝试手动启动VMware Authorization Service。如果此问题仍然存在,请联系VMware 支持部门。 解决办法: 步骤1…...

常见排序算法深度评测:从原理到10万级数据实战
常见排序算法深度评测:从原理到10万级数据实战 摘要 本文系统解析冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序和基数排序8种经典算法,通过C语言实现10万随机数排序并统计耗时。测试显示:快速排序综合性能最优&…...

Scaled_dot_product_attention(SDPA)使用详解
在学习huggingFace的Transformer库时,我们不可避免会遇到scaled_dot_product_attention(SDPA)这个函数,它被用来加速大模型的Attention计算,本文就详细介绍一下它的使用方法,核心内容主要参考了torch.nn.functional中该函数的注释…...

Linux练级宝典->Linux进程概念介绍
目录 进程基本概念 PCB概念 task_struct tack_struct内容分类 PID和PPID fork函数创建子进程 进程优先级概念 4个名词 进程地址空间 进程地址空间的意义 内核进程调度队列 优先级 活动队列 过期队列 进程基本概念 一个正在执行的程序。担当分配系统资源的实体&#…...

OpenHarmony 5.0 mpegts封装的H265视频播放失败的解决方案
问题现象 OpenHarmony 5.0版本使用AVPlayer播放mpegts封装格式的H.265(HEVC)编码格式的视频时出现报错导致播放失败 问题原因 OpenHarmony 5.0版本AVPlayer播放器使用histreamer引擎,因为 libav_codec_hevc_parser.z.so 动态库未开源导致H265编码格式视频解析不到…...

Qt从入门到入土(九) -model/view(模型/视图)框架
简介 Qt的模型/视图(Model/View)架构是一种用于分离数据处理和用户界面展示的设计模式。它允许开发者将数据存储和管理(模型)与数据的显示和交互(视图)解耦,从而提高代码的可维护性和可扩展性。…...

缓存之美:Guava Cache 相比于 Caffeine 差在哪里?
大家好,我是 方圆。本文将结合 Guava Cache 的源码来分析它的实现原理,并阐述它相比于 Caffeine Cache 在性能上的劣势。为了让大家对 Guava Cache 理解起来更容易,我们还是在开篇介绍它的原理: Guava Cache 通过分段(…...

[漏洞篇]XSS漏洞详解
[漏洞篇]XSS漏洞 一、 介绍 概念 XSS:通过JS达到攻击效果 XSS全称跨站脚本(Cross Site Scripting),为避免与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故缩写为XSS。这是一种将任意 Javascript 代码插入到其他Web用户页面里执行以…...

【Leetcode 每日一题】2269. 找到一个数字的 K 美丽值
问题背景 一个整数 n u m num num 的 k k k 美丽值定义为 n u m num num 中符合以下条件的 子字符串 数目: 子字符串长度为 k k k。子字符串能整除 n u m num num。 给你整数 n u m num num 和 k k k,请你返回 n u m num num 的 k k k 美丽值…...

IO进程线程(线程)
作业 1.创建两个线程,分支线程1拷贝文件的前一部分,分支线程2拷贝文件的后一部分 2.创建三个线程,实现线程A打印A,线程B打印B,线程C打印C;重复打印顺序ABC。 信号量实现: 条件变量实现&#x…...

1-002:MySQL InnoDB引擎中的聚簇索引和非聚簇索引有什么区别?
在 MySQL InnoDB 存储引擎 中,索引主要分为 聚簇索引(Clustered Index) 和 非聚簇索引(Secondary Index)。它们的主要区别如下: 1. 聚簇索引(Clustered Index) 定义 聚簇索引是表数…...

tomcat单机多实例部署
一、部署方法 多实例可以运行多个不同的应用,也可以运行相同的应用,类似于虚拟主机,但是他可以做负载均衡。 方式一: 把tomcat的主目录挨个复制,然后把每台主机的端口给改掉就行了。 优点是最简单最直接,…...

论文阅读分享——UMDF(AAAI-24)
概述 题目:A Unified Self-Distillation Framework for Multimodal Sentiment Analysis with Uncertain Missing Modalities 发表:The Thirty-Eighth AAAI Conference on Artificial Intelligence (AAAI-24) 年份:2024 Github:暂…...

解决asp.net mvc发布到iis下安全问题
解决asp.net mvc发布到iis下安全问题 环境信息1.The web/application server is leaking version information via the "Server" HTTP response2.确保您的Web服务器、应用程序服务器、负载均衡器等已配置为强制执行Strict-Transport-Security。3.在HTML提交表单中找不…...

概念|RabbitMQ 消息生命周期 待消费的消息和待应答的消息有什么区别
目录 消息生命周期 一、消息创建与发布阶段 二、消息路由与存储阶段 三、消息存活与过期阶段 四、消息投递与消费阶段 五、消息生命周期终止 关键配置建议 待消费的消息和待应答的消息 一、待消费的消息(Unconsumed Messages) 二、待应答的消息…...

springboot三层架构详细讲解
目录 springBoot三层架构 0.简介1.各层架构 1.1 Controller层1.2 Service层1.3 ServiceImpl1.4 Mapper1.5 Entity1.6 Mapper.xml 2.各层之间的联系 2.1 Controller 与 Service2.2 Service 与 ServiceImpl2.3 Service 与 Mapper2.4 Mapper 与 Mapper.xml2.5 Service 与 Entity2…...

2025最新群智能优化算法:云漂移优化(Cloud Drift Optimization,CDO)算法求解23个经典函数测试集,MATLAB
一、云漂移优化算法 云漂移优化(Cloud Drift Optimization,CDO)算法是2025年提出的一种受自然现象启发的元启发式算法,它模拟云在大气中漂移的动态行为来解决复杂的优化问题。云在大气中受到各种大气力的影响,其粒子的…...