【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状态。
T
和t
的区别:
在进程状态中,“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进程状态 | 僵尸进程 | 孤儿进程"
相信大家看完有一定的收获。种一棵树的最好时间是十年前,其次是现在!
把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波💕💕~~~
,本文中也有不足之处,欢迎各位随时私信点评指正!
相关文章:

【Linux】探索Linux进程状态 | 僵尸进程 | 孤儿进程
最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 目录 一、进程状态1.1运行状态1.2阻塞状态1.3挂起状态 二、具体L…...

大数据股票简单分析
目录标题 内容说明解题量化金融的含义量化交易策略 点击直接资料领取 内容 1解释量化金融的含义,调研并给出至少 5种量化交易的策略或方法 2.完成Tushare Pro 的安装、注册,获取自己的 Token,查阅网站内的接口讲解和示例; 3通过Python 编程完…...

从零开始搭建链上dex自动化价差套利程序(11)
风险控制 需要将仓位杠杆控制到3倍以内,由于dydx与apex没有获取仓位杠杆的接口,但是每次发送交易的数额可以决定,故而可以设置每次发送总仓位1.5倍杠杆的数额,然后设置一个变量保证每个方向上的交易不超过2次,即可保证…...

2023.12面试题汇总小结
文章目录 Java字节码都包括哪些内容Java双亲委派机制如何打破Java Memory Model是什么synchronized的锁优化是什么CountDownLatch、CyclicBarrier、Semaphore有啥区别,什么场景下使用MySQL MVCC原理MySQL RR隔离级别,会出现幻读吗MySQL的RR隔离级别下&am…...

Linux权限命令详解
Linux权限命令详解 文章目录 Linux权限命令详解一、什么是权限?二、权限的本质三、Linux中的用户四、linux中文件的权限4.1 文件访问者的分类(人)4.2 文件类型和访问权限(事物属性) 五、快速掌握修改权限的做法【第一种…...

【Android】Glide的简单使用(下)
文章目录 缓存设置内存缓存硬盘缓存自定义磁盘缓存行为图片请求优先级缩略图旋转图片Glide的回调:TargetsBaseTargetTarget注意事项设置具体尺寸的Target 调试及Debug获取异常信息 配置第三方网络库自定义缓存 缓存设置 GlideApp .with(context).load(gifUrl).asGif().error(…...

TCP对数据的拆分
应用程序的数据一般都比较大,因此TCP会按照网络包的大小对数据进行拆分。 当发送缓冲区中的数据超过MSS的长度,数据会被以MSS长度为单位进行拆分,拆分出来的数据块被放进单独的网路包中。 根据发送缓冲区中的数据拆分情况,当判断…...

面试问题--计算机网络:二层转发、三层转发与osi模型
计算机网络:二层转发、三层转发与OSI模型 1. 二层转发和三层转发 1.1 二层转发(Data Link Layer) 在计算机网络中,二层转发是通过数据链路层(Data Link Layer)实现的。以下是关于二层转发的一些关键信息…...

kubectl获取ConfigMap导出YAML时如何忽略某些字段
前言: 当我们在使用Kubernetes时,常常需要通过kubectl命令行工具来管理资源。有时我们也想将某个资源的配置导出为YAML文件,这样做有助于版本控制和资源的迁移。然而,默认情况下,使用kubectl get命令导出资源配置会包…...

复制粘贴——QT实现原理
复制粘贴——QT实现原理 QT 剪贴板相关类 QClipboard 对外通用的剪贴板类,一般通过QGuiApplication::clipboard() 来获取对应的剪贴板实例。 // qtbase/src/gui/kernel/qclipboard.h class Q_GUI_EXPORT QClipboard : public QObject {Q_OBJECT private:explici…...

(一)五种最新算法(SWO、COA、LSO、GRO、LO)求解无人机路径规划MATLAB
一、五种算法(SWO、COA、LSO、GRO、LO)简介 1、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法(Spider wasp optimizer,SWO)由Mohamed Abdel-Basset等人于2023年提出,该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为&…...

LED透镜粘接UV胶是一种特殊的UV固化胶,用于固定和粘合LED透镜。
LED透镜粘接UV胶是一种特殊的UV固化胶,用于固定和粘合LED透镜。 它具有以下特点: 1. 高透明度:LED透镜粘接UV胶具有高透明度,可以确保光线的透过性,不影响LED的亮度和效果。 2. 快速固化:经过UV紫外线照射…...

C语言 题目
1.写一个函数算一个数的二进制(补码)表示中有几个1 #include<stdio.h>//统计二进制数中有几个1 //如13:1101 //需要考虑负数情况 如-1 结果应该是32// n 1101 //n-1 1100 //n 1100 //n-1 1011 //n 1000 //n-1 0111 //n 0000 //看n的变化 int funca(int c){int co…...

CDN 内容分发网络
CDN常见问题 什么是 CDN ? CDN 全称是 Content Delivery Network/Content Distribution Network,翻译过的意思是 内容分发网络 。 我们可以将内容分发网络拆开来看: 内容:指的是静态资源比如图片、视频、文档、JS、CSS、HTML。…...

Android : Xui- RecyclerView+BannerLayout 轮播图简单应用
实例图: 1.引用XUI http://t.csdnimg.cn/Wb4KR 2.创建显示图片布局 banner_item.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"…...

Java网络通信-第21章
Java网络通信-第21章 1.网络程序设计基础 网络程序设计基础涵盖了许多方面,包括网络协议、Web开发、数据库连接、安全性等。 1.1局域网与互联网 局域网(LAN)与互联网(Internet)是两个不同的概念,它们分…...

Leetcode 345. Reverse Vowels of a String
Problem Given a string s, reverse only all the vowels in the string and return it. The vowels are ‘a’, ‘e’, ‘i’, ‘o’, and ‘u’, and they can appear in both lower and upper cases, more than once. Algorithm Collect all the vowels and reverse the…...

[linux] 用命令行wget下载google drive的大文件
使用wget命令下载Google drive上的文件_ubuntu上wget下载谷歌云盘文件-CSDN博客 如何用命令行下载Google Drive上的共享文件?-腾讯云开发者社区-腾讯云 举例:https://drive.google.com/drive/folders/1vKj3VvJEKgS_o-uOSmz3I0-GomECpql3 1、在网页上&…...

Docker Network(网络)——8
目录: Docker 为什么需要网络管理Docker 网络架构简介 CNMLibnetwork驱动常见网络类型 bridge 网络host 网络container 网络none 网络overlay 网络docker 网络管理命令 docker network createdocker network inspectdocker network connectdocker network disconne…...

网页设计--第6次课后作业
试用Vue相关指令完成对以下json数据的显示。显示效果如下: 其中:gender1 显示为女,gender2显示为男。价格超过30元,显示“有点小贵”。价格少于等于30元,则显示“价格亲民”。 data: {books: [{"id": "…...

R语言学习
Part1阶段1:入门基础 1安装R和RStudio: 下载并安装R:https://cran.r-project.org/ 下载并安装RStudio:https://www.rstudio.com/products/rstudio/download/ 2Hello World: 学习如何在R中输出"Hello, World!"…...

基于Unity3D 低多边形地形模型纹理贴图
在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时,有几种不同的风格…...

vue预览pdf,放大缩小拖动,dialog拖动,父页面滚动
公共组件部分代码 main.js import draggable from /directive/drag/index Vue.use(draggable) pdf组件部分代码...

泽攸科技二维材料转移台的应用场景及优势
随着二维材料的广泛研究和各种潜在应用的开发,对于二维材料样品的精密操控与转移的需求日益增加。特别是一些新型二维材料的制备和器件集成制备中,需要在显微镜下对样品进行观察与定位,并能够在微米甚至纳米量级上精确移動和转移样品。 传统…...

JavaScript——基本使用HelloWrold
1. 内部标签 html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><!--script标签内:写js代码 也可以写在body标签内--><script>alert(hello,world)&l…...

关于DNS服务器地址总是127.0.0.1且无法解析域名地址
问题 笔者尝试nslookup解释域名时,出现服务器变成本地环回口地址,导致无法解析域名 C:\Users\Zsy>nslookup www.baidu.com 服务器: UnKnown Address: 127.0.0.1*** UnKnown 找不到 www.baidu.com: Server failed排查思路 尝试关闭虚拟网卡&#…...

制作一个RISC-V的操作系统四-嵌入式开发介绍
文章目录 什么是嵌入式开发交叉编译查看一些GCC文件夹 调试器GDB相关语法命令 模拟器QEMUQEMU的安装和使用项目构造工具MakeMakeFile的构成make的运行 练习4-1练习4-2练习4-3 什么是嵌入式开发 程序跑到开发板上,或者说运行到硬件上 交叉编译 简单理解交叉编译来说…...

Python爬虫-实现批量抓取王者荣耀皮肤图片并保存到本地
前言 本文是该专栏的第12篇,后面会持续分享python爬虫案例干货,记得关注。 本文以王者荣耀的英雄皮肤为例,用python实现批量抓取“全部英雄”的皮肤图片,并将图片“批量保存”到本地。具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。注意,这里抓取的图片…...

04-详解Eureka注册中心的作用,具体配置,服务注册和服务发现
Eureka注册中心的作用 Eureka架构 远程调用的两个问题 服务的ip地址和端口号写死: 生产环境中服务的地址可能会随时发生变化,如果写死每次都需要重新修改代码多实例问题: 在高并发的情况下一个服务可以有多个实例形成一个集群,此时如果采用硬编码的方式只能访问服务的一个实…...

数据分析基础之《matplotlib(3)—散点图》
一、常见图形种类及意义 1、matplotlib能够绘制折线图、散点图、柱状图、直方图、饼图。我们需要知道不同的统计图的意义,以此来决定选择哪种统计图来呈现我们的数据 2、折线图plot 说明:以折线的上升或下降来表示统计数量的增减变化的统计图 特点&…...