【Linux】探索Linux进程状态 | 僵尸进程 | 孤儿进程

最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。

目录

  • 一、进程状态
    • 1.1运行状态
    • 1.2阻塞状态
    • 1.3挂起状态
  • 二、具体Linux中的进程状态
    • 2.1看看Linux内核源代码怎么说
    • 2.2进程状态查看
    • D磁盘休眠状态(Disk sleep)
    • T停止状态(stopped)
  • 三、僵尸进程
    • 3.1僵尸进程危害
  • 四、孤儿进程
  • 🍀小结🍀

在这里插入图片描述
在这里插入图片描述

🎉博客主页:小智_x0___0x_

🎉欢迎关注:👍点赞🙌收藏✍️留言

🎉系列专栏:Linux入门到精通

🎉代码仓库:小智的代码仓库


一、进程状态

进程状态在操作系统中可以分为五大状态,分别是:

  • 新建状态:一个进程刚被创建,把PCB和对应的代码和数据刚申请出来,尚未进入就绪队列
  • 就绪状态:进程已经分配到除CPU以外的所有必要资源,只要再获得CPU,便可立即执行,进程这时的状态称为就绪状态
  • 阻塞状态:也称为等待或睡眠状态,一个进程正在等待某一事件发生(例如请求I/O而等待I/O完成等)而暂时停止运行,这时即使把处理机分配给进程也无法运行,故称该进程处于阻塞状态1。处于阻塞状态的进程也可能有多个,通常将它们排成一个队列,称为阻塞队列
  • 运行状态:进程占有处理器正在运行的状态。进程已获得CPU,其程序正在执行1
  • 终止状态:指进程完成任务到达正常结束点,或出现无法克服的错误而异常终止,或被操作系统及有终止权的进程所终止时所处的状态

1.1运行状态

当多个进程需要运行时,它们会竞争CPU资源。在极端情况下,如果只有一个CPU,那么众多进程就必须通过调度器来合理使用CPU资源,确保资源的均衡使用。为了管理这些进程,每个CPU都会维护一个自己的运行队列struct runqueue。这个运行队列是一个重要的数据结构,用于存储当前CPU上待运行的进程。

每个进程都有一个对应的task_struct结构体,这个结构体包含了进程的各种属性。而运行队列中最重要的属性是head和tail指针,它们分别指向队列的头部和尾部。这意味着排队的不是进程的代码,而是进程的PCB在排队。

当CPU需要运行某个进程时,它会从运行队列中挑选一个进程来执行。挑选的过程是由调度器完成的,它会根据一定的算法从队列中选择一个合适的进程。一旦选定了进程,调度器就会将该进程从队列中移除,并将其放到CPU上运行。
在这里插入图片描述
当多个进程处于运行队列中时,它们所处的状态被称为运行状态(r状态)。这意味着这些进程已经准备好,可以随时被调度执行。当一个进程开始运行时,它将自己置于CPU上并执行。然而,一个进程并不需要一直执行到完成才让出CPU。例如,如果有一个进程陷入了一个无限循环中,它可能会一直占用CPU,导致其他进程无法得到调度和执行。

为了防止这种情况的发生,操作系统引入了时间片的概念。每个进程都被分配了一个时间片,它定义了该进程在CPU上的最大执行时间。一旦一个进程的执行时间超过了它的时间片,操作系统会强制将其从CPU上移除,并将其放回运行队列的尾部等待再次调度。

时间片的引入确保了每个进程都有机会在一段时间内得到执行,从而实现了多个进程的并发执行。并发执行是指在同一时间段内,多个进程的代码都会被执行。通过合理分配时间片,操作系统可以确保所有进程都得到公平调度和执行,从而提高了系统的整体效率和响应速度。

1.2阻塞状态

我们每个外设都有一个等待队列,每个使用设备的进程,如果想要使用某个设备,就需要等待该设备变为就绪状态。如果设备当前不可用,即处于不可读状态,那么进程会自动将其PCB(进程控制块)加入到该设备的等待队列中。一旦设备变为可用状态,即处于可读状态,进程就可以从等待队列中取出PCB,进入就绪状态,等待CPU调度。如果设备仍然没有准备好,进程就会在等待队列中等待,这时我们称进程处于阻塞状态。因此,当我们说让进程去某个资源中等待时,实际上是将进程加入到该资源的等待队列中,也就是让进程进入阻塞状态。
在这里插入图片描述
系统中可能有很多阻塞的进程,每个都在等待资源或设备。进程间也可能互相等待。如果只有一个CPU,那同一时间只能运行一个进程,其他的都得等着。

1.3挂起状态

如果有很多进程都在等一个设备,比如磁盘,但磁盘一直没准备好,这些进程就只能在内存里等着,也不占用CPU。但有时候,操作系统的内存可能会不够用,因为每个进程都需要占用一些内存。如果一个进程只是等着,没有被CPU调度,那它的代码和数据其实在内存里是空闲的。为了解决这个问题,操作系统可以把等待进程的代码和数据移到磁盘里去,只留下一个PCB在内存里排队。这样,当设备准备好了,再把代码和数据从磁盘移回内存。这个过程叫做换出和换入。当代码和数据不在内存里时,我们称这个进程为挂起状态。这样操作系统就可以空出一些内存给其他进程用。这个挂起状态适用于所有等待的进程。
在这里插入图片描述
挂起状态对用户是不可见的,这是操作系统的一种行为。

上面介绍的这些属于操作系统学科的理论知识,不同的操作系统可能会有不同的实现方案,下面我们来深入研究研究具体的 Linux 操作系统中有哪些进程状态。

二、具体Linux中的进程状态

2.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 */
};
  • R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

2.2进程状态查看

我们先来写一段代码观察效果:

int main()
{while(1){printf("hello linux\n");}return 0;
}

在这里插入图片描述
可以看到这里并不是R状态,而是S状态,这是因为当程序疯狂地进行打印操作时,你的设备可能并不处于可以直接写入的状态。因此,你的进程有很大可能性一直处于等待状态。你可能认为你的进程正在直接向设备写入数据,但事实上,操作系统内部,你的进程可能大部分时间都在等待I/O设备(如显示器)就绪。因此,你的进程状态一直显示为S状态,这个S状态实际上对应着我们操作系统原理中的阻塞状态。

我们再来把代码修改一下去掉printf:

int main()
{while(1);return 0;}

在这里插入图片描述
当去掉printf语句后,程序就不再涉及I/O操作,而是纯粹地运行计算任务。在这种情况下,进程的状态会变成R状态,也就是运行状态。这是因为没有I/O等待,进程可以一直占用CPU进行计算,直到任务完成。所以,当没有I/O操作时,进程就处于运行状态,也就是R状态。

查询结果中显示的+表示该进程在前台运行,这意味我们此时在 bash 命令行输指令是不会有任何反应的,可以在输入指令的后面加上&,此时表示让该进程在后台运行,要终止掉该进程只能通过指令kill -9 PID给进程发送终止信号。

D磁盘休眠状态(Disk sleep)

如果一个进程处于D状态,我们也称之为disk sleep,在Linux系统中它也是一种阻塞状态,只不过这种状态在操作系统层面被称为深度睡眠。相对应的,我们之前提到的S状态可以被称为浅度睡眠。就像人们睡觉时有深浅之分,浅度睡眠可以被直接唤醒,比如被程序员或其他进程唤醒。

我们再来通过一个有趣的故事来了解D状态:

有一个进程要完成I/O操作,此时进程呢他那朝着远端的磁盘大喊了一声磁盘啊,我这有1GB的数据我把数据存到你存到磁盘的某个位置上,你帮我做一下吧然后呢,当磁盘听到这句话,磁盘慢慢悠悠的探出来个脑袋,就给进程说好的,那你把数据给我吧,我去帮你写,于是磁盘就抱着进程的数据去做写入了,磁盘进行写入时,这个进程它翘着二郎腿,悠哉悠哉的在这里等待,此时操作系统它从旁边路过,操作系统现在压力很大,不知道什么原因,反正整个计算机里,进程变得非常多了,而且每一个地方都特别吃资源,内存资源严重不足,当前操作系统火急火燎的在想办法,当他从这个进程旁边路过的时候,他瞥了一眼这个进程,觉得他很不爽,他把他能做的全做了,包括进程所对应的代码和数据能置换全置换了,所以操作系统一气之下啊,就对着这个进程说,你这个进程这么没眼色,你没看到当前内存已经被撑得快爆了吗?我已经马上快挂掉了,你还在这里翘着二郎腿,你还在等着呢,不要等了,所以操作系统直接把这个进程干掉了,如果系统压力已经在内存辗转腾挪已经解决不了时操作系统就要开始动手杀进程了,所以操作系统是会杀掉处于某一些他自己判定不太重要的进程 删掉了之后,此时这个刚刚在写入数据的磁盘也遇到了问题,当前他在写入时发现写到一半时突然发现磁盘空间不够了,这个磁盘就转过头,探出脑袋就对这个进程说进程啊,不好意思,我写入失败了,唉,进程呢,进程怎么不见了?那我数据没有写成功该怎么办呢我到底是再尝试一次呢还是我再等一等,我该怎么做决策呢,(有的硬件直接丢掉的有的给你再试着写一下,大部分都是掉直接丢掉),此时数据就被丢失了,丢失的数据非常重要。于是呢,法官就把操作系统,进程和磁盘一并带上了法庭,法官先审问操作系统说你怎么能杀掉进程呢?操作系统却说:“请问用户有没有赋予我管理他软件资源的权利?请问我杀掉进程是不是在特别极端的情况下杀掉了?请问我有没有履行我操作系统的职责?我的职责是保证系统不挂数据丢失和我有什么关系,我就是在做我操作系统该做的事情,如果你判我有罪了,那么请问下次如果再碰到这样的极端情况,那到底我还做不做,我如果不杀最后导致操作系统挂掉,第一,它的数据该丢还是会丢,第二,可能还会影响其他进程,那么这个责任谁来承担。”法官说:“唉,这话说的还挺有道理啊,是的,他只是履行了他的义务,而且他确实是在极端情况下做的这个事情”于是法官又把目光转移到了磁盘身上,对磁盘说:“你怎么能把人家数据丢掉呢?”此时磁盘就说:“法官大人不要怪我,在这件事情上我就是个跑腿的人家让我干啥就干啥我在写入的时候就已经告诉了对方,我可能会失败,我让他去等的我要给他结果的,我的工作模式从来向来都是这样,从我出生的时候就是这样,其他磁盘也是这样,如果你认为我有罪的话,那是不是我的兄弟磁盘,我的朋友磁盘也有问题,那是不是我们把储存的逻辑全部都改下,我就是个跑腿的,我怎么能决定这个数据写入失败该怎么办,数据被丢失是因为我还有其他事情要做,因为有其他进程也要让我写入”,法官听了之后觉得也有道理,那么就把视角转向了受害人进程的身上,反正操作系统没错,磁盘也没错,那就是你的问题了,在法官刚看向进程的时候,进程扑通一下就跪下来了对法官说:“法官我可是受害人啊,我是被杀掉的,我就是静静的坐在那里,人在家中坐,锅从天上来,我是被杀掉的,我怎么能有错呢啊”。法官此时一想,唉,他们三个好像说的都挺有道理,难道是我错了吗? 凡是有争议的地方,那么一定是因为制度设计不合理 法官最后说算了算了,你们三个都回去吧,我完了去改改操作系统,法官就把进程的状态加了一个状态,那么这个状态就是只要这个进程当前正在有写入任务交给了磁盘,如果磁盘没有办法立马响应的话,需要进程等待这个进程绝对不能以浅度睡眠的方式运行即S状态,必须把自己设为D状态,从我们的源代码方式规定,D状态进程任何人都不能杀掉,包括操作系统 所以故事又来了,这个进程呢,又喊出来磁盘啊,磁盘说怎么又是你,进程说没关系,这次写吧,这次我不怪你了,所以呢,磁盘抱着数据就去进行写入了,那么当前这个进程翘着二郎腿在这里啊,嗑着瓜子,在这里等,一个操作系统路过了操作系统说你这个进程话还没说完,进程就亮出了一个免死金牌,一边看去,不要影响我,我还忙着呢,你现在是没资格杀我啊,所以操作系统一看行啊,有这回事就行反正我尽力了,人家不让杀他就不让杀我去那么去杀别的进程,反正对我来我做了我的工作,你没有被杀死那后果自己承担,所以当前进程的此时就处了一个状态叫D状态,当它进行等待时进程不可被杀死,这样的话就不会存在刚刚我们的这种问题了所以当磁盘把数据写完之后,返回来时告诉进程进程啊,你的数据写完了这个时候得到了结果之后,进程再把自己的状态由D状态恢复成R状态。

我们最后再来总结一下这个小故事:
在这个故事中,一个进程请求磁盘保存1GB数据。磁盘接受了任务,进程则等待。由于系统内存紧张,操作系统决定杀掉该进程以释放资源。磁盘在写入过程中发现空间不足,但进程已被杀死,数据丢失。法官审问后,决定给进程增加D状态,保证正在进行I/O操作的进程不会被杀死。这样,即使操作系统再次路过,也无法杀掉处于D状态的进程,避免了数据丢失。

D状态也是阻塞状态的一种

T停止状态(stopped)

T状态称之为暂停状态也叫做stop状态,我们来举一个例子:

int main()
{while(1){printf("hello linux\n");sleep(1);}return 0;}

在这里插入图片描述
此时我们的进程还是S状态.
在这里插入图片描述
接下来我们给进程发送信号来暂停进程kill -19 759:
在这里插入图片描述
可以看到我们的进程被stop了,我们再来查一下进程状态
在这里插入图片描述
此时进程就变成了T状态,我们想让进程再次跑起来,可以给进程发送18号信号kill -18 759:
在这里插入图片描述
可以看到程序又正常跑了起来,再来查看进程状态:
在这里插入图片描述
这里又变成了S状态,但是却少了+这是因为我们将进程暂停启动之后进程就会变成后台进程。此时我们想要杀掉这个进程就只能使用kill -9来杀死进程。

当一个进程处于T状态一般是不会接受信号,除了特殊信号,我们使用gdb调试工具调试的时候,设置断点,程序遇到断点停止时候就会处于t状态。
在这里插入图片描述
Tt的区别:
在进程状态中,“T”代表停止状态或常规暂停,而“t”代表追踪停止。二者的主要区别在于,“T”状态通常可以通过发送SIGSTOP信号给进程来使其停止,而这个被暂停的进程可以通过发送SIGCONT信号来继续运行。“t”状态主要发生在进程被调试过程中遇到断点时,此时进程会进入追踪停止状态。

三、僵尸进程

如果今天我们有父和子两个进程,父进程一直在运行,并且父进程不关心对应的子进程,而子进程直接退出之时,他并不是退出之后立马要将自己的所有资源全部释放,因为父进程没有还没有来关心他,那么此时操作系统就必须把子进程的状态一直给我维持着,直到我的父进程开始关心他,那么其中我们把这种已经死掉的,但是当前需要由父进程来关心,此时这个进程所维持的这种状态,我们称之为Z状态。

下面我们再来写一段代码验证一下:

子进程执行完5次打印后就处于 Z 状态,等待父进程来回收它的资源。处于 Z 状态的进程的相关资源尤其是 task_struct 结构体不能被释放。只有当父进程把子进程的相关资源回收后,子进程才能变成 X死亡状态。我们将这种处于 Z 状态的进程就叫做僵尸进程,如果父进程一直不来回收,那这种进程会长时间占用内存资源,造成内存泄漏。后面我们会介绍解决这种问题的方法(waitpid())感兴趣的老铁可以期待后续更新!

3.1僵尸进程危害

  • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态。
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。
  • 那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
  • 内存泄漏

四、孤儿进程

上面的例子中我们是让子进程先退出,父进程一直运行,接下来我们让父进程先退出,子进程一直运行,我们再来看看会有什么结果。

#include <iostream>
#include <unistd.h>
#include <cstdlib>
using namespace std;
int main()
{pid_t id=fork();if(id==0){int cnt =500;while(cnt){printf("i an child,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);cnt--;sleep(1);}printf("child quit!\n");exit(0);}else{int cnt=5;while(cnt){printf("i am parent,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);sleep(1);cnt--;}printf("parent quit!\n");}return 0;}


我们可以看到父进程在执行结束后就只剩下子进程,为什么父进程不会处在 Z僵尸状态呢?答案是父进程也是 bash 的子进程,父进程在执行结束后,它的父进程 bash 会将其回收掉,并且过程非常快,所以我们我们没有看到父进程处在 Z僵尸状态。其次我们发现,当父进程结束后,它的子进程的父进程会变成1号进程,即操作系统。我们将父进程是1号进程的进程叫做孤儿进程,该进程被系统领养。因为孤儿进程未来也会退出,也要被释放。

🍀小结🍀

今天我们学习了"【Linux】探索Linux进程状态 | 僵尸进程 | 孤儿进程"相信大家看完有一定的收获。种一棵树的最好时间是十年前,其次是现在! 把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波💕💕~~~,本文中也有不足之处,欢迎各位随时私信点评指正!
在这里插入图片描述

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

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

相关文章

React中使用react-json-view展示JSON数据

文章目录 一、前言1.1、在线demo1.2、Github仓库 二、实践2.1、安装react-json-view2.2、组件封装2.3、效果2.4、参数详解2.4.1、src(必须) &#xff1a;JSON Object2.4.2、name&#xff1a;string或false2.4.3、theme&#xff1a;string2.4.4、style&#xff1a;object2.4.5、…

[ROS2] --- service

1 service介绍 1.1 service概念 话题通信是基于订阅/发布机制的&#xff0c;无论有没有订阅者&#xff0c;发布者都会周期发布数据&#xff0c;这种模式适合持续数据的收发&#xff0c;比如传感器数据。机器人系统中还有另外一些配置性质的数据&#xff0c;并不需要周期处理&…

C#,图算法——以邻接节点表示的图最短路径的迪杰斯特拉(Dijkstra)算法C#程序

1 文本格式 using System; using System.Text; using System.Linq; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer.Algorithm { public class Node // : IComparable<Node> { private int vertex, weigh…

【分布式微服务专题】从单体到分布式(一、SpringCloud项目初步升级)

目录 前言阅读对象阅读导航前置知识笔记正文一、单体服务介绍二、服务拆分三、分布式微服务升级前的思考3.1 关于SpringBoot/SpringCloud的思考【有点门槛】 四、SpringCloud升级整合4.1 新建父子项目 学习总结感谢 前言 从本节课开始&#xff0c;我将自己手写一个基于SpringC…

如何轻松恢复 Windows 中删除的文件夹

我们都曾经历过这样的事&#xff0c;而且我们中的大多数人可能很快就会再次这样做。我们讨论的是在 Windows 中按“Delete”或“ShiftDelete”键意外删除重要文件夹的情况。 如果您刚刚按下删除键且未超过 30 天&#xff0c;或者尚未清空回收站&#xff0c;则可以恢复文件夹。…

操作系统学习笔记---内存管理

目录 概念 功能 内存空间的分配和回收 地址转换 逻辑地址&#xff08;相对地址&#xff09; 物理地址&#xff08;绝对地址&#xff09; 内存空间的扩充 内存共享 存储保护 方式 源程序变为可执行程序步骤 链接方式 装入方式 覆盖 交换 连续分配管理方式 单一连…

python安装与工具PyCharm

摘要&#xff1a; 周末闲来无事学习一下python&#xff01;不是你菜鸡&#xff0c;只不过是对手太强了&#xff01;所以你要不断努力&#xff0c;去追求更高的未来&#xff01;下面先了解python与环境的安装与工具的配置&#xff01; python安装&#xff1a; 官网 进入官网下载…

git 关于分支、merge、commit提交

最近开始用git终端提交代码&#xff0c;梳理了一些知识点 一 关于分支 关于分支&#xff0c;git的分支分为本地分支远程分支两种分支&#xff0c;在上传代码时&#xff0c;我们要确保当前本地分支连接了一个远程分支。 我们可以通过下面代码查看当前的本地分支&#xff1a; g…

迅为3588开发板 sudo: 无法解析主机:/DNS配置

环境申明 RK3588 ubuntu 22.04 jammy 迅为开发板 hostname 看是否有Host .&#xff0c;如果没有&#xff0c; sudo vim /etc/hostname在里面加一行&#xff0c;我这就这一个 iTOP-RK3588hosts 修改本地hosts sudo vim /etc/hosts127.0.0.1 localhost localhost iTOP-RK3…

2.postman环境变量及接口关联

一、环境变量以及全局变量 操作流程 1.点击environment 2.点击environment右侧号&#xff0c;新增环境变量 3.在变量中输入变量名以及变量值 4.回到collection页面&#xff0c;修改变量环境 5.在collection中通过{{变量名}}调用变量 变量定义 环境变量&#xff1a;环境变量…

vue 限制在指定容器内可拖拽的div

<template><div class"container" id"container"><div class"drag-box center" v-drag v-if"isShowDrag"><div>无法拖拽出容器的div浮窗</div></div></div> </template><script&g…

P11 Linux进程编程exec族函数

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《Linux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f6f8;推荐专栏3: ​​​​​​《链表_C…

Java 简易版 UDP 多人聊天室

服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{public static ServerSocket server_socket;public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []args){try{…

算法通关村第五关—LRU的设计与实现(黄金)

LRU的设计与实现 一、理解LRU的原理 LeetCode146:运用你所掌握的数据结构&#xff0c;设计和实现一个LRU(最近最少使用)缓存机制 实现LRUCache类&#xff1a; LRUCache(int capacity) 以正整数作为容量capacity初始化 LRU 缓存 int get(int key) 如果关键字key存在于缓存中&a…

数据可视化|jupyter notebook运行pyecharts,无法正常显示“可视化图形”,怎么解决?

前言 本文是该专栏的第39篇,后面会持续分享python数据分析的干货知识,记得关注。 相信有些同学在本地使用jupyter notebook运行pyecharts的时候,在代码没有任何异常的情况下,无论是html还是notebook区域,都无法显示“可视化图形”,界面区域只有空白一片。遇到这种情况,…

Nginx服务优化以及防盗链

1. 隐藏版本号 以在 CentOS 中使用命令 curl -I http://192.168.66.10 显示响应报文首部信息。 查看版本号 curl -I http://192.168.66.10 1. 修改配置文件 vim /usr/local/nginx/conf/nginx.conf http {include mime.types;default_type application/octet-stream;…

京东数据运营(京东API接口):10月投影仪店铺数据分析

鲸参谋监测的京东平台10月份投影仪市场销售数据已出炉&#xff01; 10月份&#xff0c;环同比来看&#xff0c;投影仪市场销售均上涨。鲸参谋数据显示&#xff0c;今年10月&#xff0c;京东平台投影仪的销量为16万&#xff0c;环比增长约22%&#xff0c;同比增长约8%&#xff1…

鸿蒙应用开发ArkTS基础组件的使用

语雀知识库地址&#xff1a;语雀HarmonyOS知识库 飞书知识库地址&#xff1a;飞书HarmonyOS知识库 本文示例代码地址&#xff1a;Gitee 仓库地址 嗨&#xff0c;各位好呀&#xff0c;我是小白 上一篇文章我为大家介绍了如何使用 ArkTS 开发鸿蒙应用&#xff0c;对 HarmonyOS 项…

探索开源游戏的乐趣与无限可能 | 开源专题 No.47

CleverRaven/Cataclysm-DDA Stars: 9.0k License: NOASSERTION Cataclysm&#xff1a;Dark Days Ahead 是一个回合制的生存游戏&#xff0c;设定在一个后启示录世界中。尽管有些人将其描述为 “僵尸游戏”&#xff0c;但 Cataclysm 远不止于此。在这个残酷、持久、程序生成的世…

【原创】【一类问题的通法】【真题+李6卷6+李4卷4(+李6卷5)分析】合同矩阵A B有PTAP=B,求可逆阵P的策略

【铺垫】二次型做的变换与相应二次型矩阵的对应&#xff1a;二次型f&#xff08;x1&#xff0c;x2&#xff0c;x3&#xff09;xTAx&#xff0c;g&#xff08;y1&#xff0c;y2&#xff0c;y3&#xff09;yTBy ①若f在可逆变换xPy下化为g&#xff0c;即P为可逆阵&#xff0c;有P…