当前位置: 首页 > news >正文

【Linux】进程状态与进程优先级

目录

  • 一.进程状态
    • 1.阻塞:
    • 2.挂起:
      • 具体情况
    • 3.具体操作系统状态变化
      • R:运行状态(running)
      • S:休眠状态(sleeping)
      • D:磁盘休眠状态(Disk sleep)
      • T:暂停状态(stopped)
        • 暂停进程
        • 继续进程
      • t:追踪暂停状态(tracing stop)
      • X:死亡状态(dead)
      • Z:僵尸状态(zombie)
        • 僵尸进程的危害
    • 4.进程状态总结
  • 二.孤儿进程
  • 三.进程优先级
    • 1查看系统进程
      • PRI 和 NI
      • 注意
    • 2.调整优先级
  • 四.Linux系统中kill指令常见信号
  • 五.补充概念

多任务系统: 操作系统接管了所以的硬件资源,并且本身运行在一个受保护的的级别。所有的应用程序都以进程 的方式运行在比操作系统权限更低的级别,每个进程都有自己独立的地址空间,使得进程之间的地址空间相互隔离。CPU由操作系统统一进行分配,每个进程根据检测优先级的高低都有机会得到CPU,但是,如果允许时间超出一定的时间,操作系统会暂停该进程,将CPU资源分配给其他等待的进程。这种CPU的分配方式即所谓的抢占式 ,操作系统可以强制剥夺CPU资源并且分配给它认为目前最需要的进程。如果操作系统分配给每个进程的时间都很短,即CPU在多个进程间快速地切换,从而造成了很多进程都在同时运行的假象。目前几乎所有现代的操作系统都会采用这种方式,比如我们熟悉的 UNIX、Linux、Windows NT,以及Mac OS X等留下的操作系统。 ---- 《程序员的自我修养》

一.进程状态

每个人在某一刻都有自己的状态,比如你现在在看这篇文章,那你的状态就是学习,别人在睡觉,那状态就是休息,而进程也有自己的状态,不同的状态展现了进程当前的情况。

我们先来了解一个尝试,比方说,你现在正在使用抖音看直播,那对应的进行是否一直在CPU上运行呢?

答:并不是。

假如CPU上一直运行看直播这个进程,那其它的进程就没有办法使用CPU完成自己的程序,我们若是还想去下载一个软件、使用微信与朋友聊天或干其他的事情那只能等这个进程执行完后再去做,可事实并非如此,我们可以在刷抖音的同时下载软件,并在微信上去聊天,这是因为CPU可以在多个进程快速切换(CPU先运行一个进程之后在切换其他进程,如此运行进程,让每个进程都运行一点,在一个时间段内,代码都得以推进。CPU运行速度极快,我们的感官是感受不到的),造成多个进程同时运行的假象,这也就是我们文章开头提到的多任务系统

至此,我们了解到,进程在运行的时候是可以被操作系统管理调度的,那凭什么某个进程在某一刻可以被CPU运行,而其它进程不被运行呢?

这就取决于进程状态,进程不同的状态就体现了进程当前能做什么事情,不能做什么事情。所以进程处在什么样的位置取决于进程自己。

接下来,我们在来理解操作系统中状态的两个概念,目前具体的操作系统中进程的状态大都衍生于这两个概念,掌握之后再来看其他的状态可以变的轻松一点:

1.阻塞:

进程因为等待某种条件就绪,而导致的一种不推进的状态。

想要理解这个概念,我们需要知道,操作系统是如何看看待资源(磁盘、键盘、网卡、显卡等等)的。

首先,操作系统想要了解并调用某个计算机中的成员是通过 先描述,后组织 的方式,比如说进程,就是操作系统通过PCB(结构体,其中为程序的特性,Linux操作系统的PCB叫做task_struct )将运行到内存的程序变为一个个对象(一个进程还包括对应内存的代码和数据,我们这里不讨论这个),通过链表的数据结构,将对象存入,接着就是对链表的增删查改或其他操作,来管理进程。

其次,操作系统也是通过先描述、后组织 的方法来应对计算机资源的,将这些资源通过类似的结构体的形式创建出一个个对象,这些对象代表的就是一个个计算机资源,也将这些对象通过链表的数据结构,通过增删查改等方式管理对象从而管理计算机资源。

了解了这些基础,我们在通过两个例子,来看一下什么是进程的阻塞状态

  1. 当我们正在下载一款软件,但是突然断网了

    当我们正在下载这款软件时,下载软件这个进程是在使用CPU运行的

    在这里插入图片描述

    当网线突然断掉,该进程就缺少了网络资源,CPU无法在进行运行该进程,于是操作系统便将其从CPU特定的某种队列 中将其拿出,放在了网络所对应的资源处(网卡)所维护的队列中,进行排队,等待网卡为该进程提供资源。

    在这里插入图片描述

    此时进程是不被CPU调度的,在用户看来就是卡住了,而这种等待资源的状态就是阻塞

  2. 我们使用C语言编写一段程序,其中调用scanf函数需要通过键盘输入一个值

    同理,在运行到scanf函数前,该程序所对应的进程通过CPU的运行来推进 代码的运行,但当运行到scamf函数需要从键盘输入值时,CPU就无法在将进程运行下去,此时它需要来自键盘的资源,操作系统也将其放到了所对应的资源所维护的队列中,进行排队。

    此时CPU不在运行该进程,在用户看来这也就是程序卡了,而该进程的状态即为阻塞

总结:

  1. 阻塞就是进程卡了,不被CPU调用
  2. 阻塞一定是在等待某种资源,等待占有磁盘、网卡、显卡等各种外设
  3. 为什么阻塞?进程要通过等待的方式,等具体的资源被别人用完后,在被自己使用
  4. 阻塞:就是等待某种资源的过程
  5. PCB(描述进程的PCB结构体对象)可以被维护在不同的队列中(不只是CPU)

注意: CPU切换运行进程,这些进程都是可以被CPU调用的,阻塞是一个进程缺少一种或多种资源从而停止被调用,转去获取资源。

2.挂起:

内存中只存储进程的PCB创建出的对象,而没有对应的代码和数据时,此时进程的状态就是挂起

当一个程序被加载到内存,操作系统将其以进程的形式运行后,在内存中,该进程包括PCB所创建的对象和对应的代码和数据,由CPU运行进程,推进代码的运行,当其缺少一种或多种资源后,将其从CPU特定的某种队列中提取,放入对应资源所在的队列,此时进程的状态为阻塞

在这里插入图片描述

此时的进程处在阻塞的状态,需要等待资源,这就导致对应的代码和数据 ,占用着内存,却没有什么作用,此时操作系统会考虑将该代码和数据 转移到磁盘中,只保留进程的PCB,使内存可以存储更多需要处理的数据,此时内存中对应进程的状态就是挂起 (严格意义上讲,这种状态又叫阻塞挂起状态

在这里插入图片描述

具体情况

当进程获取资源后再从磁盘内将对应的代码和数据转移到内存,重新调用CPU运行进程。

若当内存中有200个进程,其中只有30个使用CPU运行,推动代码运行,剩余的170个都处于阻塞状态,操作系统就会考虑将那170个进程中部分的代码和数据转移到磁盘,释放内存空间,提高内存利用率。

3.具体操作系统状态变化

上面讲的是操作系统状态的理论部分,是宏观上操作系统状态最核心的概念,这些理论在任何一个操作系统中都是正确的,接下来,我们脱离这些抽象的东西,来看一下,在Linux系统中,进程具体的状态是如何变化的。

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务,task表示任务,在Linux操作系统中PCB是task_struct,而在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 */
};

首先,在Linux中,进程的一部分是由task_struct结构体创建的对象,而task_struct是一个结构体,内部会包含各种属性,其中就有状态。

struct task_struct
{int status;//进程状态的变化就是修改status整数//其他属性
}

R:运行状态(running)

并不意为着进程一定在运行中,它表示进程要么是在运行中要么在运行队列(队列由操作系统自己维护)里。

其模拟状态和特点如下图:
在这里插入图片描述

下面,我们通过在Linux环境下运行一段代码来查看进程的状态(创建下面两个文件并编写对应的代码)

test.c

在这里插入图片描述

makefile

在这里插入图片描述

调用下面的指令,查看进程信息

ps axj | head -n1 && ps axj | grep mytest | grep -v grep

首先执行make指令,生成可执行程序,然后使用复制的会话运行程序

如下图,我们将程序运行,程序进入死循环,然后查看进程的信息

在这里插入图片描述

我们看到,查看到的进程的状态大多都是S+,只有一个是R+(这里先不管+,我们只看字母,后面会说的)

首先,S是睡眠状态,是阻塞状态的一种

这是因为,程序需要进行循环打印,需要频繁的访问显示器设备,而我是在在Xshell中使用centos7云服务器,其主机可能在离我千里之外的地方,printf打印结果想要出现在我的显示器上,需要有访问外设的行为 ,这导致进程在运行的过程中需要显示器资源,此时就处于阻塞 状态。

CPU的运行速度是很快的,而等待外设时间相对于CPU就慢的多,所以我们查看进程,看到大多数时候都处于S 阻塞状态,很少出现R 状态。

我们将test.c 文件修改如下,之后运行查看结果

在这里插入图片描述

之后在使用make指令,生成可执行文件,之后运行该文件,查看其进程状态

在这里插入图片描述

我们看到,此处查看进程,所有的结果表明该进程的状态为R

此时运行该代码,不需要任何资源,只是在用CPU进行运行,所以我们看到它的状态一直是R

S:休眠状态(sleeping)

在Linux系统当作,S休眠状态又叫可中断休眠 (可以被终止,可以暂停),意为着进程在等待事件的完成,本质就是阻塞状态。

我们将test.c 文件修改如下:

在这里插入图片描述

之后使用make指令,创建对应可执行文件,然后运行该文件

在这里插入图片描述

我们看到此时所处的状态为S状态(+ 之后讲)

此时进程运行到scanf,需要输入数据,进程需要键盘提供资源,该进程的task_struct对象在键盘资源所对应的队列中排队等待资源,处于阻塞状态

在这里插入图片描述

  • 此时可以使用Ctrl + c或其它命令人为的中断该进程,所以S 休眠状态,为可中断休眠。(了解)

D:磁盘休眠状态(Disk sleep)

在Linux系统中也叫做不可中断休眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

这个状态主要应对特殊的情况,这里不好演示,我们通过下面的例子来讲解:

一个进程在正常的运行,某一刻它需要将一段数据存储在磁盘的某个位置,而磁盘的运行速度比较慢,它在存储的这段时间,该进程无法在继续推进代码,只能等数据存储完成,此时这个进程的task_struct在磁盘对应的队列中排队,CPU去执行其他的进程。

如果是正常的情况,当磁盘将数据存储后,该进程继续使用CPU运行,但在该进程处于阻塞状态时,内存已经无法在存储其他的数据,操作系统此时就会想办法释放一定内存空间内不被使用的数据,释放部分内存,而正在S 状态的进程就会被操作系统杀掉,若在进程被杀掉后磁盘存储数据时发生了一定问题(比如磁盘空间不足),磁盘无法解决他就会返回给对应的进程,告诉它数据存储失败,在由进程告诉用户存储数据失败,但此时进程已经被杀死,那磁盘只能拿着数据在风中凌乱

那对这些数据磁盘该如何处理,丢弃吗?若数据是用户的账号密码或银行的转账信息呢,自然不能丢。

保留下来呢?对应的进程又没办法联系,不知道保留在哪里。

首先这种情况是可能存在的,而且这种情况十分危险的,想要解决它只能让操作系统不去杀死进程,这就需要为该进程复以新的状态D 状态。

  • D状态是磁盘无法急时存数数据造成的,通常磁盘无法及时存储数据都是因为磁盘已经负担很重,几乎面临奔溃,而磁盘都是这样,内存同样差不多(内存中会存在大量的请求需要磁盘处理),为了防止数据丢失,D状态因此诞生。
  • D状态下的进程不能被操作系统杀死,只能等待该进程获取对应资源后自己解除该状态(有时候因为D状态的存在关机重启也无法办到,只能切断电源,但数据丢失的损失只能自己承担)。
  • 我们一般遇不到处在D 状态的进程,如果从事系统管理、运维、存储等工作,经常会遇到该状态。

T:暂停状态(stopped)

可以通过发送 SIGSTOP 信号给进程来停止(T)进程(用户想要让一个进程暂停)。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。 T状态也是一种阻塞状态。

  • 在该文章第四个段落下总结有Linux系统中kill指令常见信号

我们将test.c 文件修改如下:

在这里插入图片描述

暂停进程

想要让一个进程处于T状态需要向其发送 SIGSTOP 信号,而该信号是通过kill指令发送如下:

使用kill -l查看 SIGSTOP 信号对应的序号

在这里插入图片描述

对应序号为19,向一个进程传递该信号使用kill -19 进程对应PID的方式。

之后使用make指令,创建对应可执行文件,然后运行该文件,向对应进程发送 SIGSTOP 信号,查看进程状态

在这里插入图片描述

继续进程

若我们要该进程继续运行,需要向前发送 SIGCONT 信号,同样使用kill指令发送

使用kill -l查看 SIGCONT 信号对应的序号

在这里插入图片描述

对应序号为18,向一个进程传递该信号使用kill -18 进程对应PID的方式。

在这里插入图片描述

我们看到,进行继续运行,此时的状态为S 后面的**+** 没有了

在这里插入图片描述

其中进程状态后有**+** 表示进程在前台运行,这样的状态下,我们可以使用Ctrl + c 来关闭进程,

而没有**+** 表示进程在后台运行,此时我们可以正常执行shell指令,但不能在使用Ctrl + c 关闭进程

在这里插入图片描述

想要关闭该状态下的进程,我们有两种方法,一是需要向该进程发送 SIGKILL 信号

在这里插入图片描述

对应的序号为9,向一个进程传递该信号使用kill -18 进程对应PID的方式。(在我的操作系统中需要在使用Ctrl + c 才能看到命令行,而有的是不用的)

在这里插入图片描述

二是直接使用下面的指令来关闭该进程

killall 进程名
  • 注意:进程名不是PID,而是执行的可执行文件名

注意:

  1. 对于暂停状态,用户可以将进程暂停而操作系统也可以将一个状态,比方说当用户出现一些非法操作时,操作系统就会暂停对应的进程
  2. S 和 T 的区别在于,S是进程在等待资源是真正的阻塞状态,T是停止进程的某些行为。

t:追踪暂停状态(tracing stop)

在我们调试代码时,让程序在断点处停止,本质就是暂停状态,而这种状态就是追踪式暂停。

如下图,我们使用gdb设置断点并运行,之后查看进程的状态

在这里插入图片描述

一个进程为gdb调试对应可执行文件的进程,第二个为我们写的程序对应的可执行文件在内存中对应的进程,此时这个进程的状态为t 表示该进程为暂停状态

所以我们打断点,调试时在断点处暂停,本质就是gdb向目标进程发生暂停信息,使其暂停

X:死亡状态(dead)

这个状态表面进程已经死亡,进程中的PCB、代码和数据都已经被回收,你不会在任务列表里看到这个状态。

虽然这个状态我们看不到,但有一个和它相关的状态,即Z状态–僵尸状态

Z:僵尸状态(zombie)

进程是干什么的,进程是为我们解决事情的,既然是解决事情,那必然会有结果的产生,我们要不关心结果,要不不关心,不关心结果,进程运行完也就完了,要是我们关心结果呢?

  1. 僵尸进程是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码(使用wait()系统调用获取。返回代码即返回时的状态,是运行成功后正常结束还是被OS杀死或是其它)时就会产生僵尸进程。(一个进程具有独立性,我们没有办法将其中的数据返回给父进程)
  2. 僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
  3. 只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

我们修改test.c文件如下

在这里插入图片描述

该程序运行后会产生两个进程,一个父进程,一个子进程,我们杀死子进程,父进程是不会读取到子进程状态的,此时子进程就属于僵尸状态,如下:

在这里插入图片描述

我们看到,子进程被杀死后,是不会直接被回收的,而是由父进程接收,状态为Z ,方便获取返回代码

僵尸进程的危害

  • 进程退出后父进程没有获取其返回代码,那该进程的僵尸状态就会一直维护下去,不论父进程想不想知道该进程的结果是怎么样的,但子进程必须要有告诉它的准备。(操作系统无法确定父进程是否需要知道子进程运行的结果,所以会出现僵尸进程保留结果)
  • 僵尸状态就是用数据维护,它也属于基本信息,保存在task_struct(PCB)中,要是僵尸状态一直不解除,那PCB就要一直维护。
  • 如果一个父进程创建了很多子进程,但就是不回收,那就造成了资源的浪费,因为数据结构对象本身就是要占用内存的,是要在内存的某个位置进行开辟空间,这就造成了内存泄漏。

4.进程状态总结

在这里插入图片描述

二.孤儿进程

  • 父进程先退出,子进程就称为“孤儿进程
  • 孤儿进程被1号init进程领养,由init进程回收

我们通过下面的实验来证明孤儿进程的情况

myprocess.c 文件中编写如下程序

在这里插入图片描述

该程序功能为创建子进程,并于父进程一起运行,当父进程在循环内运行6次后便会退出,只剩下子进程,此时我们在来查看子进程的情况

makefile 文件中编写如下代码

在这里插入图片描述

通过make指令快速创建可执行文件myprocess ,其中**$@** 表示依赖关系中冒号左边的目标myprocess$^ 表示依赖关系中冒号右边的依赖myprocess.c

当生成的可执行文件运行后,使用下面的指令,时其在页面循环打印出对应的进程情况

while :; do ps axj | head -n1 && ps axj | grep -v grep | grep myprocess; sleep 1; echo " -----------"; done

执行结果如下图:

在这里插入图片描述

通过上面的图画,我们看到,当父进程退出后,只有子进程在运行,而子进程对应的PPID由原本的5890变为1

在这里插入图片描述

我们知道一个进程退出后,若其父进程没有接收其返回代码,该进程会变为僵尸进程,而我们写的代码运行后产生了父子进程,父进程循环6此后退出,为什么没有变为僵尸进程呢?

首先,父进程5890(PID)也是有父进程的,它的父进程就是bash(命令行解释器),虽然父进程5890没有接收其子进程的返回值(我们没有写让父进程5809接收),但是bash3200却自动接收了父进程5890的返回代码,处理其僵尸状态,使进程5890被回收。

其次,我们看到,当父进程5809退出后,子进程5891由进程1领养,这个进程1就是init,也可以看作是操作系统领养了子进程5891,这种被领养的进程就称为孤儿进程

那为什么父进程退出后,其子进程变为孤儿进程被操作系统领养呢?

如果不领养,这个子进程就没有父进程,在其退出是,就会变为僵尸进程,并且没有父进程将其回收,造成内存泄漏,所以子进程必须被领养。

注意:

父进程退出后,子进程变为孤儿进程,其的状态变为S 没有**+** ,表示其在后台运行,想要杀掉该进程只能是否两种方法,来完成对该进程的退出

//方法1
kill -9 进程PID//方法2
killall 进程名

注意:方法2中进程名表示运行的可执行文件名,不是PID

三.进程优先级

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

为什么要有优先级?

因为CPU资源有限,一台普通的电脑上CPU是4~8个,而要执行的进程少说也要20个以上,所以要让重要的进程优先执行,保证利益的最大化。

1查看系统进程

在Linux或unix系统中,用ps -al指令则会类似输出以下几个内容:

在这里插入图片描述

其中,重要信息如下:

  • UID:代表执行者的身份,用户标识符

在这里插入图片描述

如上图,当我们查看当前文件下的信息时,可以看到两种表示文件所属用户或所属组的方式,其中,用户使用用户名来标识彼此,而操作系统使用用户标识符(UID,数字)来标识用户

  • PID:代表这个进程的代号
  • PPID:代表这个进程是由那个进程发展衍生而来的,亦即父进程的代号
  • PRI:代表这个进程可被执行的优先级,其值越小越早被执行
  • NI:代表这个进程的nice值

PRI 和 NI

  • PRI(priority),即进程的优先级,就是程序被CPU执行的先后顺序,此值越小进程的优先级越高
    • 每个普通进程的PRI默认值为80
  • NI(nice),表示进程可被执行的优先级的修正数值
    • nice值默认基本都是0
  • PRI值越小越快被执行,加入nice值后,将会使得PRI变为:PRI = 80 + nice
  • 当nice为负数时,该进程的优先级将会变小,即期优先级会变高,则其越快被执行
  • 调整优先级,在Linux下,就是调整进程的nice值
  • nice其取值范围是**-20~19** ,一共40个级别(一般不会去改nice值,一直使用默认值)
    • nice值之所以有范围,为了防止优先级被调整过度,时每次先使用CPU都是同一批进程,其它进程没办法更好的调度执行,所以过渡器 不允许过度调整nice值
    • 调度器主要功能:较均衡的让每个进程都可以使用CPU推进代码,而不能使一个或几个进程产生偏差
    • 所以,优先级对于我们来说并不是很重要,我们一般写代码也几乎不回去调整优先级

注意

  • 进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。
  • 可将nice理解为是进程优先级的修正数据

2.调整优先级

调整方法非常多,可以使用代码去调整,也可以用指令去调,这里我们讲一下使用top去调整进程的优先级

首先,我们编写如下test.c 文件

在这里插入图片描述

修改makefile 如下

在这里插入图片描述

使用make mytest指令生成可执行文件mytest,之后按照下面的步骤做

  1. 执行该文件
  2. 使用ps -la查看对应进程的PID
  3. 使用top指令打开top
  4. 进入top后,按“r”
  5. 输入进程PID,回车
  6. 输入需要调整的nice值,回车
  7. 按q退出top

在这里插入图片描述

  • 如果调整的nice值过大,那调整的值默认为19
  • 如果调整的nice值过小,那调整值默认为-20
  • 每次修改调整值,最终的PRI都是80加上nice值

四.Linux系统中kill指令常见信号

编号名称功能快捷键
2SITINT程序终止信号,用于通知前台终止进程Ctrl+c
3SIGQUIT与SIGINT相似,进程终止后会生成文件coreCtrl+\
9SIGKILL强行终止某个进程,该进程不能被封锁
18SIGCONT恢复执行被SIGSTOP或SIGTSTP信号暂停的进程
19SIGSTOP通知操作系统停止进程的运行,该信号不可忽略
20SIGTSTP暂停进程,但该信号可以被处理和忽略Ctrl+z

五.补充概念

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

相关文章:

【Linux】进程状态与进程优先级

目录一.进程状态1.阻塞:2.挂起:具体情况3.具体操作系统状态变化R:运行状态(running)S:休眠状态(sleeping)D:磁盘休眠状态(Disk sleep)T:暂停状态(stopped)暂停进程继续进程t:追踪暂停状态(traci…...

Python+Qt生日提醒

PythonQt生日提醒如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01;前言这篇博客针对<<PythonQt生日提醒>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与应用推荐首选。文章目…...

第二章 编写MBR主引导记录

主引导记录&#xff08;MBR&#xff0c;Master Boot Record&#xff09;是采用MBR分区表的硬盘的第一个扇区&#xff0c;即C/H/S地址的0柱面0磁头1扇区&#xff0c;也叫做MBR扇区 计算机的启动过程 为什么程序要载入内存 CPU的硬件电路被设计成只能运行处于内存中的程序&…...

Android 9.0 仿ios的hotseat效果修改hotseat样式

1.概述 在9.0的系统rom定制化的产品中,在launcher3的定制化需求中,有很多功能需求点需要开发,在对一下ui的定制化的过程中,会参考ios的样式进行定制化,所以最近项目需求 要求仿ios的hotseat的样式来进行产品的定制,开发一款仿ios的hotseat,所以需要对hotseat进行分析,然…...

量化私募投资百亿头部量化私募企业在招岗位:AI算法工程师21/22/23届,校招/秋招/社招都看年base60-200万

量化私募投资百亿头部量化私募企业在招岗位:AI算法工程师21/22/23届&#xff0c;校招/秋招/社招都看年base60-200万bonuscut965制度应届需要985本硕博有3年以上相关ai算法经验可放宽学历"岗位职责&#xff1a;base 北京 上海 杭州 深圳1. 利用机器学习、深度学习和人工智能…...

百度西交大大数据菁英班目标检测竞赛

来源&#xff1a;投稿 作者&#xff1a;LSC 编辑&#xff1a;学姐 数据介绍 数据集共包括40000张训练图像和1000张测试图像&#xff0c;每张训练图像对应xml标注文件&#xff1a; 共包含3类&#xff1a;0:head, 1:helmet, 2:person。 提交格式要求&#xff0c;提交名为pred_r…...

Redisson实现分布式锁

目录Redisson简介Redisson实现分布式锁步骤引入依赖application.ymlRedisson 配置类Redisson分布式锁实现Redisson简介 Redis 是最流行的 NoSQL 数据库解决方案之一&#xff0c;而 Java 是世界上最流行&#xff08;注意&#xff0c;没有说“最好”&#xff09;的编程语言之一。…...

【HID基础知识】

蓝牙HID基础知识 一&#xff1a;定义 HID是Human Interface Device的缩写&#xff0c;由其名称可以了解HID设备是直接与人交互的设备&#xff0c;例如键盘、鼠标与游戏手柄等。 蓝牙HID 是属于蓝牙协议里面的一个profile, 不管在蓝牙2.0 2.1 3.0还是4.0&#xff0c;5.0的蓝牙中…...

工赋开发者社区 | 工业数字孪生:西门子工业网络与设备虚拟调试案例(TIA+MCD+SINETPLAN)

PART1案例背景及基本情况新生产系统的设计和实施通常是耗时且高成本的过程&#xff0c;完成设计、采购、安装后&#xff0c;在移交生产运行之前还需要一个阶段&#xff0c;即调试阶段。如果在开发过程中的任何地方出现了错误而没有被发现&#xff0c;那么每个开发阶段的错误成本…...

将闲置的Ipad作为Windows的副屏(Twomon SE)

目录一、前言二、方法第一步 安装软件第二步 使用步骤三、注意一、前言 在看网课的时候&#xff0c;总有种不得劲的感觉&#xff0c;来来回回的切换就很糟心~~无意间看见闲置的板砖&#xff08;Ipad&#xff09;&#xff0c;计上心来-- _ – 期间也尝试过免费的软件&#xff…...

浮点数在内存中的存储——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容是浮点数在内存中的存储&#xff0c;昨天我们已经写过了整型在内存中的存储&#xff0c;那么&#xff0c;浮点数在内存中是怎样存储的呢&#xff1f;现在&#xff0c;就让我们进入浮点数在内存中的存储的世界吧…...

华为OD机试 C++ 实现 - 租车骑绿岛

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…...

Spring Cloud Nacos源码讲解(三)- Nacos客户端实例注册源码分析

Nacos客户端实例注册源码分析 实例客户端注册入口 流程图&#xff1a; 实际上我们在真实的生产环境中&#xff0c;我们要让某一个服务注册到Nacos中&#xff0c;我们首先要引入一个依赖&#xff1a; <dependency><groupId>com.alibaba.cloud</groupId><…...

位运算(C/C++)

1. 基础知识 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。比如&#xff0c;and运算本来是一个逻辑运算符&#xff0c;但整数与整数之间也可以进行and运算。举个例子&#xff0c;6的二进制是110&#xff0c;11的二…...

哈希表题目:设计哈希映射

文章目录题目标题和出处难度题目描述要求示例数据范围前言解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题&#xff1a;设计哈希映射 出处&#xff1a;706. 设计哈希映射 难度 3 级 题目描述 要求 不使用任何内建的哈希表库设计一个…...

​力扣解法汇总1238. 循环码排列

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a; 力扣 描述&#xff1a; 给你两个整数 n 和 start。你的任务是返回任意 (0,1,2,,...,2^n-1) 的排列 p&…...

[数据结构]时间复杂度与空间复杂度

[数据结构]时间复杂度与空间复杂度 如何衡量一个算法的好坏 long long Fib(int N) {if(N < 3)return 1;return Fib(N-1) Fib(N-2); } 这是一个求斐波那契数列的函数&#xff0c;使用递归的方法求得&#xff0c;虽然代码看起来很简洁&#xff0c;但是简洁真的就好吗&#…...

Codeforces Round #848 (Div. 2)(A~D)

A. Flip Flop Sum给出一个只有1和-1的数组&#xff0c;修改一对相邻的数&#xff0c;将它们变为对应的相反数&#xff0c;修改完后数组的和最大是多少。思路&#xff1a;最优的情况是修改一对-1&#xff0c;其次是一个1一个-1&#xff0c;否则修改两个1。AC Code&#xff1a;#i…...

第十三届蓝桥杯Java B 组国赛 C 题——左移右移(AC)

目录1.左移右移1.题目描述2.输入格式3.输出格式4.样例输入5.样例输出6.数据范围6.原题链接2.解题思路3.Ac_code1.左移右移 1.题目描述 小蓝有一个长度为 NNN 的数组, 初始时从左到右依次是 1,2,3,…N1,2,3, \ldots N1,2,3,…N 。 之后小蓝对这个数组进行了 MMM 次操作, 每次…...

第14篇:系列二—Java抽象类/接口/枚举

目录 1、继承的定义(Inheritance) 2、继承的优点 2.1 易维护性 2.2 复用性 2.3 条理性...

深入浅出C++ ——哈希

文章目录前言一、unordered系列关联式容器1. unordered_map2. unordered_set二、哈希1. 哈希概念2. 哈希冲突3. 哈希函数4. 哈希冲突解决方法三、模拟实现unordered系列容器1. 哈希表的改造2. 模拟实现 unordered_set3. 模拟实现 unordered_map前言 在C11中&#xff0c;STL又提…...

Tina_Linux_系统裁剪_开发指南

文章目录Tina_Linux_系统裁剪_开发指南1 概述2 Tina系统裁剪简介2.1 boot0裁剪2.2 uboot裁剪2.3 内核裁剪2.3.1 删除不使用的功能2.3.2 删除不使用的驱动2.3.3 修改内核源代码2.3.3.1 size工具.2.3.3.2 ksize.py脚本2.3.3.3 nm命令2.3.3.4 kernel压缩方式.2.4 文件系统裁剪.2.4…...

算法刷题打卡第99天:至少在两个数组中出现的值

至少在两个数组中出现的值 难度&#xff1a;简单 给你三个整数数组 nums1、nums2 和 nums3 &#xff0c;请你构造并返回一个 元素各不相同的 数组&#xff0c;且由 至少 在 两个 数组中出现的所有值组成。数组中的元素可以按 任意 顺序排列。 示例 1&#xff1a; 输入&…...

线程池面试题

1. 什么是线程池&#xff1f;为什么要使用线程池&#xff1f; 线程池是一种用于管理线程的技术&#xff0c;它可以在应用程序中重复使用一组线程来执行多个任务。线程池的优点包括提高应用程序的性能和可伸缩性、避免线程创建和销毁的开销、避免线程过多导致系统负担过重等。线…...

【学习笔记】NOIP爆零赛5

说实话是不想补题的。因为每一道题都贼难写&#xff0c;题解又通篇写着显然&#xff0c;然后自己天天搞竞赛又把注意力搞差了&#xff0c;调一道题又调半天&#xff0c;考试的题又难的要死 不会正解 &#xff0c;部分分又写挂了 可能心态崩了就是从那场t1t1t1签到题考高精度数位…...

【数据结构】时间复杂度

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;初阶数据结构 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对…...

vector的基本使用

目录 介绍&#xff1a; vector iterator 的使用 增删查改 增&#xff08;push_back insert&#xff09;&#xff1a; 删(pop_back erase)&#xff1a; swap&#xff1a; vector的容量和扩容&#xff1a; 排序&#xff08;sort&#xff09;&#xff1a; 介绍&#xff…...

剑指 Offer 55 - I. 二叉树的深度

摘要 剑指 Offer 55 - I. 二叉树的深度 一、深度优先搜索 如果我们知道了左子树和右子树的最大深度l和r&#xff0c;那么该二叉树的最大深度即为&#xff1a;max(l,r)1。 而左子树和右子树的最大深度又可以以同样的方式进行计算。因此我们可以用「深度优先搜索」的方法来计…...

Bean的生命周期和作用域

Bean的生命周期Bean的执行流程&#xff1a;Bean 执行流程&#xff1a;启动Spring 容器 -> 实例化 Bean&#xff08;分配内存空间&#xff0c;从无到有&#xff09;-> Bean 注册到 Spring 中&#xff08;存操作&#xff09; -> 将 Bean 装配到需要的类中&#xff08;取…...

TestNG和Junit的区别,测试框架该如何选择?

要想知道两个框架的区别&#xff0c;首先分别介绍一下两个框架。 TestNG是一个java中的开源自动化测试框架&#xff0c;其灵感来自JUnit和NUnit&#xff0c;TestNG还涵盖了JUnit4整个核心的功能&#xff0c;但引入了一些新的功能&#xff0c;使其功能更强大&#xff0c;使用更…...