【Linux系统编程】进程状态

news2024/11/28 12:38:58

文章目录

  • 前言
  • 1. 准备工作
  • 2. 阻塞、挂起状态的了解
    • 2.1 阻塞
    • 2.2 挂起
  • 3. 看看Linux内核源代码怎么说
  • 4. R运行状态(running)
  • 5. S休眠状态(sleeping)
  • 6. D不可中断休眠状态
  • 7. T暂停状态(stopped)
  • 8. t 追踪暂停状态 (tracing stop)
  • 9. X死亡状态(dead)
  • 10. Z僵尸状态 (zombie)

前言

在前面的学习中,我们已经学习了进程的概念和基本创建,以及如何通过相关的系统调用创建进程和获取进程标识符。

那为了弄明白正在运行的进程是什么意思,我们需要了解进程的不同状态

1. 准备工作

先问大家一个问题:我们使用一个应用的时候,比如我们打开电脑上的爱奇艺看电影,那在看电影的过程中这个应用对应的进程是否是一直在不停的运行呢?

🆗,那其实呢它并不是一直在不停运行的。
我们来举个极端一点的场景:
假设现在这里只有一个CPU,但是我们同时打开了多个进程,比如QQ、微信、爱奇艺、网易云音乐等,然后浏览器还有一些下载任务。
在这里插入图片描述
那这么多的进程在操作系统内被CPU调度运行的时候呢其实并不是从一个进程运行开始,一直不停直到运行结束的,而是每个进程被CPU运行一会儿,操作系统都会把它从操作系统上拿下来,然后把另一个放上来运行,这样重复的快速交替运行的。
一般呢我们把它叫做基于进程切换的分时操作系统,即不同的进程快速切换交替运行,同一时间段内它们的代码都可以得以推进,使得用户感觉多个应用程序几乎同时在运行,因为我们的感官和CPU的运行速度差的是很大的。

所以进程在运行的时候是可以被操作系统管理和调度的:

那这样的话就涉及一个问题,就是在某个时刻操作系统凭什么调度这个进程,让这个进程在CPU上运行而不是其它的进程呢?

那这就取决于进程状态相关的概念。
那在正式学习进程状态之前,我们先来了解两个概念——阻塞和挂起。

2. 阻塞、挂起状态的了解

2.1 阻塞

那我们先来了解一下阻塞:

阻塞即进程因为正在等待某种条件就绪,而导致的一种不推进(不被调度)的状态。

这样说呢,大家可能不太理解:

比如现在有一个进程被创建了(我们打开一个应用或运行一个程序),但是一直没有被CPU执行,那大家想一下这种情况在我们用户层面看到的是一个什么情况呢?
再比如我们有时候在Windows上启动了好多个程序,就可能会出现“卡”的情况。
那这种情况呢其实就可能是进程太多了,操作系统调度不过来了,目前操作系统正在调度的,就正在运行,没有被调度的,就卡在那了。
所以呢,说成大白话,阻塞就是进程“卡住”了。

再比如呢:

我们下载一些东西的时候,如果出现了断网或者0KB了,那这个时候这个下载的进度条就也卡住了。当然这个卡跟我们上面说的有的不一样。
但是这种情况其实也可以认为是阻塞状态。
所以,我们又得出:
阻塞一定是在等待某种资源

那如何理解这里的等待某种资源呢?

首先这里等待的资源可能是什么呢?
比如:磁盘、网卡、显卡各种外设等。
举个例子:
我们在下载某个东西的时候,突然断网了,那对应的进程就会被设置成阻塞状态了,CPU就不会再继续执行你了,你这个进程就要等到网络好了的时候才会被操作系统调度,被CPU继续执行。
就好比你去银行办理某个业务,办理之前你需要填一个单子,但是此时单子用完了,相应的工作人员去取了,然后你所在的这个柜台的工作人员对你说,那您先去旁边等一会吧,先让后面的人办理它们的业务,等您拿到单子填好之后再来办理您的业务吧。

那现实生活中的等待我们可能很好理解,那你就搬个凳子坐那里等一会呗,可是这里等待某种资源,它具体是如何等待呢?

首先,对于这些资源,操作系统肯定要管理起来,怎么管理的?
先描述,再组织!
这是我们之前讲过的。先搞一个结构体把它们的属性啥的都封装起来,然后在搞一个链表或其它高效的数据结构组织起来。
那进程呢?操作系统里面可能存在很多进程,那也要管理起来,如何管理?
先描述,再组织。
那就是一个task_struct的链表。
那某个进程在等待某种资源的时候呢其实就是把自己的task_struct放到对应资源的等待队列中。
在操作系统中,每个资源对应的描述数据结构通常会包含一个等待队列。这个等待队列用于存储等待该资源的进程或线程。
当一个进程请求某个资源时,如果资源当前不可用,操作系统会将该进程标记为阻塞状态,并将其对应的 PCB(task_struct) 移动到相应资源的等待队列后面。这样,CPU就可以调度其他可执行的进程来继续执行。

2.2 挂起

那下面我们再来了解一下挂起

还是通过一个例子给大家讲解:

假设现在有一个下载任务因为断网进入了阻塞状态
在这里插入图片描述
而此时呢操作系统的内存资源又特别紧张,那此时呢操作系统可能会做这样的事情,就是把这些阻塞状态的进程的代码和数据先交换到磁盘上,因为你这些阻塞的进程不被调度,但是你的代码和数据还放在内存里,那就太占用资源了。
然后等到这些阻塞的进程等待的资源就绪的时候,再把它们的代码和数据交换回内存,然后被CPU运行。
那其中操作系统把某些进程的代码和数据交换到磁盘上,此时就可以认为这些进程处在挂起状态
严格意义来讲,我们这里说的这种挂起状态全称可以叫做阻塞挂起状态,可以将挂起理解为一种特殊的阻塞状态

那为什么要先给大家说一下这两个概念呢?

因为这两个状态是操作系统中进程比较核心的两个状态,当然还有一个运行状态它相对比较好理解,我们后面针对具体的Linux操作系统去讲解。

当然如果我们去看一些操作系统的书籍或去网上搜进程的状态:

可能大部分都是这种
在这里插入图片描述
有的可能会有挂起状态。
而我们上面了解的内容其实就是基于操作系统这门课程来说的,可以认为它对于所有具体的操作系统都是成立的,可能比较抽象。

而我们下面呢,要针对一款具体的操作系统——Linux来学习一下进程的状态。

3. 看看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 */
};

那这里的进程状态呢其实就是这几个

在这里插入图片描述
一共有7种
在这里插入图片描述
进程状态的变化其实就是该每个状态对应的那个数值就行了

接下来我们就来一一学习这几种状态

4. R运行状态(running)

R表示运行状态,那我问大家,如果一个进程是R状态,那么它一定是在CPU上运行吗?

那其实是不一定的!
也就是说,操作系统里可能有10个8个状态为R的进程,但是它们之中可能只有几个是正在CPU上运行的。
所以,其实操作系统维护调度进程也有相应的队列(运行队列
在这里插入图片描述
运行队列通常根据不同的调度策略进行管理,处在运行队列中的进程,它的状态就是R

所以总结一下:

R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里

那下面我们来写一个代码观察观察:

在这里插入图片描述
这样一个代码

再写一个Makefile:

在这里插入图片描述

然后我们来make生成可执行程序并执行一下:

在这里插入图片描述
大家看,现在这个进程在运行吗?
当然,我们肉眼可见它在不停的运行。
那我们来查看一下,前面学过查看进程的命令
在这里插入图片描述
我们看到查出来的进程的状态是s,后面那个+号我们先不管,那s对应的状态是啥呢?
s呢其实是休眠状态,后面我们就会学。

那这里怎么回事啊?

为什么我们查到的状态是s休眠呢,虽然s状态我们还不太了解,但我知道它不是R运行状态,那这是怎么回事呢?

🆗,至于原因呢先不急,我呢现在把我们上面的代码修改一下:

在这里插入图片描述
我把这句代码注释掉。
然后我们重写make并运行
在这里插入图片描述
这次再查看
在这里插入图片描述
大家看这次就是R运行状态了

那这是怎么回事呢?

🆗,我们第一次的代码,是不是一个死循环然后里面一个打印语句,所以它允许的时候是不是要不断的频繁访问显示器这个外设啊?
但是,我们每次访问显示器的时候,他一定是就绪的吗?
如果不是就绪的话,那我们的进程是不是就不在进程的运行队列里面排队了,而是在显示器这个外设资源的等待队列里面排队。
所以,我们才查到了S状态,它也是阻塞状态的一种。
所以这个进程并不是一直在CPU的运行队列里面的,而是在运行队列和外设资源的等待队列里面不断切换的。

那为什么我们查到的是S状态而不是R状态呢?

我们这里只有一行代码,CPU执行的时候是很快的,而等待外设的过程相对于CPU执行代码的速度是非常慢的。
所以我们ps命令查的时候会发现查到的差不多都是s状态,可能查1万次能有一两次是R状态。

那为什么我们后面把打印注释掉查看到的就是R状态了:

那也很好解释,因为我们把它注释掉,程序里面就没有访问资源的代码。
只有while循环判断,while循环判断就是纯计算,所以它不需要访问外设,那只要被调度,就一直处在运行队列里,所以我们查到它的状态总是R状态。

那下面我们就来学习下一个状态——S状态

5. S休眠状态(sleeping)

概念大家可以先看一下:

S休眠状态(sleeping): 意味着进程在等待事件完成(这里的休眠有时候也叫做可中断修眠(interruptible sleep))。

那首先呢,可以告诉大家,S状态就是一种阻塞状态

我们再来修改一下代码:

在这里插入图片描述
改成这样

我们来运行一下:

在这里插入图片描述
其实就是一个死循环嘛,我们输入一个数,他就给我们打印一个数

那我们来查一下这个进程的状态

在这里插入图片描述
我们看到此时它的状态就是S。
因为它此时正在等待资源啊
在这里插入图片描述
等待我们通过键盘输入数据。
所以它此时就不在CPU的运行队列里,没有被调度,而是在键盘资源的等待队列,那就是我们上面说的阻塞状态。
而我们说了,S休眠状态其实就是阻塞的一种,而且S这种休眠状态被称为可中断休眠
在这里插入图片描述
我们CTRL+c就可以终止该进程

那现在大家再回过头来看S状态的概念:

S休眠状态(sleeping): 意味着进程在等待事件完成(这里的休眠有时候也叫做可中断修眠(interruptible sleep))。

就应该比较好理解了

那我们继续

6. D不可中断休眠状态

D 磁盘休眠状态(Disk sleep)也叫不可中断休眠状态(uninterruptible sleep),在这个状态的进程通常要等待IO的结束。
也算是一种阻塞状态。

那么D 状态呢?

其实我们平时大概率是遇不到的,一般是那些做系统管理的,运维的等等这些人员可能遇到的会比较多。

那该如何理解这个D 状态呢?我们来看这样一个场景:

在这里插入图片描述
假设现在呢这个进程想往磁盘上写100MB的数据。
那它就告诉磁盘,我想往你身上写100MB的数据;然后磁盘说,那我的速度比较慢,你要等等我;那此时进程就被设置成了阻塞状态,就去磁盘的等待队列里面排队了。
那CPU呢就对这个进程说,那你先写数据吧,我先运行其它的进程,等你资源准备就绪了,我再调度你。
此时,操作系统路过。
作为系统的管理者,它发现此时系统的内存资源已经非常紧张了,如果再有进程就要挂了,但是此时操作系统却发现你这个进程却不在运行队列里,而是啥也不干在这里等。
那操作系统就想,那我把你杀掉吧,于是,这个进程就被干掉了

与此同时呢,又发生了新的状况,这个进程被干掉了,此时磁盘还在写数据,但是,由于某些原因,数据写失败了。
那然后呢磁盘就要给这个进程说,你的这些数据写入失败了,但是此时却发现人不见了,找不到这个进程了。我还想着告诉你,然后让你反馈给用户呢!
那现在进程被杀死了,就只剩磁盘拿着这100mb的数据,不知该怎么处理了。
可以直接把这些数据丢掉嘛,如果这些数据很重要呢!

那此时这种情况该如何处理呢?

上面的故事呢,涉及3个比较关键的角色——操作系统、进程、磁盘。
那么请问:导致上面那样的情况出现,是谁的锅呢?
那我们分析一下它们做的好像都是合理的。
那怎么办呢?如何避免这种情况的出现呢?
那其实只要我们保证这个进程不能被杀死就行了啊。

所以呢,就有了这样一种休眠状态:

即D状态——不可中断休眠状态。
如果一个进程处在这种状态,它就无法被杀死,操作系统也不行。
所以如果出现D状态的话,那你的机器可能就快要宕机了,因为此时磁盘的压力可能已经非常大了,严重变慢,才导致出现这种情况。
所以我们才说这种状态我们大概率遇不到。

7. T暂停状态(stopped)

T暂停状态呢其实也是一种阻塞状态:

可以通过发送 SIGSTOP 信号给进程来暂停(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

我们再来修改一下代码:

在这里插入图片描述
我们make并运行一下
在这里插入图片描述
当然现在如果我们查他的状态是S
在这里插入图片描述

那我们怎么让它暂停呢?

再来学习一个新命令
在这里插入图片描述
还是kill命令,后面我们还会详细讲,现在先用。
然后呢-19这个选项,加上对应进程的PID,他就可以暂停一个进程。

我们来试一下:

在这里插入图片描述
目前它的状态是S
在这里插入图片描述
我们看到执行之后这个进程就停止了,而且我们再去查看进程状态就变成T暂停状态了。

那我想让他继续运行呢?

再学一个命令
在这里插入图片描述
kill -18 就可以让指定的进程继续执行
在这里插入图片描述
我们看到执行之后它就重新运行起来了
此时再去查看进程状态
在这里插入图片描述
就又变回S了。

但是呢!

在这里插入图片描述
此时我们去CTRL+c无法终止这个进程了。
那除此之外不知道大家有没有注意到一个现象
前面我们查看的状态字母后面还有一个“+”加号,但是自从上面变成T状态之后,就没有+了

那进程状态后面的+表示什么呢?

🆗,如果带+的话,表明该进程是在前台运行的,CTRL+c可以终止掉它;
如果没有+,就表明这个进程变成了在后台运行,后台运行的时候我们可以去正常执行我们的shell指令
在这里插入图片描述
但是它在后台还会一直运行,且CTRL+c终止不了
那有办法杀掉它吗,再来认识一个命令
在这里插入图片描述
kill -9
在这里插入图片描述
就可以杀掉这个后台进程(当然前台的也可以)

8. t 追踪暂停状态 (tracing stop)

然后我们看到,除了T之外:

在这里插入图片描述
还有一个t——追踪暂停状态

那其实我们GDB调式程序的是时候,如果打了断点,程序在断点处停下来,此时程序就会停止执行进入t状态

我们来演示一下:

那首先Makefile里面我们要加一个-g选项让它以debug版本生成,这是我们之前讲过的内容
在这里插入图片描述
然后我们GBD调式一下
在这里插入图片描述
查看一下代码
在这里插入图片描述
那我现在在第12行打个断点
在这里插入图片描述
然后我们r开始调式
在这里插入图片描述
它就在12行停下来了

那此时我们去查看它的状态

在这里插入图片描述
就能看到对应进程的状态就变成t了
如果我们退出gdb
在这里插入图片描述
在这里插入图片描述
此时再查就没有了

那这就是追踪暂停状态

9. X死亡状态(dead)

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

它是一个瞬时状态,我们也很难查到,不过与之相关的,还有一个重点状态——Z (zombie):僵尸状态

那这两个我们放到一块讲

10. Z僵尸状态 (zombie)

首先问大家一个问题,我们为什么要去创建进程?

那其实就是为了让进程帮我们办事嘛,完成某个任务。
那对于进程执行的结果,我们有时候可能是关心的,有时候可能并不关心。

那我们来讲一个东西:

我们平时写的C/C++ 代码,main函数里面最后一般都要有一个返回值return 0;
那大家可能不是特别清楚为什么main函数要有一个返回值,这个返回值是做什么的呢?
🆗,那这个返回值呢其实叫做进程退出码
另外呢我们直接有讲过:
任何命令行上启动的进程,都是bash的子进程,所以我们运行一个程序的时候,可以认为是父进程bash创建了一个子进程,让这个子进程去帮忙办事。
那你事办的怎么样,结果如何?父进程是怎么知道的呢?
它是通过退出码来获悉的。
在这里插入图片描述
在这里插入图片描述
那如何获取一个进程的退出码呢?
echo &?
在这里插入图片描述
就可以获取进程的退出码

不过呢:

我们上面的代码没什么意义,如果我们关心进程的执行结果,比如有一个算法,判断它执行的结果对不对。
我们改一下代码
在这里插入图片描述
假设正确结果是0,如果算法返回值等于0,就返回0,否则,返回3代表返回结果不正确。
那我们再来运行查看一下退出码
在这里插入图片描述
是0,表示结果正确
如果运算结果不对
在这里插入图片描述
那么
在这里插入图片描述
退出码就变成了3

那关于上面讲的这个退出码,大家先了解一下,后面还会说。

那再回到我们上面讲的:

我们创建进程帮我们做事有时候是关心结果的,那如何获取这个结果呢?
其中一个方式就是通过退出码

那么:如果一个进程退出了立即变成了X死亡状态,那父进程bash有没有机会拿到这个退出结果呢?

所以,为了方便子进程退出后父进程或操作系统获取该进程的退出结果,Linux进程退出时,进程一般不会立即死亡,而是要维持一个Z状态即——僵尸状态。
等这个进程真正被回收了,它的状态就会变成X死亡状态。(如何回收我们后面会讲)

那处在僵尸状态的进程就叫做僵尸进程,关于僵尸进程的进一步理解我们下篇文章讲解…
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1052492.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL学习笔记26

MySQL主从复制的搭建(AB复制) 传统AB复制架构(M-S): 说明:在配置MySQL主从架构时,必须保证数据库的版本高度一致,统一版本为5.7.31 环境规划: 编号主机名称主机IP地址角色信息1ma…

C/C++跨平台构建工具CMake-----在C++源码中读取CMakeLists.txt配置文件中的内容

文章目录 1.需求描述2.需求准备2.1 创建项目2.2 编辑CMakeLists.txt文件2.3 编写C文件2.4 编译构建项目 3.需求实现3.1 在CMakeLists.txt中输出日志信息3.2 增加配置生成C头文件3.3在C 源码中访问配置的值3.4 C文件中读取CMakeLists.txt中的字符串 总结 1.需求描述 当我们开发…

C语言数据结构之排序整合与比较(冒泡,选择,插入,希尔,堆排序,快排及改良,归并排序,计数排序)

前言:排序作为数据结构中的一个重要模块,重要性不言而寓,我们的讲法为下理论掌握大致的算法结构,再上代码及代码讲解,助你一臂之力。 一,冒泡 冒泡排序应该是大家学习以来第一个认识的排序方法&#xff0…

FFmpeg 命令:从入门到精通 | FFmpeg 基本介绍

FFmpeg 命令:从入门到精通 | FFmpeg 基本介绍 FFmpeg 命令:从入门到精通 | FFmpeg 基本介绍FFmpeg 简介FFmpeg 基础知识复用与解复用编解码器码率和帧率 资料 FFmpeg 命令:从入门到精通 | FFmpeg 基本介绍 本系列文章要解决的问题&#xff1…

2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题

2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题 模块一:数据库系统运维(25分)任务一:数据库系统搭建(10分)任务二:房源数据库系统运维(15分) 模块二&a…

milvus 结合Thowee 文本转向量 ,新建表,存储,搜索,删除

1.向量数据库科普 【上集】向量数据库技术鉴赏 【下集】向量数据库技术鉴赏 milvus连接 from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility connections.connect(host124.****, port19530)2.milvus Thowee 文本转向量 使用 …

模拟实现简单的通讯录

前言:生活中处处都会看到或是用到通讯录,今天我们就通过C语言来简单的模拟实现一下通讯录。 鸡汤:跨越山海,终见曙光! 链接:gitee仓库:代码链接 目录 主函数声明部分初始化通讯录实现扩容的函数增加通讯录所…

【Docker】docker拉取镜像错误 missing signature key

问题 当我使用docker拉取一个特定的镜像时,提示错误: 错误 missing signature key 但是拉取其他镜像又可以访问,,,,于是,我怀疑是否是docker版本问题。 docker --version结果确实&#xff0…

使用Python进行App用户细分

App用户细分是根据用户与App的互动方式对用户进行分组的任务。它有助于找到保留用户,找到营销活动的用户群,并解决许多其他需要基于相似特征搜索用户的业务问题。这篇文章中,将带你完成使用Python进行机器学习的App用户细分任务。 App用户细…

FFmpeg 命令:从入门到精通 | FFmpeg 音视频处理流程

FFmpeg 命令:从入门到精通 | FFmpeg 音视频处理流程 FFmpeg 命令:从入门到精通 | FFmpeg 音视频处理流程实例 FFmpeg 命令:从入门到精通 | FFmpeg 音视频处理流程 实例 ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x…

ElasticSearch 同步数据变少了

一、前言 这几天对接ES遇到几个坑,我们将一张库存表同步到ES发现Docs Count和我们表中的数据对不上,需要加上Docs deleted才对得上,也不知道批量写入数据为什么有些数据就会成 Docs deleted。 二、ID和版本号 ES中每一个Document都有一个_…

ElementUI之增删改及表单验证

⭐⭐本文章收录与ElementUI原创专栏:ElementUI专栏 ⭐⭐ ElementUI的官网:ElementUI官网 目录 一.前言 二.使用ElementUI完成增删改 2.1 后台代码 2.2 前端代码 三.使用ElementUI完成表单验证 一.前言 本章是继上一篇的基础之上在做完善&#xff0…

Leetcode---364场周赛

题目列表 2864. 最大二进制奇数 2865. 美丽塔 I 2866. 美丽塔 II 2867. 统计树中的合法路径数目 一、最大二进制奇数 这题只要你对二进制有了解(学编程的不会不了解二进制吧),应该问题不大,这题要求最大奇数,1.奇数:只要保证…

二维码智慧门牌管理系统:创新历史,稳定未来

文章目录 前言一、解决传统门牌管理混乱二、提供便捷服务三、尊重历史,保持稳定 前言 随着科技的飞速发展,二维码智慧门牌管理系统已经成为了城市管理的新趋势。这款系统的出现,不仅优化了传统门牌管理的不足,还大大提高了城市管…

3.物联网射频识别,(高频)RFID应用ISO14443-2协议

一。ISO14443-2协议简介 1.ISO14443协议组成及部分缩略语 (1)14443协议组成(下面的协议简介会详细介绍) 14443-1 物理特性 14443-2 射频功率和信号接口 14443-3 初始化和防冲突 (分为Type A、Type B两种接口&…

(高阶) Redis 7 第16讲 预热/雪崩/击穿/穿透 缓存篇

面试题 什么是缓存预热/雪崩/击穿/穿透如何做缓存预热如何避免或减少缓存雪崩穿透和击穿的区别?穿透和击穿的解决方案出现缓存不一致时,有哪些修补方案缓存预热 理论 将需要的数据提前加载到缓存中,不需要用户使用的过程中进行数据回写。(比如秒杀活动数据等) 方案 1.…

【C语言深入理解指针(1)】

1.内存和地址 1.1内存 在讲内存和地址之前,我们想有个⽣活中的案例: 假设有⼀栋宿舍楼,把你放在楼⾥,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩,如果想找到你,就得挨…

学校安全用电管理系统解决方案

随着科技的发展和进步,电力已成为我们日常生活和学习的重要支柱。然而,电力的使用也带来了一定的安全风险。特别是对于学校这个复杂而又活跃的环境,安全用电管理系统的角色显得尤为重要。 一、学校用电管理系统的现状 目前&#xff0…

2023-09-28 LeetCode每日一题(花期内花的数目)

2023-09-28每日一题 一、题目编号 2251. 花期内花的数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的二维整数数组 flowers ,其中 flowers[i] [starti, endi] 表示第 i 朵花的 花期 从 starti 到 endi (都 包含&#xf…

JSP学习笔记【三】——JQuery

前言 在写项目的时候需要动态对某组件的属性进行调整,我看网上的教程都是使用document.getElementById等,但我在eclipse编写.jsp文件的时候,却提示document cannot be resolved。由于我对jsp没有系统的了解以及无人可咨询,网上也…