Linux部署程序之glibc兼容性问题

news2024/11/24 1:36:46

Linux部署程序之glibc兼容性问题

在部署程序的时候,一般会遇到glibc不兼容的问题,现象如下:

/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21’ not found

在此之前先要了解一下 gcc/glibc/libc/libstdc++ 是什么东东。

gcc/glibc/libc/libstdc++

Linux下开发时经常会遇到 libc、glib、glibc、eglibc、libc++、libstdc++、gcc、g++ 它们都是什么?

gcc/g++

GCC 是 GNU 编译器集合的意思(GNU Compiler Collection), 它可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada等语言。

  • gcc是GCC中的GUN C Compiler(C 编译器)
  • g++是GCC中的GUN C++ Compiler(C++编译器)

🗣️就本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的GUN编译器而已,比如,用gcc编译一个c文件的话,会有以下几个步骤:

  • Step1:Call a preprocessor, like cpp.
  • Step2:Call an actual compiler, like cc or cc1.
  • Step3:Call an assembler, like as.
  • Step4:Call a linker, like ld

由于编译器是可以更换的,所以gcc不仅仅可以编译C文件。

所以,更准确的说法是:gcc调用了C compiler,而g++调用了C++ compiler

具体而言

  • g++ 会把 .c 文件当做是 C++ 语言 (在 .c 文件前后分别加上 -xc++ 和 -xnone, 强行变成 C++), 从而调用 cc1plus 进行编译.
  • g++ 遇到 .cpp 文件也会当做是 C++, 调用 cc1plus 进行编译.
  • g++ 还会默认告诉链接器, 让它链接上 C++ 标准库.
  • gcc 会把 .c 文件当做是 C 语言. 从而调用 cc1 进行编译.
  • gcc 遇到 .cpp 文件, 会处理成 C++ 语言. 调用 cc1plus 进行编译.
  • gcc 默认不会链接上 C++ 标准库.

libc

libc 是 linux 下的旧C ANSI C函数库,也就是 #include < stdio.h> 定义的地方,后来逐渐被glibc取代,也就是 GNU C Library。此外还有klibc、uclibc,但现在用的最多的是 glibc。

主流的一些linux操作系统如 Debian, Ubuntu,Redhat等用的都是glibc。

那 ANSI C 函数库是基本的 C 语言函数库,包含了 C 语言最基本的库函数。这个库可以根据头文件划分为 15 个部分,其中包括:

  1. <ctype.h>:包含用来测试某个特征字符的函数的函数原型,以及用来转换大小写字母的函数原型;
  2. <errno.h>:定义用来报告错误条件的宏;
  3. <float.h>:包含系统的浮点数大小限制;
  4. <math.h>:包含数学库函数的函数原型;
  5. <stddef.h>:包含执行某些计算 C 所用的常见的函数定义;
  6. <stdio.h>:包含标准输入输出库函数的函数原型,以及他们所用的信息;
  7. <stdlib.h>:包含数字转换到文本,以及文本转换到数字的函数原型,还有内存分配、随机数字以及其他实用函数的函数原型;
  8. <string.h>:包含字符串处理函数的函数原型;
  9. <time.h>:包含时间和日期操作的函数原型和类型;
  10. <stdarg.h>:包含函数原型和宏,用于处理未知数值和类型的函数的参数列表;
  11. <signal.h>:包含函数原型和宏,用于处理程序执行期间可能出现的各种条件;
  12. <setjmp.h>:包含可以绕过一般函数调用并返回序列的函数的原型,即非局部跳转;
  13. <locale.h>:包含函数原型和其他信息,使程序可以针对所运行的地区进行修改。
  14. 地区的表示方法可以使计算机系统处理不同的数据表达约定,如全世界的日期、时间、美元数和大数字;
  15. <assert.h>:包含宏和信息,用于进行诊断,帮助程序调试。

由于libc逐渐被glibc取代,所以就不在介绍

glibc

glibc是linux下面c标准库的实现,即GNU C Library。glibc本身是GNU旗下的C标准库,后来逐渐成为了Linux的标准c库,而Linux下原来的标准c库Linux libc逐渐不再被维护。

由于 Linux 是用 C 语言写的,所以 Linux 的一些操作是用 C 语言实现的,因此,GUN 组织开发了一个 C 语言的库 以便让我们更好的利用 C 语言开发基于 Linux 操作系统的程序。 不过现在的不同的 Linux 的发行版本对这两个函数库有不同的处理方法,有的可能已经集成在同一个库里了。

glibc在/lib目录下的.so文件为libc.so.6

那glibc都做了些什么呢?

glibc是Linux系统中最底层的API,几乎其它任何的运行库都要依赖glibc。

glibc最主要的功能就是对系统调用的封装。怎么能在C代码中直接用fopen函数就能打开文件? 打开文件最终还是要触发系统中的sys_open系统调用,而这中间的处理过程都是glibc来完成的。

查看 glibc 的版本

vincent@msi-creator-15:~$ 
---➤ ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31
Copyright (C) 2020 自由软件基金会。
这是一个自由软件;请见源代码的授权条款。本软件不含任何没有担保;甚至不保证适销性
或者适合某些特殊目的。
由 Roland McGrath 和 Ulrich Drepper 编写。
vincent@msi-creator-15:~$ 
---➤ strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.29
GLIBC_2.30
GLIBC_PRIVATE
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.2) stable release version 2.31.

eglibc

这里的eEmbedded的意思,也就是前面说到的变种glibc。

eglibc的主要特性是为了更好的支持嵌入式架构,可以支持不同的shell(包括嵌入式),但它是二进制兼容glibc的,就是说如果你的代码之前依赖eglibc库,那么换成glibc后也不需要重新编译。

曾经 ubuntu 使用过一段时间 eglibc。
在这里插入图片描述
在这里插入图片描述

从 Debian 8.0 之后 ubuntu 又切换回 glibc 了。

glib

glib也是个c程序库,不过比较轻量级,glib 可以在多个平台下使用,比如 Linux、Unix、Windows 等。

📢 glib 是 Gtk+ 库和 Gnome 的基础

那它跟glibc有什么关系吗?

其实,glib 和 glibc 基本上没有太大联系,可能唯一的共同点就是,其都是 C 编程需要调用的库而已。

libc++

libc++是llvm搞的,是C++标准库的实现,clang++ 默认的 stdlib 链接库。但是一般 Linux 都不会自带它,即使安装了 clang 也不会带,要手动安装。因为 clang 对 libstdc++的支持会更好 😅

libstdc++

libstdc++ 是 gcc 对C++ 标准库的实现,g++ 默认的 stdlib 链接库。

Debian 自带了 libstdc++ 动态库,路径一般是 /lib/x86_64-linux-gnu/libstdc++.so.6

libstdc++与gcc是捆绑在一起的,也就是说安装gcc的时候会把libstdc++装上。

那为什么glibc和gcc没有捆绑在一起呢?

相比glibc,libstdc++虽然提供了c++程序的标准库,但它并不与内核打交道。对于系统级别的事件,libstdc++首先是会与glibc交互,才能和内核通信。相比glibc来说,libstdc++就显得没那么基础了。

查看 libstdc++ 支持的 GLIBCXX 版本

GLIBCXX和GLIBC是两个东西,前者针对C++,后者针对C。

vincent@msi-creator-15:~$ 
---➤ strings /lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21
GLIBCXX_3.4.22
GLIBCXX_3.4.23
GLIBCXX_3.4.24
GLIBCXX_3.4.25
GLIBCXX_3.4.26
GLIBCXX_3.4.27
GLIBCXX_3.4.28
GLIBCXX_DEBUG_MESSAGE_LENGTH

场景

开发环境为gcc 11.1.0,glibc版本是2.31,但是生产环境的 glibc 是2.14。

那么编译好的程序如何在生产环境中运行呢?后续会讲解。

这里要提到一个知识点,比如我们当前的系统是 ubuntu 20.04,系统默认安装的是 gcc 9.3.0,glibc版本是2.31。

vincent@msi-creator-15:~$ 
---➤ gcc-9 --version
gcc-9 (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
vincent@msi-creator-15:~$ 
---➤ ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31
Copyright (C) 2020 自由软件基金会。
这是一个自由软件;请见源代码的授权条款。本软件不含任何没有担保;甚至不保证适销性
或者适合某些特殊目的。
由 Roland McGrath 和 Ulrich Drepper 编写。

但是我们如何使用更高版本的gcc呢,一般来说有两种方式:

  1. 通过 apt 来安装
  2. 通过源码编译安装

有时我们可以通过apt进行安装,但往往版本不会太新,如果想使用比较新的gcc,就要通过源码的方式安装。

那么编译源码使用的是 gcc 9.3.0 版本的编译器去编译 gcc 11.1.0 版本的代码

📢 编译更高版本的gcc可能需要更高版本的编译器

编译好的 gcc 11.1.0 是不带有 glibc 库的,依赖的还是 glibc 2.31。

也就是说通过 gcc 11.1.0 编译的程序最终是依赖 glibc 2.31,除非自行编译了更高版本的 glibc 。

但是 libstd++ 是和gcc版本挂钩的,也就是编译 gcc 的时候就会生成 libstdc++.so 动态库。

案例介绍

当前系统环境:

  • gcc 6.3.0
  • glibc 2.24
  • glibcxx 3.4.22

目标系统环境:

  • gcc 4.8.5
  • glibc 2.17
  • glibcxx 3.4.19

示例程序:

//regex.cpp

#include<iostream>
#include <regex>

using namespace std;

int main()
{  
    // gcc 4.8.5 run error
    std::regex m_regex("[a-z]+");
    std::cout << std::regex_match("abc", m_regex) << std::endl;

    return 0;
}

编译运行

g++ -o regex regex.cpp

查看 regex 运行所需要的动态库有哪些,通过 ldd 查看。

$ ldd regex
        linux-vdso.so.1 (0x00007fff087f9000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fdeb0b41000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdeb083d000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fdeb0626000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdeb0287000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fdeb1103000)

可以看到主要的两个库 libc.so.6libstdc++.so.6 都是使用系统内默认的。

如果此时把 regex 程序拷贝到 gcc 4.8.5 环境中运行将会报错。

$ ./regex
./regex: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./regex)
./regex: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./regex)

可以看出 regex 运行最低需要 GLIBCXX_3.4.21 版本。

那在看看 regex 运行所需要的动态库。

$ ldd regex
./regex: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./regex)
./regex: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./regex)
        linux-vdso.so.1 =>  (0x00007ffff05d7000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f1d59c9b000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f1d59999000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f1d59783000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f1d593b6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f1d5a1e2000)

依赖的库是一样的,只是版本不对。

解决兼容性的方法

目前来说有如下几种方式:

  1. 打包依赖动态库并修改elf(推荐)
  2. 静态编译
  3. docker容器
  4. 升级gcc/g++版本(包含glibc)

打包依赖动态库并修改elf

打包依赖库

在开发环境中,我们把运行所需要的动态库都打包到一个目录下。

可以使用下面的脚本

#!/bin/bash

# copylib.sh

LibDir=$PWD"/lib"

Target=$1

lib_array=($(ldd $Target | grep -o "/.*" | grep -o "/.*/[^[:space:]]*"))

$(mkdir $LibDir)

for Variable in ${lib_array[@]}
do
cp "$Variable" $LibDir
done

执行

./copylib.sh regex

$ tree
.
├── cplib.sh
├── lib
│   ├── ld-linux-x86-64.so.2
│   ├── libc.so.6
│   ├── libgcc_s.so.1
│   ├── libm.so.6
│   └── libstdc++.so.6
└── regex

修改elf的rpath和dynamic loader

这里要解释一下 rpath 和 dynamic loader 是什么?

  • 动态库加载器dynamic loader是在程序启动时,操作系统会把控制权转交给ld-linux-x86-64.so.2,而不是交给程序正常的进入地址,ld-linux-x86-64.so.2会寻找并加载所有需要的库文件,然后再将控制权交给应用的起始入口。

    它和glibc是关联的,也就是必须要使用正确的动态加载器,当然高版本一般是向下兼容的。

    经过查看文件头,可以看出 ld-linux-x86-64.so.2 的位置信息写死在ELF中,并不受rpath和LD_LIBRARY_PATH的影响。

    $ readelf -l regex
    
    Elf 文件类型为 DYN (共享目标文件)
    入口点 0x44b0
    共有 9 个程序头,开始于偏移量64
    
    程序头:
      Type           Offset             VirtAddr           PhysAddr
    ...
          [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
    ...
    

    这个路径有两种方式可以修改,一种是在编译源码的时候指定位置

    g++ -o regex regex.cpp -Wl,-dynamic-linker='./lib/ld-linux-x86-64.so.2'
    

    另外一种就是通过 patchelf 工具修改。

    动态库加载器也叫ELF interpreter

  • 关于rpath,可以查看 Linux之动态链接库 此篇文章。大致就是指动态库或可执行文件运行时到哪里找依赖的动态库。

接下来通过 patchelf 工具修改 rpathdynamic loader

首先安装 patchelf

sudo apt install patchelf

查看版本

vincent@msi-creator-15:~$ 
---➤ patchelf --version
patchelf 0.13

接下来让可执行程序在运行的时候到我们指定的目录下查找所需要的动态库

patchelf --set-rpath `pwd`/lib regex
patchelf --set-interpreter `pwd`/lib/ld-linux-x86-64.so.2 regex

这里的 rpath 也可以通过设置 LD_LIBRARY_PATH 来达到一样的目的。

export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH

此时就可以运行了。

静态编译

静态编译就是将运行时所需要的动态库都打包到可执行文件中了,那么就会导致可执行文件程序体积过大,还很多其他缺点,一般不采用这种方式。

g++ -o regex regex.cpp -static-libgcc -static-libstdc++

docker容器

docker容器是一种解决方式,但是由于其需要先安装docker,所以当前应用不太建议使用该方式。

升级gcc/g++版本

这里就需要升级生产环境中的 gcc 和 glibc 版本了,但是升级gcc还好说,升级 glibc 就要慎重了,因为你的系统依赖于既有的 glibc 库,一旦更换几乎系统就不可能重启成功

所以不推荐使用这种方式。

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

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

相关文章

PHP变量和常量(基础语法)

文章目录 PHP变量和常量&#xff08;基础语法&#xff09;简介变量常量 PHP中的变量变量基础全局变量超全局变量静态变量 PHP常量基础总结 PHP变量和常量&#xff08;基础语法&#xff09; 简介 变量和常量是编程语言中不可或缺的元素&#xff0c;它们类似于盒子&#xff0c;…

06 QT自定义信号和槽

案例&#xff1a;创建教师类和学生类&#xff0c;教师发出自定义hungry信号&#xff0c;学生响应信号&#xff0c;执行treat函数。 创建老师和学生类&#xff08;由于老师和学生不是控件&#xff0c;所以选择QObject作为基类&#xff09; 1&#xff1a;老师发送自定义信号&…

「深度学习之优化算法」(十七)灰狼算法

1. 灰狼算法简介 (以下描述,均不是学术用语,仅供大家快乐的阅读)   灰狼算法(Grey Wolf Algorithm)是受灰狼群体捕猎行为启发而提出的算法。算法提出于2013年,仍是一个较新的算法。目前为止(2020)与之相关的论文也比较多,但多为算法的应用,应该仍有研究和改进的余…

Qgis二次开发-实现缩略图、标注

1.效果图 2.简介 因为上述动作是和画布进行交互&#xff0c;所以首先需要自定义一个地图交互工具类&#xff0c;由于做的比较简单&#xff0c;只需要重写实现鼠标点击事件。 void canvasPressEvent(QgsMapMouseEvent *e) override; 其次就是在地图画布上画标注图片(svg格式)…

Docker中的网络

文章目录 一、Docker 网络1.1 Docker 网络实现原理1.2 查看容器的输出和日志信息Docker 的网络模式 二、资源控制2.1 CPU 资源控制2.2 对内存使用的限制 一、Docker 网络 1.1 Docker 网络实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&a…

CentOS7安装并远程连接MySQL8.0.33

一、前言 学习MySQL进阶篇时需要在CentOS上安装MySQL&#xff0c;然后远程连接使用&#xff0c;于是就抽了两天时间把瑞吉外卖的Linux篇给看了95% 本篇是摘选了学习笔记中关于安装MySQL的部分&#xff0c;作为参考也作为分享 二、安装MySQL 先检测当前系统中是否已安装MySQL…

平头哥 TH1520 RISC-V BeagleV-Ahead使用Thead-Yocto自定义构建系统 最详细版本

使用Thead-Yocto自定义BeagleV-Ahead系统 Thead-Yocto简述 官网&#xff1a;https://www.yoctoproject.org/ THE YOCTO PROJECT. IT’S NOT AN EMBEDDED LINUX DISTRIBUTION,IT CREATES A CUSTOM ONE FOR YOU. YOCTO项目&#xff1a;他不是一个嵌入式Linux发行版&#xff0c…

SQL SERVER安装

其中服务器名称输入./自己本机电脑名称. nchar类型一个单位可以放一个汉字-------长度短的补空格一个字节8位一个汉字两个字节 char类型两个单位可以放一个汉字 nvarchar类型是可变长度-----------长度短不会补空格 varchar类型是可变长度两个单位可以放一个汉字---------…

电脑显示连接上WiFi,但没办法上网

问题: 电脑显示已经连接上WiFi。但是百度不出来东西&#xff0c;也没办法打开任何网页。 解决方法&#xff1a; win10系统 在左下角搜索栏&#xff0c;搜索“代理服务器设置”。 找到手动设置代理 —》关闭“使用代理服务” 【默认是打开的】 关闭之后即可上网~~

Python(三十四)条件表达式

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

数据结构--线性表两种存储方式的总结以及应用

这里写目录标题 顺序表和链表的比较存储密度链表的优缺点二者特点的比较以及使用场景 应用线性表的合并有序表的合并用顺序表实现用链表实现 案例实现多项式运算稀疏多项式的运算链表的创建多项式相加图书管理系统 顺序表和链表的比较 存储密度 链表的优缺点 二者特点的比较以…

mybatis学习笔记之在WEB中应用MyBatis

文章目录 数据库表的设计和准备数据环境搭建前端页面编写后端代码实现后端代码目录dao层servicewebpojoUtils 数据库表的设计和准备数据 环境搭建 在pom.xml中配置依赖&#xff08;logback、mybatis、mysql、servlet&#xff09; 注意引入tomcat 前端页面编写 <!DOCTYPE …

Ubuntu 网络配置指导手册

一、前言 从Ubuntu 17.10 Artful开始&#xff0c;Netplan取代ifupdown成为默认的配置实用程序&#xff0c;网络管理改成 netplan 方式处理&#xff0c;不在再采用从/etc/network/interfaces 里固定 IP 的配置 &#xff0c;配置写在 /etc/netplan/01-network-manager-all.yaml 或…

《Docker基础知识解析:容器与虚拟化的区别与优势,选择最佳方案优化云计算应用》

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【MATLAB第57期】基于MATLAB的双隐含层BP神经网络回归预测模型(无工具箱版本及工具箱版本对比)

【MATLAB第57期】基于MATLAB的双隐含层BP神经网络回归预测模型&#xff08;无工具箱版本及工具箱版本对比&#xff09; 一、无工具箱版本 1.数据设置 数据为案例数据 。103行样本&#xff0c;7输入1输出数据。 2.参数设置 训练函数 梯度下降 HiddenUnit1Num10;%隐层1结点数…

Thinkphp+vue中小企业人事管理系统q731f

运行环境:phpstudy/wamp/xammp等 开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp5 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat/phpmyadmin中小企业人事管理系统的主要开发目标如下&#xff1a; &…

性能测试之 cpu 篇

目录 1 前言&#xff1a; 2.1 cpu 介绍 2.1.1 上下文切换 2.1.2 运行队列 2.1.3 CPU 利用率 2.2 cpu 性能监控 2.2.1 vmstat 的使用 2.2.2 案例学习:持续的 CPU 利用率 2.2.3 案例学习:超负荷调度 2.2.4. mpstat 工具的使用 2.2.5. 案例学习: 未充分使用的处理量 2…

windows-文件夹-默认打开方式被修改-修改为资源管理器

文章目录 1.方法2.总结 1.方法 如果文件夹默认修改方式被修改&#xff0c;可以打开注册表 按windowsR输入&#xff1a; regedit然后修改注册表项 HKEY_CLASSES_ROOT\Directory\shell将其它值删除&#xff0c;键入默认的windows资源管理器 %systemroot%\explorer如下图所示&…

【PostgreSQL内核学习(五)—— 查询规划(预处理)】

查询规划——预处理 预处理提升子链接/子查询预处理表达式预处理HAVING子句 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明引用来源。 本文主…

【网络教程】如何快速的解决WordPress“另一更新正在进行”的问题

文章目录 WordPress提示“另一更新正在进行”解决方案手动删除数据库记录使用插件WordPress提示“另一更新正在进行” 当我们在更新WordPress的插件或者升级WordPress时会出现后台提示“另一更新正在进行”,如下图 当我们点击更新后,出现下图提示 出现上述问题是由于在升级Wo…