深入理解 Linux Load Average

2023-05-16

一直不解,为什么io占用较高时,系统负载也会变高,偶遇此文,终解吾惑。

#1 load average介绍

##1.1 load average 指标介绍

uptime和top等命令都可以看到load average指标,从左至右三个数字分别表示1分钟、5分钟、15分钟的load average:


uptime

16:04:43 up 20 days, 6:08, 2 users, load average: 0.01, 0.00, 0.00

Load average的概念源自UNIX系统,虽然各家的公式不尽相同,但都是用于衡量正在使用CPU的进程数量和正在等待CPU的进程数量,一句话就是runnable processes的数量。所以load average可以作为CPU瓶颈的参考指标,如果大于CPU的数量,说明CPU可能不够用了。

但是, Linux上不是这样的!

Linux上的load average除了包括正在使用CPU的进程数量和正在等待CPU的进程数量之外,还包括uninterruptible sleep的进程数量。通常等待IO设备、等待网络的时候,进程会处于uninterruptible sleep状态。Linux设计者的逻辑是,uninterruptible sleep应该都是很短暂的,很快就会恢复运行,所以被等同于runnable。然而uninterruptible sleep即使再短暂也是sleep,何况现实世界中uninterruptible sleep未必很短暂,大量的、或长时间的uninterruptible sleep通常意味着IO设备遇到了瓶颈。众所周知,sleep状态的进程是不需要CPU的,即使所有的CPU都空闲,正在sleep的进程也是运行不了的,所以sleep进程的数量绝对不适合用作衡量CPU负载的指标,Linux把uninterruptible sleep进程算进load average的做法直接颠覆了load average的本来意义。所以在Linux系统上,load average这个指标基本失去了作用,因为你不知道它代表什么意思,当看到load average很高的时候,你不知道是runnable进程太多还是uninterruptible sleep进程太多,也就无法判断是CPU不够用还是IO设备有瓶颈。

参考资料:https://en.wikipedia.org/wiki/Load_(computing)

“Most UNIX systems count only processes in the running (on CPU) or runnable (waiting for CPU) states. However, Linux also includes processes in uninterruptible sleep states (usually waiting for disk activity), which can lead to markedly different results if many processes remain blocked in I/O due to a busy or stalled I/O system.“

##1.2 load_average 的含义

###1.2.1 如何衡量通车大桥的负荷

判断系统负荷是否过重,必须理解load average的真正含义。下面,我根据 “Understanding Linux CPU Load” 这篇文章,尝试用最通俗的语言,解释这个问题。

首先,假设最简单的情况,你的电脑只有一个CPU,所有的运算都必须由这个CPU来完成。

那么,我们不妨把这个CPU想象成一座大桥,桥上只有一根车道,所有车辆都必须从这根车道上通过。(很显然,这座桥只能单向通行。)

系统负荷为0,意味着大桥上一辆车也没有。

图片1

系统负荷为0.5,意味着大桥一半的路段有车。

图片 2

系统负荷为1.0,意味着大桥的所有路段都有车,也就是说大桥已经"满"了。但是必须注意的是,直到此时大桥还是能顺畅通行的。

图片 3

桥上在通车的时候, 不光桥上的车影响通车的效率, 后面排队等着还没有上桥的也对桥的拥挤程度有贡献, 因此我们有必要考虑这点, 如果把等待的那些车也算到负载中去, 那么负荷就会 > 1.0.

系统负荷为1.7,意味着车辆太多了,大桥已经被占满了(100%),后面等着上桥的车辆为桥面车辆的70%。以此类推,系统负荷2.0,意味着等待上桥的车辆与桥面的车辆一样多;系统负荷3.0,意味着等待上桥的车辆是桥面车辆的2倍。总之,当系统负荷大于1,后面的车辆就必须等待了;系统负荷越大,过桥就必须等得越久。

图片 4

###1.2.2 类比CPU的系统负荷

CPU的系统负荷,基本上等同于上面的类比。大桥的通行能力,就是CPU的最大工作量;桥梁上的车辆,就是一个个等待CPU处理的进程(process)。

如果CPU每分钟最多处理100个进程,那么系统负荷0.2,意味着CPU在这1分钟里只处理20个进程;系统负荷1.0,意味着CPU在这1分钟里正好处理100个进程;系统负荷1.7,意味着除了CPU正在处理的100个进程以外,还有70个进程正排队等着CPU处理。

为了电脑顺畅运行,系统负荷最好不要超过1.0,这样就没有进程需要等待了,所有进程都能第一时间得到处理。很显然,1.0是一个关键值,超过这个值,系统就不在最佳状态了,你要动手干预了。

###1.2.3 系统负荷的经验法则

1.0是系统负荷的理想值吗?

不一定,系统管理员往往会留一点余地,当这个值达到0.7,就应当引起注意了。经验法则是这样的:

当系统负荷持续大于0.7,你必须开始调查了,问题出在哪里,防止情况恶化。

当系统负荷持续大于1.0,你必须动手寻找解决办法,把这个值降下来。

当系统负荷达到5.0,就表明你的系统有很严重的问题,长时间没有响应,或者接近死机了。你不应该让系统达到这个值。

###1.2.4 多处理器的情形

上面,我们假设你的电脑只有1个CPU。如果你的电脑装了2个CPU,会发生什么情况呢?

2个CPU,意味着电脑的处理能力翻了一倍,能够同时处理的进程数量也翻了一倍。

还是用大桥来类比,两个CPU就意味着大桥有两根车道了,通车能力翻倍了。

图片 6

所以,2个CPU表明系统负荷可以达到2.0,此时每个CPU都达到100%的工作量。推广开来,n个CPU的电脑,可接受的系统负荷最大为n.0。

###1.2.5 多核处理器的情形

芯片厂商往往在一个CPU内部,包含多个CPU核心,这被称为多核CPU。

在系统负荷方面,多核CPU与多CPU效果类似,所以考虑系统负荷的时候,必须考虑这台电脑有几个CPU、每个CPU有几个核心。然后,把系统负荷除以总的核心数,只要每个核心的负荷不超过1.0,就表明电脑正常运行。

怎么知道电脑有多少个CPU核心呢?

"cat /proc/cpuinfo"命令,可以查看CPU信息。"grep -c ‘model name’ /proc/cpuinfo"命令,直接返回CPU的总核心数。

-###1.2.6 最佳观察时长

最后一个问题,"load average"一共返回三个平均值----1分钟系统负荷、5分钟系统负荷,15分钟系统负荷,----应该参考哪个值?

如果只有1分钟的系统负荷大于1.0,其他两个时间段都小于1.0,这表明只是暂时现象,问题不大。

如果15分钟内,平均系统负荷大于1.0(调整CPU核心数之后),表明问题持续存在,不是暂时现象。所以,你应该主要观察"15分钟系统负荷",将它作为电脑正常运行的指标。

#2 Loadavg分析

##2.1 读取 loadavg 的接口 /proc/loadavg

在内核中 /proc/loadavg 是通过 loadavg_proc_show 来读取相应数据,下面首先来看一下load_read_proc的实现:

# https://elixir.bootlin.com/linux/v5.2.13/source/kernel/sched/loadavg.c#L64

/**
 * get_avenrun - get the load average array
 * @loads: pointer to dest load array
 * @offset: offset to add
 * @shift: shift count to shift the result left
 *
 * These values are estimates at best, so no need for locking.
 */
void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
{
    loads[0] = (avenrun[0] + offset) << shift;
    loads[1] = (avenrun[1] + offset) << shift;
    loads[2] = (avenrun[2] + offset) << shift;
}

# http://elixir.bootlin.com/linux/v5.2.13/source/fs/proc/loadavg.c#13
static int loadavg_proc_show(struct seq_file *m, void *v)
{
    unsigned long avnrun[3];

    get_avenrun(avnrun, FIXED_1/200, 0);

    seq_printf(m, "%lu.%02lu %lu.%02lu %lu.%02lu %ld/%d %d\n",
        LOAD_INT(avnrun[0]), LOAD_FRAC(avnrun[0]),
        LOAD_INT(avnrun[1]), LOAD_FRAC(avnrun[1]),
        LOAD_INT(avnrun[2]), LOAD_FRAC(avnrun[2]),
        nr_running(), nr_threads,
        idr_get_cursor(&task_active_pid_ns(current)->idr) - 1);
    return 0;
}

几个宏的定义如下 :


# https://elixir.bootlin.com/linux/v5.2.13/source/include/linux/sched/loadavg.h#L43



#define FSHIFT 11 /* nr of bits of precision */

#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */

#define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */

#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */

#define EXP_5 2014 /* 1/exp(5sec/5min) */

#define EXP_15 2037 /* 1/exp(5sec/15min) */



#define LOAD_INT(x) ((x) >> FSHIFT)

#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)

根据输出格式,LOAD_INT对应计算的是load的整数部分,LOAD_FRAC计算的是load的小数部分。

将a=avenrun[0] + (FIXED_1/200)带入整数部分和小数部分计算可得:

$$avnrun_i = (avnrun_i + \frac{FIXED_1}{200}) <<11

= (avnrun_i+ 1>>11/200) <<11$$

= \frac{avnrun_i + \frac{2{11}}{200}}{2{11}}$$


LOAD_INT(a) = avnrun_i + \frac{2^{11}}{200}

LOAD_FRAC(a) = ((avenrun[0]%(2^11) + 2^11/200) * 100) / (2^11)
             = (((avenrun[0]%(2^11)) * 100 + 2^10) / (2^11)
             = ((avenrun[0]%(2^11) * 100) / (2^11) + ½

由上述计算结果可以看出,FIXED_1/200在这里是用于小数部分第三位的四舍五入,由于小数部分只取前两位,第三位如果大于5,则进一位,否则直接舍去。

临时变量a/b/c的低11位存放的为load的小数部分值,第11位开始的高位存放的为load整数部分。

因此可以得到a=load(1min) * 2^11

因此有: load(1min) * 2^11 = avenrun[0] + 2^11 / 200

进而推导出: load(1min)=avenrun[0]/(2^11) + 1/200

忽略用于小数部分第3位四舍五入的1/200,可以得到load(1min)=avenrun[0] / 2^11,即:

avenrun[0] = load(1min) * 2^11

avenrun是个陌生的量,这个变量是如何计算的,和系统运行进程、cpu之间的关系如何,在第二阶段进行分析。

##2.2 avenrun 如何表示CPU 负载

内核将 load的计算和load的查看进行了分离,avenrun就是用于连接load计算和load查看的桥梁。
下面开始分析通过avenrun进一步分析系统load的计算。

###2.2.1 avenrun 的更新

avenrun 数组是在 calc_global_load 中进行更新, 在系统更新了 calc_load_update 过了 10 个 jiffies 之后, 会在 do_timer 更新 jiffies 之后, 直接调用 calc_global_load 更新 avenrun 数组


do_timer

    -=> calc_global_load

# https://elixir.bootlin.com/linux/v5.2.13/source/kernel/sched/loadavg.c#L337
/*

 * calc_load - update the avenrun load estimates 10 ticks after the

 * CPUs have updated calc_load_tasks.

 *

 * Called from the global timer code.

 */

void calc_global_load(unsigned long ticks)

{

    unsigned long sample_window;

    long active, delta;



    sample_window = READ_ONCE(calc_load_update);

    if (time_before(jiffies, sample_window + 10))

        return;



    /*

     * Fold the 'old' NO_HZ-delta to include all NO_HZ CPUs.

     */

    delta = calc_load_nohz_fold();

    if (delta)

        atomic_long_add(delta, &calc_load_tasks);



    active = atomic_long_read(&calc_load_tasks);

    active = active > 0 ? active * FIXED_1 : 0;



    avenrun[0] = calc_load(avenrun[0], EXP_1, active);

    avenrun[1] = calc_load(avenrun[1], EXP_5, active);

    avenrun[2] = calc_load(avenrun[2], EXP_15, active);



    WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);



    /*

     * In case we went to NO_HZ for multiple LOAD_FREQ intervals

     * catch up in bulk.

     */

    calc_global_nohz();

}

calc_load_tasks 可以理解为当前系统中 RUNNING(R状态)进程和 uninterruptible(D状态)进程的总数目.

active_tasks为系统中当前贡献load的task数nr_active乘于FIXED_1,用于计算avenrun

avenrun 的计算方法 calc_load 如下所示:


# https://elixir.bootlin.com/linux/v5.2.13/source/include/linux/sched/loadavg.h#L19

/*

 * a1 = a0 * e + a * (1 - e)

 */

static inline unsigned long

calc_load(unsigned long load, unsigned long exp, unsigned long active)

{

    unsigned long newload;



    newload = load * exp + active * (FIXED_1 - exp);

    if (active >= load)

        newload += FIXED_1-1;



    return newload / FIXED_1;

}

用avenrun(t-1)和avenrun(t)分别表示上一次计算的avenrun和本次计算的avenrun,则根据CALC_LOAD宏可以得到如下计算:

avenrun(t)=(avenrun(t-1) * EXP_N + nr_active * FIXED_1*(FIXED_1 – EXP_N)) / FIXED_1

      = avenrun(t-1) + (nr_active*FIXED_1 – avenrun(t-1)) * (FIXED_1 -EXP_N) / FIXED_1

推导出:

avenrun(t) – avenrun(t-1) = (nr_active*FIXED_1 – avenrun(t-1)) * (FIXED_1 – EXP_N) / FIXED_1

将第一阶段推导的结果代入上式,可得:

(load(t) – load(t-1)) * FIXED_1 = (nr_active – load(t-1)) * (FIXED_1 – EXP_N)

进一步得到nr_active变化和load变化之间的关系式:

load(t) – load(t-1) = (nr_active – load(t-1)) * (FIXED_1 – EXP_N) / FIXED_1

这个式子可以反映的内容包含如下两点:

1)当nr_active为常数时,load会不断的趋近于nr_active,趋近速率由快逐渐变缓

2)nr_active的变化反映在load的变化上是被降级了的,系统突然间增加10个进程,

1分钟load的变化每次只能够有不到1的增加(这个也就是权重的的分配)。

另外也可以通过将式子简化为:

load(t)= load(t-1) * EXP_N / FIXED_1 + nr_active * (1 - EXP_N/FIXED_1)

这样可以更加直观的看出nr_active和历史load在当前load中的权重关系 (多谢任震宇大师的指出)


#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ 

#define EXP_5 2014 /* 1/exp(5sec/5min) */ 

#define EXP_15 2037 /* 1/exp(5sec/15min) */

1分钟、5分钟、15分钟对应的EXP_N值如上,随着EXP_N的增大,(FIXED_1 – EXP_N)/FIXED_1值就越小,

这样nr_active的变化对整体load带来的影响就越小。对于一个nr_active波动较小的系统,load会

不断的趋近于nr_active,最开始趋近比较快,随着相差值变小,趋近慢慢变缓,越接近时越缓慢,并最

终达到nr_active。如下图所示:

文件:load 1515.jpg(无图)

也因此得到一个结论,load直接反应的是系统中的nr_active。 那么nr_active又包含哪些? 如何去计算

当前系统中的nr_active? 这些就涉及到了nr_active的采样。

###2.2.2 calc_load_tasks 的更新


calc_load_tasks 常规情况下在 tick 中进行更新.

this_rq->calc_load_active 记录了当前 RQ 上 RUNNING(R状态)线程和 uninterruptible(D状态)线程的总数.

delta 为上次更新到现在 this_rq 上 R+D 状态进程的增量情况.

calc_load_tasks 则保存了当前系统中进程 R+D 状态进程的总数目.

LOAD_FREQ 被定义成 5HZ+1(5S 之后), 是更新 this_rq->calc_load_active 和 全局的 calc_load_tasks 的时间间隔, 每 LOAD_FREQ 才会更新一次.

this_rq->calc_load_update 总表示当前RQ 上下次执行 calc_global_load_tick 时可以进行更新的时间

在 calc_global_load_tick 中

  1. 先检查 calc_load_update 到期没,

  2. 到期后,

先更新了 this_rq->calc_load_active

接着更新了全局的 calc_load_tasks.

最后设置 this_rq->calc_load_update 为 LOAD_FREQ(5S) 之后.

因此每隔 LOAD_FREQ的时间, 系统在calc_global_load_tick 中基于 this_rq->calc_load_active, 更新 全局的calc_load_tasks.


# https://elixir.bootlin.com/linux/v5.2.13/source/kernel/sched/loadavg.c#L79

static long calc_load_fold_active(struct rq *this_rq)

{

        long nr_active, delta = 0;

 

        nr_active = this_rq->nr_running;

        nr_active += (long) this_rq->nr_uninterruptible;

 

        if (nr_active != this_rq->calc_load_active) {

                delta = nr_active - this_rq->calc_load_active;

                this_rq->calc_load_active = nr_active;

        }

 

        return delta;

}



# https://elixir.bootlin.com/linux/v5.2.13/source/kernel/sched/loadavg.c#L369

/*

 * Called from scheduler_tick() to periodically update this CPU's

 * active count.

 */

void calc_global_load_tick(struct rq *this_rq)

{

    long delta;



    if (time_before(jiffies, this_rq->calc_load_update))

        return;



    delta = calc_load_fold_active(this_rq, 0);

    if (delta)

        atomic_long_add(delta, &calc_load_tasks);



    this_rq->calc_load_update += LOAD_FREQ;

}

而 avenrun 则在 calc_load_update 更新 10 ticks 之后通过 calc_global_load 更新.

#3 参考资料

https://www.cnblogs.com/qqmomery/p/6267429.html

http://linuxperf.com/?p=176

https://scoutapm.com/blog/understanding-load-averages

http://www.ruanyifeng.com/blog/2011/07/linux_load_average_explained.html

http://www.blogjava.net/cenwenchu/archive/2008/06/30/211712.html

https://www.cnblogs.com/qqmomery/p/6267429.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入理解 Linux Load Average 的相关文章

  • 如何从类似于 eclipse 的命令行创建可运行的 jar 文件

    我知道 eclipse 会生成一个可运行的 jar 文件 其中提取并包含在该 jar 文件中的所有库 jar 文件 从命令提示符手动创建 jar 文件时如何执行类似的操作 我需要将所有 lib jar 解压到类文件夹中吗 目前我正在使用 j
  • 如何在 Linux 主机上的 docker 容器中挂载目录 [重复]

    这个问题在这里已经有答案了 我想将一个目录从 docker 容器挂载到本地文件系统 该目录是网站根目录 我需要能够使用任何编辑器在本地计算机上编辑它 我知道我可以跑docker run v local path container path
  • Linux 上的 Python 3.6 tkinter 窗口图标错误

    我正在从 Python GUI 编程手册 学习 Python GUI 某项任务要求我通过将以下代码添加到我的配方中来更改窗口图标 Change the main windows icon win iconbitmap r C Python3
  • 操作系统什么时候清除进程的内存

    进程在某些操作系统上成功或异常终止 操作系统何时决定擦除分配给该进程的内存 数据 代码等 在退出时或当它想为新进程分配内存时 这个清除内存分配过程在所有操作系统 winXP Win7 linux Mac 上都相同吗 据我了解 页表具有该进程
  • numpy 未定义符号:PyFPE_jbuf

    我正在尝试使用一百万首歌曲数据集 为此我必须安装 python 表 numpy cython hdf5 numexpr 等 昨天我设法安装了我需要的所有内容 在使用 hdf5 遇到一些麻烦之后 我下载了预编译的二进制包并将它们保存在我的 b
  • 怎样才能使 Windows 成为一个开箱即用的 POSIX 兼容操作系统?

    这个问题的动机是我的一个牵强的梦想 即 nix 平台上可用的许多优秀软件可以轻松移植到 Windows 微软最近对开源和开放性采取了不同的方法 所以我真的很想知道如果微软有这样的倾向 这样的事情会有多可行 我很好奇的一些更具体的事情是 是否
  • InstaPy:“错误,无法确定 64 位 Linux 的正确文件名”

    有人知道如何解决或解决这个问题吗 来自控制台的堆栈跟踪 执行后报告错误 InstaPy Version 0 6 9 Workspace in use home zanettra InstaPy Error unable to determi
  • 构建 makefile 依赖/继承树

    如果我解释得不好或者问了一些明显的问题 我很抱歉 但我是 Linux 内核的新手 而且有点深入 我们有一个嵌入式 Linux 系统 它附带一个 文档非常糟糕的 SDK 其中包含数百个文件夹stuff 大多数文件夹包含rules make m
  • git在Windows和Linux之间切换后强制刷新索引

    我有一个Windows和Linux共享的磁盘分区 格式 NTFS 它包含一个 git 存储库 约 6 7 GB 如果我只使用Windows or 只使用Linux操作 git 存储库一切正常 但是每次切换系统的时候git status命令将
  • 在Linux中断上下文中运行用户线程

    我正在编写一些定制的应用程序 并允许更改 Linux 内核中的中断处理程序代码 我有一个用户线程正在等待中断发生 如果发生中断 那么我要做的第一件事就是执行该用户线程 有什么办法让它发挥作用吗 Thanks 创建一个字符设备 这就是内核所做
  • 在 Ubuntu 16.04 上找不到 printf.c

    我最近切换到Ubuntu 16 04 我在用vscode作为 Ubuntu 上的 IDE 我配置了其他语言 但我无法做到这一点C C 我创建c cpp properties json launch json tasks json 当我开始编
  • 每个进程每个线程的时间量

    我有一个关于 Windows 和 Linux 中进程和线程的时间量子的问题 我知道操作系统通常为每个线程提供固定的时间量 我知道时间量根据前台或后台线程而变化 也可能根据进程的优先级而变化 每个进程有固定的时间量吗 例如 如果操作系统为每个
  • Linux shell 脚本:十六进制数字到二进制字符串

    我正在 shell 脚本中寻找一些简单的方法来将十六进制数字转换为 0 和 1 字符的序列 Example 5F gt 01011111 是否有任何命令或简单的方法来完成它 或者我应该为其编写一些开关 echo ibase 16 obase
  • linux x86 汇编语言 sys_read 调用的第一个参数应为 0 (stdin)

    我正在编写一个简单的汇编程序来从标准输入读取 如 scanf 这是我的代码 section bss num resb 5 section txt global start start mov eax 3 sys read mov ebx 0
  • 如何让“grep”从文件中读取模式?

    假设有一个很大的文本文件 我只想打印与某些模式不匹配的行 显然 我可以使用egrep v patter1 pattern2 pattern3 现在 如果所有这些模式都在一个文本文件中怎么办 最好的制作方法是什么egrep从文件中读取模式 g
  • 从 TypeScript 运行任何 Linux 终端命令?

    有没有办法直接从 TypeScript 类中执行 Linux 终端命令 这个想法是做类似的事情 let myTerminal new LinuxTerminal let terminalResult myTerminal run sudo
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • 如何查找连接到 AF_INET 套接字的客户端的 UID?

    有什么方法或类似的东西ucred for AF UNIX如果是AF INET插座 TCP在我的例子中 找出连接到我的套接字的客户端的UID 还有 proc net tcp但它显示了UID of the creator插座的而不是连接的cli
  • Linux shell 脚本中的 while 循环超时

    这工作正常 无限循环 while TRUE do printf done 我在尝试着timeout this while loop与timeout命令 所有这些都不起作用 timeout 5 while TRUE do printf don
  • PHP 致命错误:未找到“MongoClient”类

    我有一个使用 Apache 的网站 代码如下 当我尝试访问它时 我在 error log 中收到错误 PHP Fatal Error Class MongoClient not found 以下是可能错误的设置 但我认为没有错误 php i

随机推荐

  • Pytorch : Dataset和DataLoader

    一 综述 Dataset 对数据进行抽象 xff0c 将数据包装为Dataset类 DataLoader 在 Dataset之上对数据进行进一步处理 xff0c 包括进行乱序处理 xff0c 获取一个batch size的数据等 二 Dat
  • 特征工程

    一 数据读取 1 1 读取CSV文件 1 1 1 原文件内容 1 1 2 读取csv span class token keyword import span csv csv file span class token operator 6
  • 代码命名规范

    代码命名规范 现在是2016年12月30日中午12点35分 xff0c 这是我第一次写博客 xff0c 用的是markdown编辑器 xff0c 还不太会用 今天就先简单的写一下 xff0c 看看写出来的效果是什么样的 xff01 xff0
  • Ubuntu18.04 离线安装nginx

    由于服务器位于内网环境且无法访问互联网 xff0c 需要离线安装nginx xff0c ubuntu18 04离线安装软件也并不复杂 xff0c 只是需要较大的耐心去搜集所需的包 xff0c 不过大家不用担心 xff0c 我已经为大家准备好
  • easyui combobox动态绑定数据

    1 jsp上的写法 lt input span class hljs keyword class span 61 span class hljs string 34 easyui combobox 34 span id 61 span cl
  • Echarts(二、柱状图(各参数详细描述))

    1 jsp页面 span class hljs tag lt span class hljs title body span gt span span class hljs tag lt span class hljs title div
  • js中级脚本算法

    1区间求值算法挑战 span class hljs function span class hljs keyword function span span class hljs title sumAll span span class hl
  • 常用easyUI -icon 图标

    1 样式 代码 xff1a lt DOCTYPE html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt title gt Ea
  • vue与后台交互数据(vue-resource)

    需要引入库 xff1a vue resource lt script src 61 34 https cdn jsdelivr net vue resource 1 0 3 vue resource min js 34 gt lt scri
  • Tensorflow——jupyter notebook调用某个库时,出现找不到这个库情况的解决方案

    1 激活tensorflow环境 终端下输入 xff1a source activate tensorflow 2 进入jupyter notebook 出现如下问题 xff1a 没有找到matplotlib库 3 解决方法 在tensor
  • 组合排序题目汇总(排列组合、卡特兰数和递归思想)

    组合排序题目汇总 排列组合矩阵走法A必须在B左边站队互不相邻站队分糖果球放入桶吃糖 卡特兰数括号匹配进出栈顺序 售票顺序二叉树不同的结构数高矮排列 递归思想信封装信 排列组合 矩阵走法 在6 9的方格中 xff0c 以左上角为起点 xff0
  • java.lang.IllegalStateException 错误原因及解决方法小记

    java lang IllegalStateException Cannot perform this operation because the connection pool has been closed at android dat
  • 架构设计三原则

    1 简单原则 xff1b 分析完业务场景的结构复杂性和逻辑复杂性后 xff0c 从业务场景和解决问题的角度出发 xff0c 选择和设计能够满足需求的方案 在简单架构和复杂架构都能满足要求的时候 xff0c 优先选择简单架构 xff0c 因为
  • mybatis的resultMap property爆红

    span class token tag span class token tag span class token punctuation lt span resultMap span span class token attr name
  • Ubuntu20.04 rc-local 配置开机自启动脚本

    1 rc local服务简介 Linux中的rc local服务是一个开机自动启动的 xff0c 调用开发人员或系统管理员编写的可执行脚本或命令的 xff0c 它的启动顺序是在系统所有服务加载完成之后执行 ubuntu20 04系统已经默认
  • zynq7000 linux axi-gpio驱动:重置axi-gpio驱动方法

    linux gpio 从内核空间导出到用户空间 petalinux 在制作 Linux 系统时 xff0c 会自动的将 gpio 从内核空间导出到用户空间 xff0c 在用户空间下可以通过 sysfs 方式控制 gpio xff1b 用户空
  • AndroidManifest的理解

    最近做二次开发 xff0c 修改别人代码的时候发现清单文件中多了很多奇怪的属性和标签 xff08 自己以前没见过的 xff09 xff0c 在不明白的情况下直接开发出现了很多奇怪的问题 所以痛下决心 xff0c 重新复习下这些基础知识 以下
  • 使用 zsh 后HOME/END 键以及小键盘失效

    1 问题描述 zsh是一款超赞的shell工具 xff0c 但是配置复杂 xff0c 有个闲着没事的程序员 xff0c 弄了一个开源项目 robbyrussell oh my zsh 截止目前 xff0c 58 8k 43 star就知道有
  • 开启内核地址随机化KASLR后, qemu 调试 kernel 不能设置断点

    1 问题 gdb 断点异常 这几天更新了 qemu 然后在进行 gdb 调试的时候 发现断点断不住了 之前都是正常的 从来没有出现过这种情况啊 继续分析下看看是哪里出现的异常 2 原因分析 难道是 gdb 或者 QEMU 出现 BUG 了
  • 深入理解 Linux Load Average

    一直不解 xff0c 为什么io占用较高时 xff0c 系统负载也会变高 xff0c 偶遇此文 xff0c 终解吾惑 1 load average介绍 1 1 load average 指标介绍 uptime和top等命令都可以看到load