交流平台网站怎么做不了哪里做网站比较稳定
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:37
当前位置: 首页 > news >正文
交流平台网站怎么做不了,哪里做网站比较稳定,网站手机端页面怎么做,海南工程网站建设#x1f308;个人主页#xff1a;Yui_ #x1f308;Linux专栏#xff1a;Linux #x1f308;C语言笔记专栏#xff1a;C语言笔记 #x1f308;数据结构专栏#xff1a;数据结构 #x1f308;C专栏#xff1a;C 文章目录 1.什么是库1.2 认识动静态库1.2.1 动态库1.2.2…个人主页Yui_ Linux专栏Linux C语言笔记专栏C语言笔记 数据结构专栏数据结构 C专栏C 文章目录 1.什么是库1.2 认识动静态库1.2.1 动态库1.2.2 静态库 2.封装动静态库2.1 封装动态库2.1.1 组织头文件和库文件2.1.2 动态库的使用 2.2 封装静态库2.2.1 使用静态库 3. 动静态库小知识3.1 gcc对动静态的优先级3.2 动静态库的区别 4.总结 1.什么是库
在计算机编程中库Library是一个预先编写的代码集合包含了可以被其他程序调用的函数、类、变量和资源。库的主要目的是为了简化编程过程提供常用功能的实现促进代码重用从而减少开发时间和提高软件的可靠性。 在实践中我们一定会使用到别人的库如你在C语言时期一定会调用到c标准库。除了标准库我们还可以使用第三方库无论使用那种库都是为了节省我们的时间不在需要我们自己来造“轮子”。 所有的库都可以从两个方面来认识
创建者使用者 提问使用者在使用库时是否能知道该库的源代码呢 回答在不逆向的情况下使用者是无法得知库的源代码的这也就牵扯到了库的第二个属性隐藏源代码。 我们都知道形成可执行文件的步骤有4步 预处理头文件展开、去注释、宏替换、条件编译等生成.i文件。编译语法分析、语义分析、符号汇总等检查无误后将代码翻译成汇编指令生成.s文件汇编将汇编指令转化成二进制指令生成.o文件。链接将生成的各个.o文件进行链接生成可执行程序。 而库就是所有.o文件用特定的方式进行打包形成的一个文件。 注意库文件需要配合对应的头文件进行使用头文件不必隐藏 当我们在main.c中使用对应的功能函数 当有许多不同的源文件去调用这些功能函数时那要的话功能函数会被重复的进行预处理、编译、汇编的操作各自生成.o文件然后我们的源文件再和这些功能函数一起生成可执行文件。 如此操作会有许多重复的操作我们完全可以提前让功能函数变成一个个.o文件再去和源文件进行链接但是我们还要考虑到可能会存在非常多的.o文件为了减轻我们的操作我们可以对这些.o文件进行打包这样的文件我们称为库。
如此一来库的本质就是若干个目标文件的集合每一个目标文件都包含了由源码编译生成的二进制代码在保证使用的同时还有很好的隐藏性
1.2 认识动静态库
动静态库是编程中常用的两种库类型用于封装和重用代码。它们在链接、加载和使用方面存在显著的差异。
1.2.1 动态库
动态库或共享库是在运行时加载的库通常以 .soLinux或 .dllWindows文件格式存在。动态库的代码不被复制到可执行文件中而是在运行时由操作系统加载。 我们先来写一段简单的代码
#include stdio.hint main()
{printf(hello world!!!!\n);return 0;
}
//生成可执行文件mybin编译成功后我们使用ldd指令来查看其所链接的动态库 ldd语法
ldd filename功能 用于打印程序或库文件所依赖的动态库共享库列表。ldd不是一个可执行程序只是一个shell脚本。 ubuntuVM-20-9-ubuntu:/libraryTest$ ldd mybin linux-vdso.so.1 (0x00007ffc9c4db000)libc.so.6 /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd8df175000)/lib64/ld-linux-x86-64.so.2 (0x00007fd8df3ab000)libc.so 就是该程序所依赖的动态库那么我们一个如何识别一个动态库的名字呢 去掉前缀lib再去掉后缀.so就是库名了。 也就是说这个动态库的名字就是c没错这就是c运行库。
1.2.2 静态库
静态库是将一组对象文件.o 文件打包成一个库文件通常为 .a 后缀在编译时将其链接到最终生成的可执行文件中。链接过程是在编译阶段完成的库的代码被复制到可执行文件中。 正常情况下gcc默认都是连接的动态库如果需要进行静态连接要特别指定。
gcc -o staticBin libTest.c -staticubuntuVM-20-9-ubuntu:/libraryTest\( ls -l
total 904
-rw-rw-r-- 1 ubuntu ubuntu 82 Oct 29 11:40 libTest.c
-rw-rw-r-- 1 ubuntu ubuntu 74 Oct 29 11:41 makefile
-rwxrwxr-x 1 ubuntu ubuntu 15952 Oct 29 11:41 mybin
-rwxrwxr-x 1 ubuntu ubuntu 900344 Oct 29 14:49 staticBin可以发现静态连接的可执行程序所占的空间大小远大于动态连接的。 使用ldd观察是否有依赖的库
ubuntuVM-20-9-ubuntu:~/libraryTest\) ldd staticBin not a dynamic executable发现静态链接生成的可执行程序不依赖其他库文件。 使用file查看
ubuntuVM-20-9-ubuntu:/libraryTest$ file staticBin
staticBin: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]d4a39b68ac04f9fd8b37bd8c17ce42a8b27ad8c2, for GNU/Linux 3.2.0, not stripped发现是statically linked 如果你是centos用户可能会遇到静态库未安装的情况只需要搜索一下安装方法即可。
2.封装动静态库
2.1 封装动态库
先写好需要封装的代码 add.h
#pragma once
int add(int a,int b);sub.h
#pragma once
int sub(int a,int b);add.c
#include add.h
int add(int a,int b)
{return ab;
}sub.c
#include sub.h
int sub(int a,int b)
{return a-b;
}dynLibTest.c
#include stdio.h
#include add.h
#include sub.hint main()
{int a 100;int b 200;printf(%d %d %d\n,a,b,add(a,b));printf(%d - %d %d\n,a,b,sub(a,b));return 0;
}然后我们还需要知道位置无关码的概念Position-Independent CodePIC 位置无关码Position-Independent CodePIC是一种编译代码的方式使得生成的代码可以在内存的任意位置执行而不需要修改代码中的地址。这种特性在动态链接库和共享库中非常重要因为它们可以被多个进程共享并在加载时被放置到不同的内存地址。 为了实现位置无关编译器在生成代码时使用相对地址而不是绝对地址。例如在访问全局变量时编译器不会生成直接访问变量的绝对地址的代码而是使用相对于当前指令位置的偏移量。这样无论代码被加载到哪个地址访问都可以通过相对计算来实现。 位置无关码是一种重要的编程技术尤其在动态链接和共享库中具有广泛的应用。它提供了灵活性和内存使用效率同时也增强了程序的安全性。 如果我要实现位置无关码可以在gcc后面加上-fPIC选项
gcc -fPIC -c add.c
gcc -fPIC -c sub.c我们也知道不加-fPIC一样可以生成.o文件。但是它们之间还是很有区别的。 位置无关码对于gcc
fPIC作用于编译阶段告诉编译器于位置无关的代码此时产生的代码中没有绝对地址全部都使用相对地址从而代码可以被加载到内存的任意位置可以正确的执行。这正是共享库被加载时在内存的位置不是不是固定的。如果不加-fPIC选项则加载.so文件的代码时代码段引用的数据对象需要重定位这个重定位会修改代码段地内容这就会造成每一个使用这个.so文件代码段的内核里都会生成这个.so文件代码的拷贝并且每一个拷贝都不一样这就是使得内存的消耗变大。为此我们总是会用-fPIC来生成.so文件但是不会用点-fPIC来生成.a静态文件。我们当然可以不用-fPIC来生成.so文件只是这样的话.so文件必须要在加载到用户的地址空间时重定向所有表目。 使用-shard将文件打包为动态库
gcc -shared -o libmyc.so add.o sub.o通过readelf -S 来查看库的信息如偏移量offset。
2.1.1 组织头文件和库文件
为了方便我们后续的操作我会写一个makefile来组织头文件和库文件。
.PHONY:all
all:libmyc.solibmyc.so:add.o sub.ogcc -shared add.o sub.o -o libmyc.so
add.o:add.cgcc -fPIC -c add.c -o add.o
sub.o:sub.cgcc -fPIC -c sub.c -o sub.o
.PHONY:output
output:mkdir -p mylib/libmkdir -p mylib/includecp -rf *.h mylib/includecp -rf *.so mylib/lib
.PHONY:clean
clean:rm -rf *.o mylib *.a *.so output 2.1.2 动态库的使用
当我们把当前目录的头文件和目标文件删除后
ubuntuVM-20-9-ubuntu:/libraryTest\( rm -rf *.o *.h此时如果我们直接使用gcc来编译会发生什么呢 没错肯定会报错说找不到头文件啦。
ubuntuVM-20-9-ubuntu:~/libraryTest\) gcc dynLibTest.c
dynLibTest.c:2:10: fatal error: add.h: No such file or directory2 | #include add.h| ^~~~~~~
compilation terminated.为了让编译器能够找到我们的头文件需要我们加上-I 头文件所在路径
gcc -I./mylib/include dynLibTest.c现在的错误就是找不到目标函数了因为我们没有给编译器指明在哪里它肯定就找不到了。
ubuntuVM-20-9-ubuntu:/libraryTest$ gcc -I./mylib/include dynLibTest.c
/usr/bin/ld: /tmp/ccOkC8RY.o: in function main:
dynLibTest.c:(.text0x25): undefined reference to add
/usr/bin/ld: dynLibTest.c:(.text0x52): undefined reference to sub
collect2: error: ld returned 1 exit status所有我们还需要加上-L库文件所在路径 l库名
gcc -I./mylib/include -L./mylib/lib dynLibTest.c -lmyc‘-I’指定头文件搜索路径。—L指定库文件搜索路径。-l指明需要链接库文件路径下的哪一个库。 然后我们就可以得到一个可执行文件了但是如果你去执行它就会发现它居然不能执行
ubuntuVM-20-9-ubuntu:/libraryTest\( ./a.out
./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory为什么会这样 算了先用ldd看看它依赖的动态库的吧。
居然没有连到岂有此理辛苦打了一连串指令竟然完全没作用。 其实不是这样啦因为是动态库在执行时我们仍然需要知道动态库的位置在哪。 对于动态库编译时会搜索库的路径运行时也会搜索库的路径。 为了解决这个问题我们有4种解决方案 直接将库进行安装拷贝到系统库当中。最傻瓜操作将不在系统默认库搜索路径下的库路径添加到LD_LIBRARY_PATH 3.使用idconfig指令。 拷贝到系统目录
ubuntuVM-20-9-ubuntu:~/libraryTest\) sudo cp mylib/lib/libmyc.so /lib/x86_64-linux-gnu/
ubuntuVM-20-9-ubuntu:/libraryTest\( ldd a.out linux-vdso.so.1 (0x00007fffc4f54000)libmyc.so /lib/x86_64-linux-gnu/libmyc.so (0x00007f35c8f9c000)libc.so.6 /lib/x86_64-linux-gnu/libc.so.6 (0x00007f35c8d73000)/lib64/ld-linux-x86-64.so.2 (0x00007f35c8fae000)这样虽然简单但是由于我们自己书写的库大概率是不成熟的这样会污染系统库目录。
更改环境变量
export LD_LIBRARY_PATH\)LD_LIBRARY_PATH:home/ubuntu/libraryTest/mylib/libldd查看
ubuntuVM-20-9-ubuntu:/libraryTest\( export LD_LIBRARY_PATH\)LD_LIBRARY_PATH:home/ubuntu/libraryTest/mylib/lib
ubuntuVM-20-9-ubuntu:/libraryTest$ ldd a.outlinux-vdso.so.1 (0x00007fff8fdee000)libmyc.so (0x00007f85aaf99000)libc.so.6 /lib/x86_64-linux-gnu/libc.so.6 (0x00007f85aad6a000)/lib64/ld-linux-x86-64.so.2 (0x00007f85aafa5000)该方法为临时方法在系统重新登入时就失效了。 使用Idconfig指令 /etc/ld.so.conf.d/目录下的文件用来指定动态库搜索路径。这些文件被包含在/etc/ld.so.conf文件中ldconfig命令会在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下搜索可共享的动态链接库并创建出动态装入程序(ld.so)所需的连接和缓存文件。 .conf文件用来存储各种文件的路径我们只要把我们自己写的第三方库的路径存放进去程序运行时就会去里面找了。
echo /home/ubuntu/libraryTest/mylib/lib libmyc.conf然后我们需要将.conf文件拷贝到/etc/ld.so.conf.d/下。
sudo cp libmyc.conf /etc/ld.so.conf.d/此时如果我们直接ldd是无法找到的我们来需要更新一下。
sudo ldconfig然后就可以了 那么动态库就先到这里下面我们开始静态库的讲解。
2.2 封装静态库
静态库的操作会比动态库的更为简单。 代码的话依然是上面的那些代码。
add.c sub.c add.h sub.h staLibTest.cstaLibTest.c里面的代码和dynLibTest.c 首先我们需要把所有的.c源文件都编译为目标文件。此时不在需要位置无关码
gcc -c add.c
gcc -c sub.c我们可以直接将主程序和这些.o文件进行编译。
ubuntuVM-20-9-ubuntu:/libraryTest\( gcc -o staticBin staLibTest.c add.o sub.o
ubuntuVM-20-9-ubuntu:~/libraryTest\) ./staticBin
100 200 300
100 - 200 -100正常编译不过目标文件少的情况下还好如果有很多的目标文件我们就有点吃力了。为此我们可以打一个包。 使用ar指令将目标文件打包为静态库 ar 指令是一个用于创建、修改和管理静态库文件的命令行工具广泛应用于 Unix 和类 Unix 系统如 Linux。静态库通常以 .a 后缀表示ar 允许开发者将多个目标文件.o 文件打包成一个单一的库文件便于代码重用和管理。 语法
ar [选项] [库名] [依赖文件]主要功能
r插入文件。如果目标文件已经存在则替换它。c创建一个新的库如果库文件不存在。s创建索引以加快链接过程。t列出库中包含的文件。x从库中提取指定的文件。d从库中删除指定的文件。v查看库的信息 举例将add.o和sub.o打包为静态库
ar -rc libmyc.a add.o sub.o利用-t -v选项来查看静态库的文件以及信息。
ubuntuVM-20-9-ubuntu:/libraryTest$ ar -tv libmyc.a
rw-r–r– 0/0 1224 Jan 1 08:00 1970 add.o
rw-r–r– 0/0 1224 Jan 1 08:00 1970 sub.o和动态库时一样我们现在利用makefile来完成这些操作
libmyc.a:add.o sub.oar -rc libmyc.a add.o sub.o
add.o:add.cgcc -o add.o -c add.c
sub.o:sub.cgcc -o sub.o -c sub.c.PHONY:output
output:mkdir -p mylibs/libmkdir -p mylibs/includecp -rf *.h mylibs/includecp -rf *.a mylibs/lib
.PHONY:clean
clean:rm -rf *.o mylibs libmyc.a2.2.1 使用静态库 ‘-I’指定头文件搜索路径。—L指定库文件搜索路径。-l指明需要链接库文件路径下的哪一个库。 在动态库的篇章中我们就已经了解了指定库的路径了。 在静态库也同理。
gcc staLibTest.c -I./mybins/include -L./mylibs/lib -lmyc编译完后就可以直接运行了。
ubuntuVM-20-9-ubuntu:/libraryTest\( gcc staLibTest.c -I./mybins/include -L./mylibs/lib -lmyc -o testbin -static
ubuntuVM-20-9-ubuntu:~/libraryTest\) ./testbin
100 200 300
100 - 200 -100同样的如果你觉得没错都显示指定库连接很麻烦可以把目标文件拷贝到系统库当中。
- 动静态库小知识 3.1 gcc对动静态的优先级 如果我们同时提供动态库和静态库gcc会默认使用动态库。如果我们非要静态链接必须使用static指定。如果我们只提供静态库那我们的程序只能对该库进行静态链接但是程序不一定整体是静态链接的。如果我们只提供动态库默认只能动态连接非要静态链接的话会报错。 3.2 动静态库的区别 特性静态库动态库文件后缀.a.so (Linux), .dll (Windows)链接方式编译时链接运行时链接可执行文件大小较大包含所有库代码较小只包含引用外部依赖无需要在运行时提供更新方式需要重新编译所有依赖的程序只需替换库文件性能加载速度快加载速度相对较慢共享性不支持多个进程共享支持多个进程共享 4.总结 动静态库各有优缺点选择使用哪种库通常取决于具体的项目需求、资源限制和开发环境。静态库适用于对依赖性和更新不敏感的应用而动态库则更灵活适合需要频繁更新和共享代码的场景。在实际开发中合理选择和使用这两种库能够提高代码的复用性和维护性。
- 上一篇: 交换友情链接的网站标准是什么网站的登录注册怎么做
- 下一篇: 交通建设网站做家居网站
