Linux 静态与动态编译、静态库与动态库

news2024/9/21 12:46:35

文章目录

    • 一、库的简介
    • 二、静态链接和动态链接
      • 1、静态链接
      • 2、动态链接
      • 3、GCC 下动态库与静态库
    • 三、静态库制作和使用
    • 四、动态库制作和使用
    • 总结

一、库的简介

什么是库文件呢?
所谓库文件,大家可以将其等价为压缩包文件,该文件内部通常包含不止一个目标文件(也就是二进制文件)。库文件中每个目标文件存储的代码,并非完整的程序,而是一个个实用的功能模块,以便提供给使用者一些可以直接拿来用的变量、函数或类

所以,其实库文件只是一个统称,代指的是一类压缩包,它们都包含有功能实用的目标文件。例如,C 语言库文件提供有大量的函数(如 scanf()printf()strlen() 等),C++ 库文件不仅提供有使用的函数,还有大量事先设计好的类(如 string 字符串类)。

那什么是又是库呢?为什么需要库?
库,即程序库,是一种特殊的程序,编写库的程序和编写一般的程序区别不大,只是库不能单独运行,必须作为其它执行程序的一部分来完成某些功能。程序库可分静态库(static library)和共享库(shared library)

库的好处

  1. 代码保密:将源文件打包成库分发给别人使用可以保护源码的实现不被公开,起到保密作用(详细可以看下文关于库文件与头文件的分析)。
    当然,有人可能会想到,可以使用反编译的工具反编译库文件,就可以获得源码,实际上,对于 Java 而言,反编译的还原度比较高,甚至可以达到95%以上,但对于 C/C++语言,反编译的还原度比较低,可以起到保护作用。
  2. 提高开发效率库的存在可以使得程序模块化,可以加快程序的再编译,可以实现代码重用,可以使得程序便于升级,极大的提高了程序员的开发效率,因为很多功能根本不需要从 0 开发,直接调取包含该功能的库文件即可
  3. 方便部署、分发和使用:我们将打包好的库文件方便、快速的分发给别人使用,并且库文件的调用方法也很简单,以 C 语言中的 printf() 输出函数为例,程序中只需引入 <stdio.h> 头文件,即可调用 printf() 函数。

库文件与头文件
我们在分发库文件给别人使用时,往往需要还需要提供相应的头文件。有人可能会问,调用库文件为什么还要牵扯到头文件呢?

实际上,头文件和库文件并不是一码事,它们最大的区别在于:头文件只存储变量、函数或者类等这些功能模块的声明部分,库文件才负责存储各模块具体的实现部分。大家可以这样理解:所有的库文件都提供有相应的头文件作为调用它的接口。也就是说,库文件是无法直接使用的,只能通过头文件间接调用

头文件和库文件相结合的访问机制,最大的好处在于,有时候我们只想让别人使用自己实现的功能,并不想公开实现功能的源码,就可以将其制作为库文件,这样用户获取到的是二进制文件,而头文件又只包含声明部分,这样就实现了“将源码隐藏起来”的目的,且不会影响用户使用。

二、静态链接和动态链接

事实上,库文件只是一个统称,代指的是一类压缩包,它们都包含有功能实用的目标文件。既然是目标文件,所以库文件用于程序的链接阶段,通常编译器提供有 2 种实现链接的方式,分别称为静态链接方式和动态链接方式

  • 采用静态链接方式实现链接操作的库文件,称为静态链接库、静态库
    静态库在程序的链接阶段被复制到了程序中。
  • 采用动态链接方式实现链接操作的库文件,称为动态链接库、动态库
    动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。

1、静态链接

静态链接库实现链接操作的方式很简单,即程序文件中哪里用到了库文件中的功能模块,GCC 编译器就会将该模板代码直接复制到程序文件的适当位置,最终生成可执行文件。

  • 优点:

    • 对运行环境的依赖性较小,即生成的可执行文件不再需要任何静态库文件的支持就可以独立运行(可移植性强)。
    • 静态库被打包到应用程序中,所以运行时加载速度快。
  • 缺点:

    • 运行前就加载程序文件中,所以生成的程序比较大,需要更多的系统资源,在装入内存时会消耗更多的时间。
    • 如果程序文件中多次调用库中的同一功能模块,则该模块代码势必就会被复制多次,生成的可执行文件中会包含多段完全相同的代码,造成代码的冗余。
    • 更新、部署、发布麻烦,即如果库有了更新,必须重新编译整个源程序文件。比如,静态库更新了,分发给别人后,需要把更新的库和头文件重新编译,使用者的应用程序需要重新编译部署。

2、动态链接

动态链接库,又称为共享链接库。和静态链接库不同,采用动态链接库实现链接操作时,程序文件中哪里需要库文件的功能模块,GCC 编译器不会直接将该功能模块的代码拷贝到文件中,而是将功能模块的位置信息记录到文件中,直接生成可执行文件。

显然,这样生成的可执行文件是无法独立运行的。采用动态链接库生成的可执行文件运行时,GCC 编译器会将对应的动态链接库一同加载在内存中,由于可执行文件中事先记录了所需功能模块的位置信息,所以在现有动态链接库的支持下,也可以成功运行。

所以:动态链接时,链接器在链接时仅仅建立与所需库函数的之间的链接关系,在程序运行时才将所需资源调入可执行程序

  • 优点:

    • 由于可执行文件中只记录的是功能模块的地址,真正的实现代码并没有放入程序文件中,所以相对于静态编译,有着较小的程序体积
    • 实现进程之间的资源共享(避免重复拷贝):由于可执行文件中记录的是功能模块的地址,真正的实现代码会在程序运行时被载入内存,这意味着,即便功能模块被调用多次,使用的都是同一份实现代码(这也是将动态链接库称为共享链接库的原因)。
    • 更新、部署、发布简单,简化了程序的升级:比如,动态库更新了,分发给别人后,只需要把更新的库重新编译即可,使用者的应用程序不需要重新编译部署。
  • 缺点:

    • 动态库没有被打包到应用程序中,所以运行是加载速度慢。
    • 依赖动态库,不能独立运行:发布程序时需要提供依赖的动态库。
    • 动态库依赖版本问题严重

3、GCC 下动态库与静态库

GCC 编译器生成可执行文件时,默认情况下会优先使用动态链接库实现链接操作,除非当前系统环境中没有程序文件所需要的动态链接库,GCC 编译器才会选择相应的静态链接库。如果两种都没有(或者 GCC 编译器未找到),则链接失败。(如果同一目录下同时存在同名的动态库和静态库,比如 libmax.so 和 libmax.a 都在当前路径下, 则 gcc 会优先链接动态库。)

什么时候使用静态库,什么时候使用动态库?
建议如果库比较少,编译建议使用静态库,如果库比较大,编译建议使用动态库。

三、静态库制作和使用

(1)静态库命名规则

  • 在 Linux 发行版系统中,静态链接库文件的后缀名通常用 .a 表示,libxxx.a
    • lib : 前缀(固定)
    • xxx : 库的名字,自己起
    • .a : 后缀(固定)
  • 在 Windows 系统中,静态链接库文件的后缀名为 .lib,libxxx.lib

(2) 静态库制作
步骤1:将 c 源文件生成对应的 .o 文件,只进行汇编不进行链接。
【注意】头文件和 main.c 不需要要汇编

yxm@192:~/calc$ ls
add.c  div.c  head.h  main.c  mult.c  sub.c
yxm@192:~/calc$ gcc -c add.c  -o add.o
yxm@192:~/calc$ gcc -c sub.c -o sub.o
yxm@192:~/calc$ gcc -c mult.c -o mult.o
yxm@192:~/calc$ gcc -c div.c -o div.o
yxm@192:~/calc$ ls
add.c  add.o  div.c  div.o  head.h  main.c  mult.c  mult.o  sub.c  sub.o

步骤2:使用打包工具 ar 将准备好的 .o 文件打包为 .a 文件 libxxx.a。

ar rcs libxxx.a xxx.o xxx.o

  • r – 将文件插入备存文件中
  • c – 建立备存文件
  • s – 索引
yxm@192:~/calc$ ar -rcs libcalc.a add.o mult.o sub.c div.o
yxm@192:~/calc$ ls
add.c  add.o  div.c  div.o  head.h  libcalc.a  main.c  mult.c  mult.o  sub.c  sub.o
yxm@192:~/calc$ rm add.o div.o mult.o sub.o add.c div.c mult.c sub.c 
yxm@192:~/calc$ ls
app  head.h  libcalc.a  main.c

(3)静态库使用
静态库制作完成之后,需要将 .a 文件和头文件一起发布给用户(具体原因请参看本文前面部分),用户再引用静态库编译成可执行文件 。

假设用户的测试文件为 main.c,静态库文件为 libcalc.a,编译命令如下:

yxm@192:~/calc$ ls
head.h  libcalc.a  main.c
yxm@192:~/calc$ gcc main.c  -I ./ -L ./ -lcalc -o app
yxm@192:~/calc$ ls
app  head.h  libcalc.a  main.c
yxm@192:~/calc$ ./app 
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667

参数说明(详细参考Linux 下 GCC 编译常用总结):

  • -L:表示要链接的库所在目录,即 libxxx.a 所在的目录。
  • -I(大写 i): 表示库文件对应的头文件所在的目录。
  • -l(小写L):指定链接时需要的库名,即 libxxx.a 去掉前缀和后缀之后的部分。
    【注意】-l 与后面的库名可以有空格,也可以没有空格,两个方式都对。

四、动态库制作和使用

(1)动态库命名规则

  • 在 Linux 发行版系统中,动态链接库的后缀名通常用 .so 表示,libxxx.so

    • lib : 前缀(固定)
    • xxx : 库的名字,自己起
    • .a : 后缀(固定)
  • 在 Windows 系统中,动态链接库文件的后缀名为 .dll,libxxx.dll

(2)动态库制作
步骤一:gcc 生成 .o 目标文件,此时要加编译选项:-fPIC(fpic也可)。

gcc -c –fpic/-fPIC a.c b.c
参数:

  • fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。
yxm@192:~/calc$ ls
add.c  div.c  head.h  main.c  mult.c  sub.c
yxm@192:~/calc$ gcc -c add.c  -o add.o -fPIC
yxm@192:~/calc$ gcc -c sub.c -o sub.o -fPIC
yxm@192:~/calc$ gcc -c mult.c -o mult.o -fPIC
yxm@192:~/calc$ gcc -c div.c -o div.o -fPIC
yxm@192:~/calc$ ls
add.c  add.o  div.c  div.o  head.h  main.c  mult.c  mult.o  sub.c  sub.o

步骤二:生成共享库,此时要加链接器选项: -shared(指定生成动态链接库)

gcc -shared a.o b.o -o libcalc.so

yxm@192:~/calc$ gcc -shared add.o div.o mult.o sub.o -o libcalc.so
yxm@192:~/calc$ ls
add.c  add.o  div.c  div.o  head.h  libcalc.so  main.c  mult.c  mult.o  sub.c  sub.o

(3)动态库使用测试

动态库制作完成之后,需要将 .so 文件和头文件一起发布给用户(具体原因请参看本文前面部分),用户再引用动态库编译成可执行文件(编译方法跟静态库方式一样) 。

假设用户拿到 .so 文件和头文件后,测试文件目录如下:

yxm@192:~/library$ tree
.
├── include
│   └── head.h
├── lib
│   └── libcalc.so
├── main.c
└── src
    ├── add.c
    ├── div.c
    ├── mult.c
    └── sub.c

3 directories, 7 files

编译命令(编译方法跟静态库方式一样)如下:

yxm@192:~/library$ gcc main.c  -I include/ -L lib/ -lcalc -o main
yxm@192:~/library$ ls
include  lib  main  main.c  src
yxm@192:~/library$ ./main
./main: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory

然后运行:./main,发现竟然报错了!!!

  • 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道动态库的绝对路径。此时就需要系统动态载入器(dynamic linker/loader),即 ldd。通过 ldd 可以查看可执行文件的依赖的动态库。
    yxm@192:~/library$ ldd main
    linux-vdso.so.1 (0x00007ffdb9fc1000)
    libcalc.so => not found		# 没有找到可执行文件的依赖的动态库
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c15eb4000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4c162a5000)
    
  • 既然需要动态库绝对路径,那如何定位共享库文件呢?
    对于 elf 格式的可执行程序,是由 ld-linux.so 来完成定位的,它先后搜索elf文件的 DT_RPATH段 ——> 环境变量LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib目录找到库文件后将其载入内存。详细方式参考下文:如何让系统找到动态库。

(4)如何让系统找到动态库

DT_RPATH段 由操作系统定义,不能改变,所以只能同通过修改环境变量 LD_LIBRARY_PATH、/etc/ld.so.cache文件列表和、/lib/和/usr/lib目录的方法来让系统找到动态库。

方法一:临时设置,修改环境变量 LD_LIBRARY_PATH 的值:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,$LD_LIBRARY_PATH 表示旧的 LD_LIBRARY_PATH 值,: 表示追加新值。

yxm@192:~/library$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yxm/library/lib
yxm@192:~/library$ ldd main
        linux-vdso.so.1 (0x00007fffad786000)
        libcalc.so => /home/yxm/library/lib/libcalc.so (0x00007efdad23e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efdace4d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007efdad440000)
yxm@192:~/library$ ./main
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667

【注意】这种方法运行成功后,如果关闭终端,再重新打开一个新的终端,会发现系统依旧无法找到动态库,因为是在终端中配置 LD_LIBRARY_PATH 值,终端一旦关闭,配置也将清除,所以无法找到动态库。

方法二:永久设置,把 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,设置到 ~/.bashrc 或者 /etc/profile 文件中

# 用户级设置环境变量
yxm@192:~/library$ vim ~/.bashrc

# 在 .bashrc 文件的最后一行添加如下内容:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yxm/library/lib

yxm@192:~/library$ ./bashrc		# 设置环境变量生效,相当于 source /bashrc
yxm@192:~/library$ ./main
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667
# 系统级设置环境变量
yxm@192:~/library$ vim /etc/profile

# 在 profile 文件的最后一行添加如下内容:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yxm/library/lib

yxm@192:~/library$ source /etc/profile   # 设置环境变量生效
yxm@192:~/library$ ./main
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667

方法三:修改 /etc/ld.so.cache 文件列表,但是 ld.so.cache 是一个二进制文件,所以不能直接修改,但是可以间接修改,即将动态库文件所在目录的路径添加到 /etc/ld.so.conf 文件中。

yxm@192:~/library$ sudo vim /etc/ld.so.conf

# 在 ld.so.conf 文件的最后一行添加如下内容:
/home/yxm/library/lib

yxm@192:~/library$ sudo ldconfigs  # 设置生效,该命令会重建/etc/ld.so.cache文件
yxm@192:~/library$ ./main
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667

方法四:拷贝自己制作的共享库到 /lib 或者 /usr/lib 下(不是/lib64目录),不过这种方法不推荐使用,因为这两个目录本身就自带了一些系统的库文件,如果把自定义的动态库文件放到这两个文件夹下,容易导致命名冲突,可能会替换掉系统自带的文件,导致系统的程序的运行可能出现问题。

总结

学了本文,你可以充分了解静态库与动态库的区别,学会制作并使用静态库与动态库。其实静态库与动态库的制作与使用是 GCC 使用的进一步扩展(如果需要了解 GCC 基础使用请移步 Linux 下 GCC 编译常用总结),由于比较重要所以单独用一篇文章展现,与大家一起共勉,不足之处请指正。

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

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

相关文章

MyBatis源码分析(六)MetaObject工具类的使用与源码分析

文章目录一、MetaObject基本使用二、关键类源码分析1、MetaObject的构造方法2、PropertyTokenizer分词器3、BeanWrapper4、MetaClass5、DefaultReflectorFactory6、Reflector7、总结三、MetaObject的getValue源码分析写在后面一、MetaObject基本使用 public class User {priva…

OPT(奥普特)一键测量传感器SmartFlash高精度的四重保证

OPT&#xff08;奥普特&#xff09;一键测量传感器SmartFlash集成了机器视觉的边缘提取、自动匹配、自动对焦、自动学习及图像合成等人工智能技术&#xff0c;采用双远心光路及多角度照明系统设计&#xff0c;搭载高精度运动平台&#xff0c;并通过亚像素边缘提取算法处理图像&…

Mysql全解[中级篇]

目录存储引擎MySQL体系结构1). 连接层2). 服务层3). 引擎层4). 存储层存储引擎介绍存储引擎特点InnoDBMyISAMMemory文件区别及特点存储引擎选择索引无索引情况有索引情况特点索引结构二叉树红黑树B-TreeBTreeMySQL中优化之后的BTreeHash索引分类聚集索引&二级索引回表查询索…

双周赛99(贪心、数学、区间合并计算、换根DP)

文章目录双周赛99[6312. 最小和分割](https://leetcode.cn/problems/split-with-minimum-sum/)贪心[6311. 统计染色格子数](https://leetcode.cn/problems/count-total-number-of-colored-cells/)找规律[6313. 统计将重叠区间合并成组的方案数](https://leetcode.cn/problems/c…

规并排序(Swift版本)

Overview 概述 时间复杂度为 O(nlogn) ;适合大规模的数据排序 ;相比于冒泡排序、插入排序、选择排序这三种排序算法, 更加常用 ;用到了分治思想(即分而治之, 英文叫 “Divide and conquer”)&#xff0c;非常巧妙 ;英文名称: Merge Sort ; 分治思想, 在很多领域都有广泛的应用…

windows系统安装Linux虚拟机教程

虚拟机的安装首先要下载虚拟机的安装包&#xff0c;当前最新版本是VMware 16.2.1。软件我都已经给大家准备好了&#xff08;含序列号&#xff09;&#xff0c;大家在这里下载就好。虚拟机安装包下载完毕之后&#xff0c;将它安装到电脑里。这个安装过程很简单&#xff0c;一路下…

Linux操作系统学习(线程池)

文章目录线程池线程池原理代码示例单例模式饿汉模式懒汉模式饿汉懒汉对比其他的锁线程池 线程池原理 ​ 线程池是一种线程使用模式。在多线程应用中&#xff0c;若每有一个任务&#xff0c;线程就去调度相应的函数去创建&#xff0c;当任务过多时&#xff0c;每次都去调度且每…

CCF大数据专家委员会十周年纪念庆典纪实:拥抱数字时代,展望科技未来

山河远阔&#xff0c;奋进十年&#xff0c;作为国内大数据领域最权威的学术组织&#xff0c;CCF大数据专家委员会&#xff08;以下简称“大专委”&#xff09;不忘初心&#xff0c;凝心聚力&#xff0c;见证并推动了过去10年来大数据技术生态在中国的建立、发展和成熟。 2023年…

HBase安装

文章目录一、安装Zookeeper二、安装HBase三、启动Hbase步骤四、关闭进程顺序五、简单使用Hbase在开始安装HBase之前&#xff0c;请确保您已经安装了Java运行环境和Hadoop分布式文件系统。如果您还没有安装这些软件&#xff0c;请查看之前博文介绍安装。 HBase安装包&#xff1a…

谷歌广告投放步骤流程是什么?一文带你全方位了解实操细节

谷歌&#xff0c;大家都不陌生吧&#xff0c;一个人们很常用的搜索引擎。而谷歌还可以打广告&#xff0c;即谷歌广告&#xff0c;那这跟跨境电商有什么关心呢&#xff1f;东哥告诉大家&#xff0c;关系大了去了&#xff0c;毕竟如果用户搜索与我们相关的关键词&#xff0c;就有…

streaming systems 第二章

The What, Where, When, and How of Data Processing 第一章主要关注三个领域:术语&#xff0c;准确定义我使用重载术语时的意思&#xff0c;如“流”;批处理和流处理&#xff0c;比较两种类型系统的理论能力&#xff0c;并假设使流处理系统超越批处理系统只有两件事是必要的:…

【Netty】第一章 NIO 三大组件、ByteBuffer 和文件编程

【Netty】第一章 NIO 三大组件、ByteBuffer 和文件编程 文章目录【Netty】第一章 NIO 三大组件、ByteBuffer 和文件编程一、Channel & Buffer二、Selector三、ByteBuffer1.ByteBuffer 使用方式2.ByteBuffer 结构3.ByteBuffer 常用方法4.Scattering Reads4.Gathering Write5…

Java SPI机制了解与应用

1. 了解SPI机制 我们在平时学习和工作中总是会听到Java SPI机制&#xff0c;特别是使用第三方框架的时候&#xff0c;那么什么是SP机制呢&#xff1f;SPI 全称 Service Provider Interface&#xff0c;是 Java 提供的一套用来被第三方实现或者扩展的接口&#xff0c;它可以用来…

【java】Java连接mysql数据库及mysql驱动jar包下载和使用

文章目录JDBCJDBC本质&#xff1a;JDBC作用&#xff1a;跟数据库建立连接发送 SQL 语句返回处理结果操作流程和具体的连接步骤如下&#xff1a;操作步骤&#xff1a;需要导入驱动jar包 mysql-connector-java-8.0.22.jar注册驱动获取数据库连接对象 Connection定义sql获取执行sq…

第十届CCF大数据与计算智能大赛总决赛暨颁奖典礼在苏州吴江顺利举办

2月24日-25日&#xff0c;中国计算机学会&#xff08;CCF&#xff09;主办、苏州市吴江区人民政府支持&#xff0c;苏州市吴江区工信局、吴江区东太湖度假区管理办公室、苏州市吴江区科技局、CCF大数据专家委员会、CCF自然语言处理专业委员会、CCF高性能计算专业委员会、CCF计算…

深度剖析C语言符号篇

致前行的人&#xff1a; 人生像攀登一座山&#xff0c;而找寻出路&#xff0c;却是一种学习的过程&#xff0c;我们应当在这过程中&#xff0c;学习稳定冷静&#xff0c;学习如何从慌乱中找到生机。 目录 1.注释符号&#xff1a; 2.续接符和转义符&#xff1a; 3.回车与换行…

独立产品灵感周刊 DecoHack #050 - 基于 ChatGPT 的 API 能做什么产品

ChatGPT 的 API 3.5 开放过去了一周&#xff0c;果然和预想的一样&#xff0c;接入 API 的产品爆炸式地出现了非常多&#xff0c;很多产品已经做的非常好用了&#xff0c;在很多场景方便了太多。本期整理了一些做的很不错的产品。 本周刊记录有趣好玩的独立产品设计开发相关内容…

一款好的风险管理软件可以做什么

风险管理软件哪个好&#xff1f;使用Zoho Projects易于使用的项目风险管理软件&#xff0c;最大限度地减少收入损失并快速调整您的投资组合&#xff0c;保护您的项目投资。Zoho Projects的高级风险管理软件可在您最需要的时候安全的保护您的业务。使用Zoho Projects强大的风险管…

【springmvc】视图

SpringMVC的视图 SpringMVC中的视图是View接口&#xff0c;视图的作用渲染数据&#xff0c;将模型Model中的数据展示给用户 SpringMVC视图的种类很多&#xff0c;默认有转发视图和重定向视图 当工程引入jstl的依赖&#xff0c;转发视图会自动转换为JstlView 若使用的视图技…

内核性能评估测试及具体修改操作步骤记录

步骤记录前言一、查看环境配置二、LRU缓存空间调整三、进程扫描时间间隔四、与其他内核对比的工作负载测试&#xff08;另一个内核的编译&#xff09;总结前言 记录的相关操作有&#xff1a;查看服务器硬件环境、LRU缓存大小修改、内核命名、内核编译以及进程执行周期的设置。…