Linux CPU利用率

Linux CPU利用率

在线上服务器观察线上服务运行状态的时候,绝大多数人都是喜欢先用 top 命令看看当前系统的整体 cpu 利用率。例如,随手拿来的一台机器,top 命令显示的利用率信息如下

这个输出结果说简单也简单,说复杂也不是那么容易就能全部搞明白的。例如:

问题 1:top 输出的利用率信息是如何计算出来的,它精确吗?

问题 2:ni 这一列是 nice,它输出的是 cpu 在处理啥时的开销?

问题 3:wa 代表的是 io wait,那么这段时间中 cpu 到底是忙碌还是空闲?

原理介绍

CPU占用率是一个非常重要的指标,它反映了CPU在特定时间内的忙碌程度。

抛开Linux的实现先不谈,如果有如下需求,有一个四核服务器,上面跑了四个进程。

让你来设计计算整个系统CPU利用率的这个需求,支持像top命令这样的输出,满足一下要求:

  • cpu使用率要尽可能地准确;
  • 要能体现秒级瞬时cpu状态;

经过思考你会发现,这个看起来很简单的需求,实际还是有点小复杂的。其中一个思路是把所有进程的执行时间都加起来,然后再除以系统执行总时间*4。这个思路是没问题的,用这种方法统计很长一段时间内的CPU利用率是可以的,统计也足够准确。

但只要用过top你就知道,top输出的CPU利用率并不是长时间不变的,而是默认3秒为单位会动态更新一下,(这个时间间隔可以使用-d设置)。我们的这个方案体现总利用率可以,体现这种瞬时的状态就难办了。你可能会想到那我也3秒算一次不就行了?但这个3秒的时间从哪个点开始呢?粒度很不好控制。

上一个思路问题核心就是如何解决瞬时问题。提到瞬时状态,你可能就又来思路了。那我就用瞬时采样去看,看看当前有几个核在忙。四个核中如果有两个核在忙,那利用率就是50%。这个思路思考的方向也是正确的,但是问题有两个:

  • 你算出的数字都是25%的整数倍;
  • 这个瞬时值会导致CPU使用率显示的剧烈震荡。

比如下图:

在t1的瞬时状态看来,系统的CPU利用率毫无疑问就是100%,但在t2时间看来,使用率又编程0%。思路方向是对的,但显然这种粗暴的计算无法像top命令一样优雅地工作。

我们再改进一下它,把上面两个思路结合起来,可能就能解决我们的问题了。在采样上,我们把周期定的细一些,但在计算上我们把周期定的粗一些。

我们引入采样周期的概念,定时比如每1毫秒采样一次。如果采样的瞬时,cpu在运行,就将这1ms记录为使用,这时会得出一个瞬时的cpu使用率,把它都存起来。

在统计3秒内的CPU使用率的时候,比如途中的t1和t2这段时间范围。那就把这段时间内的所有瞬时值全加一下,取个平均值。这样就能解决上面的问题了,统计相对准确,避免了瞬时值剧烈震荡且粒度过粗(只能以25%为单位变化)的问题了。

可能有同学会问了,假如cpu在两次采样中间发生变化了呢,如下图这种情况:

在当前采样点到来的时候,进程A其实刚执行完,有一点点时间既没有被上一个采样点统计到,本次也统计不到。对于进程B,其实只开了一小端时间,把1ms全记上似乎有点多记了。

确实会存在这个问题,但因为我们的采样是1ms一次,而我们实际查看使用的时候最少也是秒级别地用,会包括有成千上万个采样点的信息,所以这种误差并不会影响我们对全局的把握。

事实上,Linux也就是这样来统计系统CPU利用率的。虽然可能会有误差,但作为一项统计数据使用已经是足够了的。在实现上,Linux是将所有的瞬时值都累加到某一个数据上的,而不是真的存了很多份的瞬时数据。

接下来就让我们进入Linux来查看它对系统CPU利用率统计的具体实现。

原始数据

上一节我们说的Linux在实现上是将瞬时值都累加到某一个数据上的,这个值是内核通过/proc/stat伪文件来对用户态暴露。Linux在计算系统CPU利用率的时候用的就是它。

整体上看,top命令工作的内部细节如下图所示:

  • top命令访问/proc/stat获取各项CPU利用率使用值;
  • 内核调用stat_open函数来处理对/proc/stat的访问
  • 内核访问的数据来源于kernel_cpustat数组,并汇总;
  • 打印输出给用户态;

接下来我们把每一步都展开来详细看看。

通过使用strace跟踪top命令的各种系统调用,可以看的到它对该文件的调用。

# strace top

...

openat(AT_FDCWD, "/proc/stat", O_RDONLY) = 4

openat(AT_FDCWD, "/proc/2351514/stat", O_RDONLY) = 8

openat(AT_FDCWD, "/proc/2393539/stat", O_RDONLY) = 8

除了/proc/stat外,还有各个进程细分的/proc/pid/stat,是用来计算各个进程的CPU利用率时使用的。

内核为各个伪文件都定义了处理函数,/proc/stat文件的处理方法是:

proc_stat_operations。//file:fs/proc/stat.c

staticint__init proc_stat_init( void)

{

proc_create( "stat", 0, NULL, &proc_stat_operations);

return0;

}

staticconststructfile_operationsproc_stat_operations= {

.open = stat_open,

...

};

proc_stat_operations 中包含了该文件时对应的操作方法。当打开 /proc/stat 文件的时候,stat_open 就会被调用到。stat_open 依次调用 single_open_size,show_stat 来输出数据内容。我们来看看它的代码:

//file:fs/proc/stat.c

staticintshow_stat(struct seq_file *p, void*v)

{

u64 user, nice, system, idle, iowait, irq, softirq, steal;

for_each_possible_cpu(i) {

structkernel_cpustat* kcs= & kcpustat_cpu( i);

user += kcs->cpustat[CPUTIME_USER];

nice += kcs->cpustat[CPUTIME_NICE];

system += kcs->cpustat[CPUTIME_SYSTEM];

idle += get_idle_time(kcs, i);

iowait += get_iowait_time(kcs, i);

irq += kcs->cpustat[CPUTIME_IRQ];

softirq += kcs->cpustat[CPUTIME_SOFTIRQ];

...

}

//转换成节拍数并打印出来

seq_put_decimal_ull(p, "cpu ", nsec_to_clock_t(user));

seq_put_decimal_ull(p, " ", nsec_to_clock_t(nice));

seq_put_decimal_ull(p, " ", nsec_to_clock_t(system));

seq_put_decimal_ull(p, " ", nsec_to_clock_t(idle));

seq_put_decimal_ull(p, " ", nsec_to_clock_t(iowait));

seq_put_decimal_ull(p, " ", nsec_to_clock_t(irq));

seq_put_decimal_ull(p, " ", nsec_to_clock_t(softirq));

...

}

在上面的代码中,for_each_possible_cpu 是在遍历存储着 cpu 使用率数据的 kcpustat_cpu 变量。该变量是一个 percpu 变量,它为每一个逻辑核都准备了一个数组元素。里面存储着当前核所对应各种事件,包括 user、nice、system、idel、iowait、irq、softirq 等。

在这个循环中,将每一个核的每种使用率都加起来。最后通过 seq_put_decimal_ull 将这些数据输出出来。

注意,在内核中实际每个时间记录的是纳秒数,但是在输出的时候统一都转换成了节拍单位。至于节拍单位多长,下一节我们介绍。总之,/proc/stat的输出是从kernel_cpustat这个percpu变量中读取出来的。

我们接着再看看这个变量中的数据是何时加进来的。

统计数据怎么来的

前面我们提到内核是以采样的方式来统计cpu使用率的。这个采样周期依赖的是Linux时间子系统中的定时器。

Linux内核每隔固定周期会发出timer interrupt,这有点像乐谱中的节拍的概念。每隔一段时间就打出一个拍子,Linux就响应之并处理一些事情。

一个节拍的长度是多长时间,是通过CONFIG_HZ来定义的。它定义的方式是每一秒有几次timer interrupts。不同的系统中这个节拍的大小可能不同,通常在1ms到10ms之间。可以在自己的linux config文件中找到它的配置。

# grep ^CONFIG_HZ /boot/config-5.4.56.bsk.10-amd64

CONFIG_HZ=1000

从上述结果中可以看出,我的机器的每秒要打出1000次节拍。

rk3568每秒钟的节拍树为300:

每次当时间中断到来的时候,都会调用update_process_times来更新系统时间。更新后的时间都存储在我们前面提到的percpu变量kcpustat_cpu中。

 

 我们来详细看下汇总过程 update_process_times 的源码,它位于 kernel/time/timer.c 文件中。

//file:kernel/time/timer.c

voidupdate_process_times( intuser_tick)

{

structtask_struct* p= current;

//进行时间累积处理

account_process_tick(p, user_tick);

...

}

这个函数的参数user_tick指的是采样的瞬间是处于内核态还是用户态。接下来调用account_process_tick。

//file:kernel/sched/cputime.c

voidaccount_process_tick(struct task_struct *p, intuser_tick)

{

cputime = TICK_NSEC;

...

if(user_tick)

//3.1 统计用户态时间

account_user_time(p, cputime);

elseif((p != rq->idle) || (irq_count != HARDIRQ_OFFSET))

//3.2 统计内核态时间

account_system_time(p, HARDIRQ_OFFSET, cputime);

else

//3.3 统计空闲时间

account_idle_time(cputime);

}

这 这个函数中,首先设置cputime=TICK_NSEC,一个TICK_NSEC的定义是一个节拍所占的纳秒数。接下俩根据判断劫夺分别执行account_user_time,account_system_time和account_idle_time来统计用户态、内核态和空闲时间。

用户态时间统计

3.1 用户态时间统计 //file:kernel/sched/cputime.c

voidaccount_user_time(struct task_struct *p, u64 cputime)

{

//分两种种情况统计用户态 CPU 的使用情况

intindex;

index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;

//将时间累积到 /proc/stat 中

task_group_account_field(p, index, cputime);

......

}

account_user_time函数主要分两种情况统计:

  • 如果进程的nice值大于0,那么将会增加到cpu统计结构的nice字段中;
  • 如果进程的nice值小于等于0,那么增加到cpu统计结构的user字段中。

看到这里,开篇的问题2就有答案了,其实用户态的时间不只是user字段,nice也是。之所以要把nice分出来,是为了让Linux用户更一目了然地看到调过nice的进程所占的CPU周期有多少。

我们平时如果想要观察系统的用户态消耗的时间的话,应该是将top中输出的user和nice加起来一并考虑,而不是只看user。

接着调用task_group_acconut_field来把时间加到前面我们用到的kernel_cpustat内核变量中。

//file:kernel/sched/cputime.c

staticinlinevoidtask_group_account_field(struct task_struct *p, intindex,

u64 tmp)

{

__this_cpu_add(kernel_cpustat.cpustat[index], tmp);

...

}

 内核态时间统计

我们再来看内核态时间是如何统计的,找到account_system_time的代码。

//file:kernel/sched/cputime.c

voidaccount_system_time(struct task_struct *p, inthardirq_offset, u64 cputime)

{

if(hardirq_count - hardirq_offset)

index = CPUTIME_IRQ;

elseif(in_serving_softirq)

index = CPUTIME_SOFTIRQ;

else

index = CPUTIME_SYSTEM;

account_system_index_time(p, cputime, index);

}

内核态的时间主要分3中情况进行统计。

  • 如果当前处于硬中断执行上下文,那么统计到irq字段中;
  • 如果当前处于软中断执行上下文,那么统计到softirq字段中;
  • 否则统计到system字段中

判断好要加到哪个统计项中后,一次调用account_system_index_time、task_group_account_field来将这段时间加到内核变量kernel_cpustat中。也就是说system+irq+softirq等于内核态占用CPU的比率。

//file:kernel/sched/cputime.c

staticinlinevoidtask_group_account_field(struct task_struct *p, intindex,

u64 tmp)

{

__this_cpu_add(kernel_cpustat.cpustat[index], tmp);

}

空闲时间的累积 

每一个 CPU 核心都会有一个 idle 进程,idle 进程是当系统没有调度 CPU 资源的时候,会进入 idle 进程,而 idle 进程的作用就是不使用 CPU,以此达到省电的目的。

在ARM64架构中,当CPU Idle时,会调用WFI指令(wait for interrupt),关掉CPU的Clock以便降低功耗,当有外设中断触发时,CPU又会恢复回来。

没错,在内核变量kernel_cpustat中不仅仅统计了各种用户态、内核态的使用统计,空闲也一并统计起来了,如果在采样的瞬间,cpu既不在内核态也不在用户态的话,就将当前节拍的时间都累加到idle中。

//file:kernel/sched/cputime.c

voidaccount_idle_time(u64 cputime)

{

u64 *cpustat = kcpustat_this_cpu->cpustat;

structrq* rq= this_rq;

if(atomic_read(&rq->nr_iowait) > 0)

cpustat[CPUTIME_IOWAIT] += cputime;

else

cpustat[CPUTIME_IDLE] += cputime;

}

在CPU空闲的情况下,进一步判断是不是在等待IO(例如磁盘IO),如果是的话这段空闲时间会加到iowait中,否则就加到idle中。从这里,我们可以看懂iowait其实是cpu的空闲时间,只不过是在等待IO完成而已。

看到这里,开篇问题3 也有非常明确的答案了,io wait其实是CPU在空闲状态的一项统计,只不过这种状态和idle的区别是cpu是因为等待io而空闲。

总结

本文深入分析了Linux统计系统CPU利用率的内部原理。全文的内容可以用如下一张图来汇总:

Linux中的定时器会以某个固定节拍,比如1ms一次采样各个cpu核的使用情况,然后将当前节拍的所有时间都累加到/user/nice/system/irq/softirq/io_wait/idle中的某一项上,这些项的总和为100%。

top命令是读取的/proc/stat中输出的CPU各项利用率数据,而这个数据在内核中的是根据kernel_cpustat来汇总并输出的。

回到开篇问题1,top输出的利用率信息是如何计算出来的,它精确吗?

/proc/stat文件输出的是某个时间点的各个指标所占用的节拍树。如果想像top那样输出一个百分比,计算过程是分两个时间点t1,t2分别获取一下stat文件中的相关输出,然后经过个简单的算术运算便可以算出当前的CPU利用率。

#!/bin/bash

#获取宿主机的 CPU 使用情况
function get_host_cpu_usage(){
	#内核会在/proc/stat中输出整机CPU的使用情况, 例如:cat /proc/stat 输出如下
	#cpu  52635657 657000 57094567 7675992570 422057 0 545206 0 0 0
	#其中各列中的数值都是从启动到现在的累计和,单位是jiffies
	#除了第一列外,其余每列的含义分别是:
	#  1.user:用户态花费的cpu时间
	#  2.nice:用户态在低优先级花费的cpu时间
	#  3.system:系统态花费的cpu时间
	#  4.idel:在空闲任务上花费的cpu时间
	#  5.iowait:等待I/O花费的cpu时间
	#  6.irq:硬中断花费的cpu时间
	#  7.softirq:软中断花费的cpu时间
	#  8.steal:系统处在虚拟化环境中,你的虚拟机被其他虚拟机占用的 CPU 时间
	#  9.guest:运行虚拟机花费的cpu时间
	#  10.guest_nice:运行低优先级虚拟机花费的cpu时间

	#获取宿主机的 CPU 用量的原理,是选择两个时间点,
	#cpu总时间=user+system+nice+idle+iowait+irq+softirq
	#cpu_usage=100-(idle2-idle1)/(cpu总时间2-cpu总时1)*100

	T1_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
	T1_IDLE=$(echo $T1_CPU_INFO | awk '{print $4}')
	T1_TOTAL=$(echo $T1_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')

	sleep 10

	T2_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
	T2_IDLE=$(echo $T2_CPU_INFO | awk '{print $4}')
	T2_TOTAL=$(echo $T2_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')

    CPU_UTILIZATION=`echo ${T1_IDLE} ${T1_TOTAL} ${T2_IDLE} ${T2_TOTAL}| awk '{printf "%.2f", (1-($3-$1)/($4-$2))*100}'`
	echo "Host CPU Utiliztion:${CPU_UTILIZATION}%"
}

get_host_cpu_usage

 再说是否准确,这个统计方法是采样的,只要是采样,肯定就不是百分之百精确。但由于我们查看CPU使用率的时候往往都是计算1秒甚至更长一段时间的使用情况,这其中会包含很多采样点,所以查看整体情况问题是不大的。

另外从本文,我们也学到了top中输出的CPU的时间项目其实大致可以分为三类:

第一类:用户态消耗时间。包括user和nice。如果想看用户态的消耗,要将user和nice加起来看才对。

第二类:内核态消耗时间。包括irq, softirq和system;

第三类:空闲时间,包括io_wait和idle。其中io_wait也是cpu的空闲状态,只不过是在等io完成而已。如果只是想看CPU到底有多闲,应该把io_wait和idle加起来才对。

mpstat命令

`mpstat` 是一个在 Linux 系统中用于监控多处理器系统性能的工具,全称为 Multiprocessor Statistics。它提供了实时查询每个 CPU 的性能指标以及所有 CPU 的平均指标的功能。`mpstat` 是 `sysstat` 工具集中的一部分,而 `sysstat` 是 Linux 系统性能分析的重要工具集。

`mpstat` 的基本语法为 `mpstat [options] [interval [count]]`,其中:

  • `options` 是命令的参数,包括:
    • `-P { cpu [,...] | ON | ALL }`:指定要报告其统计信息的 CPU。使用 `ALL` 表示报告所有 CPU 的统计信息。
    • `interval`:相邻两次采样的间隔时间。
    • `count`:采样的次数。如果没有指定 `count`,则采样次数为无限次,并在结束后打印平均值。

`mpstat` 的输出包含了多个列,每列代表不同的 CPU 使用率指标,包括:

  • `%usr`:用户态使用的 CPU 百分比。
  • `%nice`:使用 nice 命令对进程进行降级时 CPU 的百分比。
  • `%sys`:内核进程使用的 CPU 百分比。
  • `%iowait`:等待进行 I/O 所使用的 CPU 时间百分比。
  • `%irq`:用于处理系统中断的 CPU 百分比。
  • `%soft`:用于软件中断的 CPU 百分比。
  • `%steal`:虚拟机强制 CPU 等待的时间百分比。
  • `%guest`:虚拟机占用 CPU 时间的百分比。
  • `%idle`:CPU 的空闲时间的百分比。

安装 `mpstat` 通常需要安装 `sysstat` 工具集,安装方法可能因不同的 Linux 发行版而异。例如,在 CentOS 上可以使用 `yum install sysstat` 命令进行安装,而在 Ubuntu 上可以使用 `apt install sysstat`。

RK3568多核CPU的利用率

如果表示我们系统负载高,那么通过top命令查看到的CPU利用率是四个核的平均值吗?之前我们看到单个应用进程占用的CPU利用率超过了100%。

---top 命令看版本。
你截图中的版本,应该是以单核统计的。
单核统计的时候,如果出现多核运行,就会出现COMMAND运行CPU超过100%。

你的截图中,就是系统CPU总占用只有28左右,其中25%都是74中断代码占用的。

如果说系统总占用28%的话,理论上即便一个核被沾满,系统也不应该会挂死吧?还有其他3个核是可以正常运行的,那是不是就可以说明死机并不是由于单个CPU被中断占满导致的?

------top 这个100%只能是参考。他和死机没有必然联系。只是说,这个方向有可能。

如果是CPU0被中断“完全”挂死,响应不了其他中断,也是有可能引起死机的。

有什么办法判断是哪个CPU挂死了呢?
CPU0在挂死之前,会有异常日志打印到串口吗?我们现在死机的时候,串口上没有任何打印。

----怀疑和cpu 100%占用相关,可以写个脚本,监控top,看是哪个程序跑满了cpu

top命令实现

我们使用的top命令一般都是busybox中的:

root@jenet:/usr/bin# busybox
BusyBox v1.32.0 (2022-11-23 22:18:06 CST) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --show SCRIPT
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

        BusyBox is a multi-call binary that combines many common Unix
        utilities into a single executable.  Most people will create a
        link to busybox for each function they wish to use and BusyBox
        will act like whatever it was invoked as.

但是rk3568自己提供了一个top程序:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[Java基础揉碎]System类

1) exit 退出当前程序 2) arraycopy: 复制数组元素,比较适合底层调用,一般使用 Arrays.copyOf完成复制数组(Arrays.copyOf其实底层也是用的System.arraycopy, 本质是一样的) int[] src{1,2,3}; int[] dest new int[3]; System.arraycopy(src, 0, des…

【SpringBoot3】Bean管理

1.Bean扫描 1.1传统Spring 标签&#xff1a;<context:component-scan base-package"com. example "/>注解&#xff1a;ComponentScan(basePackages "com.example") 1.2SpringBoot SpringBoot默认扫描启动类所在的包及其子包 2.Bean注册 如果要注…

【力扣 Hot100 | 第一天】4.10 两数相加

文章目录 1.两数相加&#xff08;4.10&#xff09;1.1题目1.2解法一&#xff1a;模拟1.2.1解题思路1.2.2代码实现 1.两数相加&#xff08;4.10&#xff09; 1.1题目 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c…

Docker容器应用为工业连接提供了新选择

一 智能数据管理 Docker容器应用能够被灵活部署在异构计算平台上&#xff0c;且仅需占用少量的资源&#xff0c;这可为工业4.0提供一种新的数据集成方案。Docker容器应用程序是提供特定功能的小型软件模块&#xff0c;可在自动化领域中用于智能数据管理。而Softing推出的新产品…

day55 最长递增子序列 最长连续递增子序列 最长重复子数组

题目1 300 最长递增子序列 题目链接 300 最长递增子序列 题意 找到整数数组nums的最长严格递增子序列的长度&#xff08;子序列并不改变原始的顺序&#xff0c;但是可以删除元素&#xff09; 动态规划 动规五部曲 1&#xff09;dp数组及下标i的含义 dp[i] 表示以nums[i…

【现代C++】委托构造函数

现代C中的委托构造函数&#xff08;Delegating Constructors&#xff09;是C11引入的特性&#xff0c;它允许一个构造函数调用同一个类中的另一个构造函数&#xff0c;以避免代码重复。这种特性在初始化对象时提高了代码的复用性和清晰性。 1. 基本用法 在同一个类中&#xf…

Harmony鸿蒙南向驱动开发-MMC

MMC&#xff08;MultiMedia Card&#xff09;即多媒体卡&#xff0c;是一种用于固态非易失性存储的小体积大容量的快闪存储卡。 MMC后续泛指一个接口协定&#xff08;一种卡式&#xff09;&#xff0c;能符合这种接口的内存器都可称作MMC储存体。主要包括几个部分&#xff1a;…

似曾相识:面向重复类型故障的可操作故障定位

导读 搜索引擎、在线视频和电子银行等在线服务系统在人们的日常生活中有着越来越重要的作用。但是&#xff0c;由于在线服务系统包含众多有着复杂依赖关系的组件&#xff08;例如服务器、容器和微服务等等&#xff09;&#xff0c;在线服务系统中的故障难以避免&#xff0c;并…

49 样式迁移【李沐动手学深度学习v2课程笔记】

1. 样式迁移&#xff08;Style Transfer) 计算机视觉的应用之一&#xff0c;将样式图片中的样式&#xff08;比如油画风格等&#xff09;迁移到内容图片&#xff08;比如实拍的图片&#xff09;上&#xff0c;得到合成图片 可以理解成为一个滤镜&#xff0c;但相对于滤镜来讲…

leetcode 常考题-动态规划算法-单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1&#xff1a; 输入: s "leetcode"…

七分钟,拿下口头offer

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen &#x1f9d1;‍&#x1f4bb;&#x1f9d1;‍&#x1f4bb;面2&#xff1a;行了…

每日一题 — 最大连续 1 的个数III

解法一&#xff1a;暴力枚举 先定义left和right双指针&#xff0c;left先固定在起始位置&#xff0c;遍历right当值等于1的时候&#xff0c;直接跳过&#xff0c;等于0的时候&#xff0c;zero计数器加一当zero等于k的时候&#xff0c;就开始记录此时最大长度是多少然后left加一…

做抖店要用到的东西:什么是精选联盟?开通到使用一篇详解!

哈喽~我是电商月月 做抖音小店的新手朋友在翻阅资料时一定接触过精选联盟这个东西 但它到底是干嘛的&#xff1f;如何开通。又是如何使用&#xff01;还没入手的朋友是不知道的 所以&#xff0c;今天我就给大家讲解一下精选联盟的入驻方法&#xff0c;以及在运营时要怎么正确…

蓝桥杯第十届c++大学B组详解

目录 1.组队 2.年号字符 3.数列求值 4.数的分解 5.迷宫 6.特别数的和 7.完全二叉树的权值 8.等差数列 9.后缀表达式 10.灵能传输 1.组队 题目解析&#xff1a;就是在个篮球人中选择这个最大的成绩&#xff0c;每个人只能选择一次不能重复选择。选满5人之后的成绩是最…

企业如何部署有效的防泄密软件策略?

在企业信息化飞速发展的今天&#xff0c;数据泄露的后果可能是灾难性的&#xff0c;不仅会导致经济损失&#xff0c;还可能损害公司的声誉。因此&#xff0c;制定和部署一个全面而有效的防泄密软件策略对于防范这种风险至关重要。策略的目标不仅是阻止外部攻击&#xff0c;更要…

《C++程序设计》阅读笔记【7-堆和拷贝构造函数】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;《C程序设计》阅读笔记 本文对应的PDF源文件请关注微信公众号程序员刘同学&#xff0c;回复C程序设计获取下载链接。 1 堆与拷贝构造函数1.1 概述1.2 分配堆对象1.3 拷贝构造函数1.3.1 默…

多线程(进阶篇小白易懂版)

文章目录 多线程为什么要有多线程多线程案例线程通讯分传主线程通讯主传分关闭线程线程锁 多线程 概念&#xff1a;多线程就是多个线程同时工作的过程&#xff0c;我们可以将线程看作是程序的执行路径&#xff0c;每个线程都定义了一个独特的控制流&#xff0c;用来完成特定的…

DataX 数据库同步部分源码解析

在工作中遇到异构数据库同步的问题,从Oracle数据库同步数据到Postgres&#xff0c;其中的很多数据库表超过百万&#xff0c;并且包含空间字段。经过筛选&#xff0c;选择了开源的DataXDataX Web作为基础框架。DataX 是阿里云的开源产品&#xff0c;大厂的产品值得信赖&#xff…

【JavaWeb】Day39.MySQL概述——数据库设计-DQL(二)

数据库设计-DQL 聚合函数 聚合函数查询就是纵向查询&#xff0c;它是对一列的值进行计算&#xff0c;然后返回一个结果值。&#xff08;将一列数据作为一个整体&#xff0c;进行纵向计算&#xff09; 语法&#xff1a; select 聚合函数(字段列表) from 表名 ; 注意 : 聚合…

LeetCode 热题 100 | 多维动态规划(二)

目录 1 5. 最长回文子串 2 1143. 最长公共子序列 菜鸟做题&#xff0c;语言是 C 1 5. 最长回文子串 核心思想&#xff1a;把总问题拆解为若干子问题。 总问题&#xff1a;从第 i 个字母到第 j 个字母是回文串子问题&#xff1a;从第 i 1 个字母到第 j - 1 个字母是回文…