使用Process Explorer/Process Hacker和Windbg排查软件高CPU占用问题

news2024/11/14 22:42:43

目录

1、问题说明

2、Process Explorer与Windbg工具介绍

2.1、Process Explorer工具

2.2、Windbg调试器

3、引发程序高CPU占用的原因分析

4、在任务管理器和Process Explorer中查看目标程序的CPU占用

5、使用Process Explorer和Process Hacker查看占用CPU高的线程

5.1、使用Process Explorer查看占用CPU高的线程

4.2、使用Process Hacker查看占用CPU高的线程

4.3、Process Hacker介绍

6、使用Windbg分析占用线程较高的线程

6.1、使用!runaway命令查看线程占用的CPU时间

6.2、Windbg中不仅能看到详细函数调用堆栈,还能看到函数中变量的值


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html       无论软件工程的理念多么先进,开发进度安排多么的合理,亦或是开发人员的经验多么丰富,大家在开发调试软件的过程中总会遇到这样那样的问题。随着软件规模和复杂性的不断增加,错误的出现频次以及分析调试的难度也在以非线性的方式持续增长。要提高分析与处理问题的效率,采用合适的分析思路与分析调试工具是非常重要的。有时,一个需要数天时间才能解决的问题,如果换一种分析调试思路或者借助某个合适的排查工具,或许只需1个小时就可以解决。今天我们以一个项目中遇到的问题实例,给大家分享排查软件CPU占用高的思路以及常用的分析工具,以供大家借鉴或参考。

1、问题说明

       上周一领导反馈在运行我们的软件时笔记本出现明显发烫,到任务管理器中查看软件进程的CPU占用值达到了20%之多:(这个地方使用示例程序的截图为例)

在当前系统中占用的CPU明显高于其他进程。这台笔记本是采购没多久的,机器的性能还是不错的,按讲不应该出现这么大的CPU消耗。 并且软件在登录成功后,并没有做任何操作,没有执行任何消耗CPU的音视频编解码操作。

       之前遇到过类似的问题,分析下来怀疑是系统中自带的defender杀毒程序引起的,因为一般杀毒软件会远程注入到程序进程中,程序执行的一些比较可疑的话,杀毒软件会持续的跟踪与监测,可能会导致程序占用的CPU比较。后来,该领导在其电脑上安装了其他杀毒软件,以为就不会出现上述CPU占用高的问题,结果这次又出现了!所以估计还是我们的软件有问题,还是要从软件内部找原因!

       当时在排查这个问题时没有保留相关截图和素材,所以下面将以一个示例程序,详细介绍如何使用Process Explorer和Windbg去高效地分析这类CPU占用高的问题。

2、Process Explorer与Windbg工具介绍

       在日常工作中,常用的排查软件问题排查工具有Dependency Walker、GDIView、Process Explorer(或者Process Hacker)、Process Monitor、API Monitor、Windbg调试器、IDA汇编工具等。使用这些工具,可以高效的分析和排查软件运行过程遇到的多种问题。关于这些工具的详细说明,在此我就不再赘述了,可以参见我写的文章:

C++软件开发值得推荐的十大高效软件分析工具icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/127608247        关于使用这些工具排查项目问题的实例,可以参考我的两篇专栏,专栏中有详细的项目案例介绍,有很强的实战参考价值:

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++常用软件分析工具从入门到精通案例集锦汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795

2.1、Process Explorer工具

2.1.1、Process Explorer功能介绍

       Process Explorer是Winternals公司(该公司已经被微软收购)开发的增强版任务管理器软件工具(procexp.exe),功能要比Windows系统自带的任务管理器的功能多很多。使用该工具可以查看服务、进程、线程(可以查看进程及进程中各个线程的CPU占用情况,可以用来分析程序高CPU占用问题)、模块(可以查看程序都加载了哪些dll模块,可以确定动态加载的dll有没有加载起来)、句柄(查看进程中使用的所有句柄,可以分析句柄泄漏问题)、磁盘使用状态、网络使用状态等多类信息。日常工作中使用较多免费工具Process Explorer和Process Monitor,都是Winternals公司开发的免费工具,被放置在Sysinternals Suite工具包中。

Sysinternals Suite包含了一系列免费的系统工具,其中有大名鼎鼎的Process Explorer、Process Monitor、FileMon、RegMon等,如果把系统管理员比喻成战士的话,那么Sysinternals Suite就是战士手中的良兵利器。熟悉和掌握这些工具,并且对Windows的体系有一定的了解,将大幅度的提高日常的诊断和排错能力。

2.1.2、Process Explorer的开发者Mark Russinovich

       说到Sysinternals Suite工具包,就必须要说一下该工具包的开发者Mark Russinovich(马克·拉希诺维奇),他是技术界的一个传奇人物。Mark Russinovich,是全球顶尖的Windows内核技术专家、现任微软Azure云(微软云计算平台)CTO。

当前微软云在全球云计算市场的占有率仅次于亚马逊云,全球排名第三的则是中国的阿里云。

2.1.2.1、Mark Russinovich与微软的”情缘“

       Mark Russinovich(马克·拉希诺维奇),1994年博士毕业于美国卡内基梅隆大学,开始从事 Windows 相关的软件开发工作。拥有计算机天赋的Mark,很快就走上了创业之路,于1996年与Bryce Cogswell(布赖·科格斯韦尔)创立Winternals软件公司。该公司为了解决工程师平常在工作上遇到的各种问题,开发出Process Explorer、Process Monitor等许多小工具。之后他们将这些工具集合起来称为Sysinternals,并完全免费,得到众多技术人的好评。

       90 年代后期,微软依靠 Windows 操作系统主宰科技界,从台式机到笔记本电脑、工作站、服务器都运行着 Windows。那个时候 Mark Russinovich 白天为一家小型软件公司开发软件,晚上与周末就在家里寻找 Windows NT 中的错误、缺陷和秘密,并且将这些信息发布到网络上,也因此经常激怒微软。Mark Russinovich 还对当时的 NT Workstation 和 NT Server 进行了逆向工程,并发现了微软人为改变市场使其以有利于自己的方式运作的行为,即微软可以强制所有网络服务使用更昂贵的操作系统,同时为其他任务销售更便宜的版本。Mark Russinovich 还为此开发了一款可以将 NT Workstation 转换为 NT Server 的工具,这也惹怒了微软,几天后他在参加微软活动的时候被拒绝进入大楼。不过,Mark Russinovich 与微软的爱恨情仇也帮他打开了加入微软的大门。

       2006年,微软为了得到Mark Russinovich这个全球顶尖的Windows内核专家,一举收购了Winternals软件公司。Mark在加盟微软后,以技术小组成员的身份,负责Windows操作系统内核的开发工作,并成为微软的技术院士,这也是全公司最重要的技术职位。

微软对Mark心仪已久,时任微软平台和服务部门工程师杰森对Mark评价道:“他是目前世界上Windows系统最需要的五个人之一!
时任微软公司部门总裁吉姆·阿辛 (Jim Allchin)也表示:“我已经关注马克很久了,他和合作伙伴创造出了一套完善的系统恢复和数据保护软件,相信他的加盟将为 Windows操作系统的开发带来巨大的推动作用。

2.1.2.2、Mark Russinovich与微软 Azure 云

       Mark除了拥有众多跨界技能外,在技术研究领域里也横跨系统、安全、云计算等。其中在2010年云计算刚发展时,马克已开始涉足。2010年,微软云计算产品Azure全面上线。Azure是基于云计算的操作系统,主要目标是为开发者提供一个平台,帮助开发可运行在云服务器、数据中心、Web和PC上的应用程序。开发者可使用微软全球数据中心的储存、计算能力和网络基础服务。

       2010年的Azure还叫“Windows Azure”,此时马克已成为Azure技术团队的一员,主力解决与Fabric控制器相关的难题。Fabric控制器是Windows Azure操作系统内核,它为运行在Azure上的应用程序提供服务和管理基础设施。

       Mark曾撰写博客《Windows Azure 主机更新:原因、时间和方式》,详细介绍Azure主机操作系统和原理、PaaS更新流程等技术细节。

        Azure刚推出时,微软将其打造为PaaS产品,推出计算服务、Azure Blob存储服务、SQL Azure数据库服务、Azure Service Bus四大服务。后来随着开源软件和云计算的发展,微软发现用IaaS的形式更易于控制。微软一是调整自身云发展战略,宣布将 Windows Azure 更名为 Microsoft Azure;二是进行技术调整,Mark与时任开发者工具与平台集团副总裁的Scott Guthrie挑起这重任,打破重重技术难关,联手重构了PaaS版本的Windows Azure,打造出微软Azure的IaaS全新形态。

       在Mark等人的努力下,如今Azure 是一个很完整的云平台,集成开发、测试、部署和管理应用程序所需的云服务,提供计算、AI、存储、混合、安全等综合服务平台。作为微软Azure云的重要参与者与见证人,Mark成为了微软Azure CTO(目前仍在任)。

2.1.2.3、C/C++与Rust语言之争

       “说到语言,现在是时候停止用 C/C++ 启动任何新项目了,并在那些需要使用 non-GC 语言的场景中使用 Rust。为了安全性和可靠性,业界应该宣布弃用这些语言。”这是去年Mark Russinovich在其社交账号上公开发布的动态。

       作为Azure CTO,他的言论一石激起千层浪。随后C++之父 Bjarne Stroustrup的隔空回应又让这场辩论再添一丝火药味道:“新的语言通常需要多年的时间和重大的努力,才能在其广泛的应用领域中与成熟的语言相媲美。发烧友们很少看到这一点,他们的评论往往是相当片面的。”

       且不论这场battle结果如何,微软官方虽然没有明确表态,但在拥抱Rust的力度上却是在稳步推进的。

由于各种技术和历史原因,Windows主要是用C和C++编写的。大多数用户模式代码现在都是用C++编写的,但大多数内核代码仍然是用C编写的。微软一些新推出的技术模块已经开始使用Rust语言去开发了。

2.2、Windbg调试器

        Windbg是微软出品的Windows平台下强大的用户态和内核态调试工具,与微软的IDE工具Visual Studio相比,它是一个轻量级的调试工具。所谓轻量级指的是安装快速轻便,但其调试功能,却比Visual Studio更为强大。

       Windbg的主界面如下所示:

我们主要使用Windbg去分析软件异常与崩溃问题。在日常工作中,大部分情况下我们都是用Windbg去事后静态分析dump文件去排查问题,有时也需要使用Windbg去动态调试目标进程。

      至于何时使用Windbg静态分析,何时使用Windbg进行动态调试,可以参见我的文章:

何时使用Windbg静态分析?何时使用Windbg动态调试?icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131806819      使用Windbg静态分析dump文件的完整步骤,可以参见我的文章:
使用Windbg静态分析dump文件的一般步骤及要点详解icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/130873143      使用Windbg动态调试目标进程的完整步骤,可以参见我的文章:

使用Windbg动态调试目标进程的一般步骤及要点详解icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131029795

3、引发程序高CPU占用的原因分析

       一般情况下,导致程序高CPU都是因为程序中出现了死循环导致的,死循环导致代码一直在不停歇的执行,占用了大量的CPU资源,表现为CPU占用高。通过项目实战,我们可以总结出引发死循环的几个常见的原因,主要有以下几种:

1)for或while循环中的循环条件有问题
       可能是因为写代码时手误,将循环条件中的i <=5,误写成了i = 5,导致循环条件一直为真,所以出现了死循环。也有可能是循环条件中使用了服务器传过来的数值,结果这个数值是个异常大的值(可能是服务器传过来的源数据有问题,也可能是数据接收端在解析数据时解析错了),导致死循环。比如服务器传过来的视频通道数nVideoChannelNum,正常情况下是个10以内的整数值,结果实际传过来的是个异常大的值,所以循环条件为int i < nVideoChannelNum出现了死循环。
2)函数调用上的死循环
       可能是函数调用上的死循环,比如A函数调用了B函数,B函数调用了C函数,而C函数又调用了A函数,所以形成了函数调用上的闭环,即函数调用上的死循环。也有可能是Windows窗口消息触发的,比如某窗口消息WM_XXXXX的响应函数A中调用了B函数,而B函数中的代码又促使该窗口产生了WM_XXXXX消息,这样间接地导致了函数调用上的死循环(消息引发的)。这两个问题场景,我们在实际的项目中都遇到过。
3)线程函数中没有加Sleep
       我们在程序中会大量地使用线程,去并发地执行相关的任务。线程函数中一般都会弄一个while循环,在程序运行期间循环条件一直为真,线程代码一直在不停歇的运行。但要注意的是,我们一般都需要在线程函数的循环体中人为地添加Sleep,让线程时不时休息一下,不能让其一直在执行任务,否则就类似于死循环,会导致高CPU占用。这点很多开发新手不太了解,需要注意一下。我们以前排查过一个掩藏很深的问题,就于这种场景有关,可以参见我之前写的文章:

使用Process Explorer查看线程的函数调用堆栈去排查程序高CPU占用问题icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/132830803

4、在任务管理器和Process Explorer中查看目标程序的CPU占用

       笔记本发烫,一般都是CPU高频度使用引起的,所以第一反应就是去任务管理器中查看CPU占用情况。下面我们以TestDlg.exe为例,故意在该程序的线程执行死循环的代码,使相关线程一直在跑,模拟真实场景中的实例。

       打开任务管理器看到我们的TestDlg.exe程序占用了最高比例的CPU,如下所示:

于是打开Process Explorer,看看到底是程序中的哪个线程CPU占用高。结果打开后,发现Process Explorer中显示的CPU占用居然和任务管理器中的不一样:

难道是Process Explorer版本太老,对Win10的兼容性不太好?因为显示的不准,查看线程的CPU占用比例也会受影响。

       于是想到另一个类似的工具Process Hacker,下载之,打开后查看好像CPU占用比例也和系统的任务管理器不一样,如下:

后来无意中发现,在Windows任务管理器中切换到详细信息标签页下:

 居然和进程标签页下的CPU占用(25%)不一样,大概相差了一半,这个着实有点让人费解啊!

5、使用Process Explorer和Process Hacker查看占用CPU高的线程

       对于CPU占用高的问题,我们需要使用工具Process Explorer或Process Hacker,看看是哪个线程占用CPU高,然后去查看线程的函数调用堆栈。通过调用堆栈中的函数去确定目标线程对应源码中的哪个业务线程。

       Process Explorer和Process Hacker在功能上是类似的,但在某些细节上还是有一些差异的,下面我们分别使用这两个工具去查看占用CPU高的线程信息,看看相关的差异。

5.1、使用Process Explorer查看占用CPU高的线程

       先看Process Explorer,在进程列表中直接双击目标进程TestDlg.exe,弹出进程的属性页面,然后点击Treads标签(Tab)页,就能看到进程的线程列表:

我们可以看到进程中有两个线程,其中线程id为28564的线程占用了较高的CPU。但单从线程id无法确定其是源代码中的哪个线程,于是双击线程行,弹出该线程的函数调用堆栈,如下所示:

       通过函数调用堆栈,我们可以对照着源码,就知道其是源码中的哪个线程了。从堆栈中看到,调用了CTestDlgDlg::OnBnClickedButton1接口,确实也是该接口中的for循环出现死循环,导致线程一直在不停歇的运行,导致了高CPU占用。

       有时我们需要在上述调用堆栈页面中,点击Refresh多次刷新函数调用堆栈,才能看到有效的调用堆栈。但有时会刷新出完全不相干的函数调用堆栈,比如在此处我们点击Refreash按钮刷新一下,堆栈就不完整了,也显示不全了:

4.2、使用Process Hacker查看占用CPU高的线程

       使用Process Hacker查看线程信息的步骤和Process Explorer是类似的,现在进程列表中双击目标进程,然后在弹出的进程属性窗口中点击Threads标签页切换到线程列表页面,也可以看到占用CPU较高的线程:

然后双击占用CPU较高的那个线程,就能查看到该线程的函数调用堆栈,如下:

也看到了CTestDlgDlg::OnBnClickedButton1接口的调用。可以多次点击Refresh按钮刷新函数调用堆栈,每次都可以显示有效的函数调用堆栈,在本问题中每次刷新后的函数调用堆栈中都能看到CTestDlgDlg::OnBnClickedButton1接口的调用。

       所以,要查看线程的有效的函数调用堆栈,用Process Hacker更好一点!

4.3、Process Hacker介绍

       上面我们已经详细介绍了Process Explorer工具,我们再来大概地介绍一下Process Hacker工具。

       Process Hacker 是一个免费开源的进程浏览器和内存编辑器,可以用来显示 Windows 系统下的服务、进程、线程、模块、句柄以及内存等信息它不仅能够帮助你查看管理进程,同时也能进行系统监视和内存编辑,帮助你监视系统资源、调试软件和检测恶意软件。

如果在Process Hacker官网下载不了该工具,可以到其他下载网站上去下载即可。

       Process Hacker相对于Process Explorer,功能差不多,UI界面更炫一点,在查看线程的函数调用堆栈时更有效一些。

       此外,从关于页面可以看出,该软件工具是一个华人开发的:

最重要一点,Process Hacker是完全免费开源的,如果要实现该工具中的部分功能,可以直接去下载源码参考。

6、使用Windbg分析占用线程较高的线程

        可以直接将Windbg附加到CPU占用高的进程上,然后使用!runaway命令查看进程中各线程的CPU时间片占用情况,时间片占用多的线程可能就是当前占用CPU较高的线程。关于!runaway命令,可以参看Windbg自带的帮助文档:(在菜单栏中点击Help -> Index,即可打开chm帮助文档)

6.1、使用!runaway命令查看线程占用的CPU时间

        打开Windbg,在菜单栏中点击File -> Attach to a Process...,在弹出的进程列表中找到目标进程TestDlg.exe,然后点击确定,即附加到该进程上。附加到目标进程上后,Windbg自动中断下来,按下g命令就可以让目标程序继续运行。我们此刻要输入!runaway 7命令,查看当前进程中的线程时间片占用情况,则需要先让Windbg中断下来,点击菜单栏中的Debug -> Break,即可中断下来。于是输入!runaway 7命令,回车,看到如下的信息:

显示的时间片信息中包含用户态时间片、内核态时间片和从程序启动到当前的时间,我们主要看用户态的时间片,因为我们的业务代码基本都是运行在用户态的。

       从上图中可以看出,线程id为0x6f94(16进制)的线程占用的用户态时间片最多。但这个地方需要注意一下,占用时间片多,不代表就是当前时刻占用CPU最高的线程。可以辅助Process Explorer或Process Hacker查看占用CPU较高的那个线程id,如下所示:

从图中看到,占用CPU较高线程的线程id为28564,而0x6f94 = 28564,说明Windbg中显示的0号线程id为0x6f94的线程就是CPU占用最高的线程。

       于是使用~0s切换到0号线程(线程id前面的序号就是线程序号),然后输入kn查看此时的函数调用堆栈:

Windbg中显示的函数调用堆栈应该是最精准的!调用堆栈中也看到了CTestDlgDlg::OnBnClickedButton1接口的调用。

6.2、Windbg中不仅能看到详细函数调用堆栈,还能看到函数中变量的值

       有人可能会说,既然Process Explorer中能看到函数调用堆栈,为啥还要用Windbg呢?一方面是要介绍使用Windbg排查的方法,另一方面Windbg中除了可以看到完整的函数调用堆栈,还能查看到函数调用堆栈中函数中的变量的值,可以辅助定位问题。

       在本例中,可以点击函数调用堆栈每一行前面的序号,展开该函数去查看函数中相关变量的值。比如点击TestDlg!CTestDlgDlg::OnBnClickedButton1+0x99所在函数行前面的序号0e,就能查看CTestDlgDlg::OnBnClickedButton1函数中相关变量的值,如下所示:

从图中可以看到for循环中的变量i是一个异常大的值,这正是问题所在。

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

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

相关文章

安装 MySQL 服务时提示 Install/Remove of the Service Denied

安装 MySQL 服务时提示 Install/Remove of the Service Denied 1. 概述1.1 问题1.2 没有 MySQL 服务的时候 2. 解决方法 1. 概述 1.1 问题 在安装 MySQL-8.0.25-winx64 的 MySQL 服务时遇到了以下提示&#xff1a; 安装 MySQL 服务时提示&#xff1a;、 Install/Remove of t…

【c++|opencv】一、基础操作---3.访问图像元素

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 访问图像元素 1. 访问图像像素 1.1 访问某像素 //灰度图像&#xff1a; image.at<uchar>(j, i) //j为行数&#xff0c;i为列数 //BGR彩色图像 i…

清华 ChatGLM-6B 中文对话模型部署简易教程

本文目录 一、前言二、下载三、部署3.1 配置环境3.2 启动 demo 程序3.2.1 启动 cli_demo.py3.2.2 启动 web_demo.py 四、【最新】ChatGLM-6B-int4 版本教程4.1 下载4.2 配置环境4.3 启动 demo 程序 五、华为 CodeLab 免费 GPU 平台部署 ChatGLM-6B-int4&#xff08;CPU版&#…

移植wpa_supplicant及简单使用

嵌入式环境下的设备有时会需要能连接到外网进行一些数据的交互&#xff0c;通过利用wpa_supplicant客户端结合有线网卡或无线网卡&#xff0c;即可配置好网络达到目的。 资源&#xff1a;openssl-0.9.8e.tar.gz wpa_supplicant-0.7.3.tar.gz 源代码下载路径一&#xff1a;http…

激光雷达,被降本“牺牲”?

激光雷达&#xff0c;正在成为车企「价格战」的牺牲品。尤其是纯视觉方案带来的巨大显性降本效应&#xff0c;开始动摇车企的传感器配置策略。 本周&#xff0c;随着极越01的上市&#xff0c;相比去年发布的探月版车型39.98万的定价&#xff0c;大幅下降至24.99-33.99万&#…

【c++|opencv】二、灰度变换和空间滤波---1.灰度变换、对数变换、伽马变换

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 灰度变换、对数变换、伽马变换 1. 灰度变换 #include <iostream> #include <opencv2/opencv.hpp>using namespace std; using namespace c…

pytorch复现2_AlexNet

不涉及原理 AlexNet网络结构 代码&#xff1a; model&#xff1a; import torch.nn as nn import torchclass AlexNet(nn.Module):def __init__(self, num_classes1000, init_weightsFalse):super(AlexNet, self).__init__()self.features nn.Sequential(nn.Conv2d(3, 48, k…

mongdb 存在重复字段值,建立唯一索引失败

1. 插入两条相同的数据 db.user.insertOne({name:"test",age:30, })2. 创建索引 db.user.createIndex({name:1},{unique: true});3. 报错

《2023北京智慧城市创新应用案例集》丨附下载

✦ ✦✦ ✦✦ ✦✦ ✦ 建设数字中国是数字时代推进中国式现代化的重要引擎&#xff0c;是构筑国家竞争新优势的有力支撑。党的二十大报告提出要提高城市规划、建设、治理水平&#xff0c;“打造宜居、韧性、智慧城市”&#xff1b;要加快发展数字经济&#xff0c;促进数字经济…

常用 sqlite3 命令

本次将向您讲解 SQLite 编程人员所使用的简单却有用的命令。这些命令被称为 SQLite 的点命令&#xff0c;这些命令的不同之处在于它们不以分号 ; 结束。 让我们在命令提示符下键入一个简单的 sqlite3 命令&#xff0c;在 SQLite 命令提示符下&#xff0c;您可以使 用各种 …

PTA 树的同构

题目 给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2&#xff0c;则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的&#xff0c;因为我们把其中一棵树的结点A、B、G的左右孩子互换后&#xff0c;就得到另外一棵树。而图2就不是同构的。 现给定两棵树…

广播机制-广播接收者BroadcastReceiver

在Android中&#xff0c;广播是一种在组件之间传递消息的机制&#xff0c;例如电池电量低时会发送一条提示如果要接收并过滤广播中的消息&#xff0c;则需要使用Broadcast Receiver&#xff08;广播接收者&#xff09;。广播接收者是Android四大组件之一&#xff0c;通过广播接…

dockerfile中临时拉取gitlab代码

git clone https://<name>:<token>gitlab.com/<USER>/<REPO>.git

基于STM32F103C8T6的UAV飞控板硬件设计

一、主控单元&#xff1a; 主控单元基于意法半导体公司的STM32F103C8T6单片机进行设计。STM32F103C8T6DE 内核为ARM Cortex-M3&#xff1b;最大主频&#xff1a;72MHz &#xff1b;工作电压范围&#xff1a;2V~3.6V &#xff1b;程序存储容量&#xff1a;64KB&#xff1b; 程序…

qtableview委托应用

https://download.csdn.net/download/venice0708/88485153

Python构造代理IP池提高访问量

目录 前言 一、代理IP是什么 二、代理IP池是什么 三、如何构建代理 IP 池 1. 从网上获取代理 IP 地址 2. 对 IP 地址进行筛选 3. 使用筛选出来的 IP 地址进行数据的爬取 四、总结 前言 爬虫程序是批量获取互联网上的信息的重要工具&#xff0c;在访问目标网站时需要频…

【广州华锐互动】牛顿运动定律VR虚拟教学软件

在科技日新月异的今天&#xff0c;虚拟现实&#xff08;VR&#xff09;技术已经逐渐渗透到各个领域&#xff0c;为我们带来了前所未有的沉浸式体验。在教育领域&#xff0c;VR技术的应用也日益广泛&#xff0c;尤其是在物理教学中&#xff0c;牛顿运动定律VR虚拟教学软件为学生…

预制件二维码怎么生成

在建筑施工领域&#xff0c;预制构件的使用越来越广泛&#xff0c;它能够提高工程质量和施工效率&#xff0c;减少施工现场对环境的影响。通过凡尔码的二维码管理平台&#xff0c;用户可以实现预制构件的高效管理&#xff0c;并提升施工效率和施工质量 预制件二维码怎么生成 准…

org.springframework.cloud:spring-cloud-starter-openfeign:jar is missing详解

openfeign无法导入的问题 我感觉最近带的好几个新人在搭建springCloud基础框架的时候&#xff0c;会犯一个非常小的错误&#xff0c;导致进度卡住了。 这个错误就是Feign导入的错误&#xff1a; ‘dependencies.dependency.version’ for org.springframework.cloud:spring-c…

乐鑫 SoC 内存映射入门

微控制器 (MCU) 的性能和内存能力逐步提升&#xff0c;其复杂度也随之加大。特别是当用户需要配置内存管理单元来映射外部存储器芯片 (Flash/SPIRAM) 时&#xff0c;这种现象尤其明显。 开始在乐鑫 SoC 上运行 Zephyr RTOS 时&#xff0c;会发现这些 SoC 与 ARM 架构的 MCU 相…