尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
12.【Linux系统编程】动静态库制作与使用
目录1. 库的概念2. 静态库2.1 静态库的生成2.2 静态库的使用3. 动态库3.1 动态库生成3.2 动态库的使用3.3 库运行搜索路径3.3.1 简单解释3.3.2 详细解释了解4. 动静态库补充5. 使用外部库不重要1. 库的概念库是写好的现有的成熟的可以复用的代码。现实中每个程序都要依赖很多基础的底层库不可能每个人的代码都从零开始因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式可以被操作系统载入内存执行。库有两种静态库.a[Linux]、.lib[windows]动态库.so[Linux]、.dll[windows]// ubuntu 动静态库// C$ ls-l/lib/x86_64-linux-gnu/libc-2.31.so-rwxr-xr-x1root root2029592May102:20/lib/x86_64-linux-gnu/libc-2.31.so $ ls-l/lib/x86_64-linux-gnu/libc.a-rw-r--r--1root root5747594May102:20/lib/x86_64-linux-gnu/libc.a//C$ ls/usr/lib/gcc/x86_64-linux-gnu/9/libstdc.so-l lrwxrwxrwx1root root40Oct242022/usr/lib/gcc/x86_64-linuxgnu/9/libstdc.so-../../../x86_64-linux-gnu/libstdc.so.6$ ls/usr/lib/gcc/x86_64-linux-gnu/9/libstdc.a/usr/lib/gcc/x86_64-linux-gnu/9/libstdc.a// Centos 动静态库// C$ ls/lib64/libc-2.17.so-l-rwxr-xr-x1root root2156592Jun423:05/lib64/libc-2.17.so[whbbite-alicloud~]$ ls/lib64/libc.a-l-rw-r--r--1root root5105516Jun423:05/lib64/libc.a// C$ ls/lib64/libstdc.so.6-l lrwxrwxrwx1root root19Sep1820:59/lib64/libstdc.so.6-libstdc.so.6.0.19$ ls/usr/lib/gcc/x86_64-redhat-linux/4.8.2/libstdc.a-l-rw-r--r--1root root2932366Sep302020/usr/lib/gcc/x86_64-redhatlinux/4.8.2/libstdc.a后续操作需要使用的文件// mystdio.h#pragmaonce#includestdio.hvoidmy_print(intval);// mystdio.c#includemystdio.hvoidmy_print(intval){printf(mystdio输出%d\n,val);}// mystring.h#pragmaonceintmy_strlen(constchar*s);// mystring.c#includemystring.hintmy_strlen(constchar*s){constchar*ends;while(*end!\0)end;returnend-s;}2. 静态库静态库概念静态库.a后缀程序在编译链接的时候把库的代码链接到可执行文件中静态库的本质是.o文件打包程序运行的时候将不再需要静态库即静态库链接即为拷贝。静态库的使用情形一个可执行程序可能用到许多的库这些库运行有的是静态库有的是动态库编译默认为动态链接库只有在该库下找不到动态.so的时候才会采用同名静态库。可以使用gcc的-static强转设置链接静态库。2.1 静态库的生成静态库生成流程gcc编译生成.o文件 → ar命令打包.o文件ar是gnu归档工具rc表示(replace and create)$ ar-tvlibmystdio.a rw-rw-r--1000/10002848Oct2914:352024my_stdio.o rw-rw-r--1000/10001272Oct2914:352024my_string.ot列出静态库中的文件vverbose 详细信息# Makefilelibmyc.a:mystdio.o mystring.o# 链接ar-rc$$^ %.o:%.c# 输出.o文件gcc-c$echocompling $ to$... done.PHONY:output# 输出output:mkdir-plib/includemkdir-plib/mylibcp-f*.h lib/includecp-f*.a lib/mylibtarczf lib.tgz lib .PHONY:clean# 清理clean:rm-rf*.o libmyc.a lib lib.tgz usercode2.2 静态库的使用// usercode.c#includemystdio.h#includemystring.hintmain(){my_print(my_strlen(abc));return0;}静态库三种不同存放路径的使用方法# 场景1头文件和库文件和我们自己的源文件在同一个路径下$ gcc usercode.c -L.-lmyc-ousercode# 场景2头文件和库文件安装到系统路径下$ gcc usercode.c-lmyc-ousercode# 场景3头文件和库文件有自己的独立路径$ gcc usercode.c -I头文件路径 -L库文件路径-lmyc-ousercode-L: 指定库路径-I: 指定头文件搜索路径-l: 指定库名库文件名称和引入库的名称去掉前缀lib去掉后缀.a如libc.a - c。测试目标文件生成后静态库删掉程序照样可以运行。3. 动态库动态库.so程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表而不是外部函数所在目标文件的整个机器码在可执行文件开始运行以前外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中 这个过程称为动态链接dynamic linking动态库可以在多个程序间共享所以动态链接使得可执行文件更小节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用节省了内存和磁盘空间。3.1 动态库生成静态库生成流程gcc编译生成.o文件 → gcc命令打包.o文件# Makefilelibmystdio.so:my_stdio.o my_string.o# 链接gcc-o$$^-shared%.o:%.c# 输出.o文件gcc-fPIC-c$.PHONY:clean# 清理clean:rm-rf*.o libmyc.so lib lib.tgzechoclean ... done.PHONY:output# 输出output:mkdir-plib/includemkdir-plib/mylibcp-f*.h lib/includecp-f*.so lib/mylibtarczf lib.tgz libshared: 表示生成共享库格式fPIC产生位置无关码(position independent code)库名规则libxxx.so3.2 动态库的使用动态库三种不同存放路径的使用方法静态库和动态库在 GCC 链接时的使用方式基本相同都是 -L 指定库路径、-l 指定库名。区别是静态库在链接时把代码放进程序而动态库在运行时还需要加载对应的 .so 文件。# 场景1头文件和库文件和我们自己的源文件在同一个路径下$ gcc usercode.c -L.-lmyc-ousercode# 场景2头文件和库文件安装到系统路径下$ gcc-ousercode usercode.c-lmyc# 场景3头文件和库文件有自己的独立路径$ gcc-ousercode usercode.c -I头文件路径 -L库文件路径-lmyc$ ldd libmystdio.so // 查看库或者可执行程序的依赖3.3 库运行搜索路径问题./usercode执行时找不到动态库路径原因链接时gcc知道库在哪里而系统不知道3.3.1 简单解释报错原因 Linux 使用动态库.so时编译链接阶段和程序运行阶段查找动态库的路径不同。gcc的-L参数只负责指定编译链接时的库文件路径不能保证程序运行时找到动态库。因此即使libmystdio.so在当前目录下程序运行时仍可能报错cannot open shared object file。解决方法 可以通过LD_LIBRARY_PATH指定运行时动态库的搜索路径。例如gcc usercode.c -L. -lmystdio -o c.out LD_LIBRARY_PATH. ./c.out也可以使用export LD_LIBRARY_PATH. ./c.out一句话记忆-L指定链接时的库路径LD_LIBRARY_PATH指定运行时的动态库搜索路径。3.3.2 详细解释了解make之后生成libmyc.so文件make output之后新建lib存储.h文件和libmyc.so文件删除当前usercode所在文件夹内的libmyc.so库./usercode运行报错ldd usercode查看显示库文件找不到bash流程如下[gyycsdn test]$lsMakefile Makefile-bak mystdio.c mystdio.h mystring.c mystring.h usercode.c[gyycsdn test]$makegcc-fPIC-cmystdio.cechocompling mystdio.c to mystdio.o ... donecompling mystdio.c to mystdio.o...donegcc-fPIC-cmystring.cechocompling mystring.c to mystring.o ... donecompling mystring.c to mystring.o...donegcc-olibmyc.so mystdio.o mystring.o-shared[gyycsdn test]$lslibmyc.so Makefile Makefile-bak mystdio.c mystdio.h mystdio.o mystring.c mystring.h mystring.o usercode.c[gyycsdn test]$makeoutputmkdir-plib/includemkdir-plib/mylibcp-f*.h lib/includecp-f*.so lib/mylibtarczf lib.tgz lib[gyycsdn test]$lslib libmyc.so lib.tgz Makefile Makefile-bak mystdio.c mystdio.h mystdio.o mystring.c mystring.h mystring.o usercode.c[gyycsdn test]$rmlibmyc.so lib.tgz[gyycsdn test]$lslib Makefile Makefile-bak mystdio.c mystdio.h mystdio.o mystring.c mystring.h mystring.o usercode.c[gyycsdn test]$ gcc-ousercode usercode.c-Ilib/include/-Llib/mylib/-lmyc[gyycsdn test]$lslib Makefile Makefile-bak mystdio.c mystdio.h mystdio.o mystring.c mystring.h mystring.o usercode usercode.c[gyycsdn test]$ ./usercode ./usercode: errorwhileloading shared libraries: libmyc.so: cannotopenshared object file: No suchfileor directory# libmyc.so not found[gyycsdn test]$ ldd usercode linux-vdso.so.1(0x00007fff66f72000)libmyc.sonot found libc.so.6/lib64/libc.so.6(0x00007f0315739000)/lib64/ld-linux-x86-64.so.2(0x00007f0315b07000)“动态库找不到”的解决方法将库放在系统库里面。拷贝.so文件到系统共享库路径下,一般指/usr/lib、/usr/local/lib、/lib64或者开篇指明的库路径等向系统共享库路径下建立同名软连接更改环境变量LD_LIBRARY_PATHldconfig方案配置/ etc/ld.so.conf.d/ldconfig更新[rootlocalhost linux]# cat /etc/ld.so.conf.d/bit.conf/root/tools/linux[rootlocalhost linux]# ldconfig // 要生效这里要执行ldconfig重新加载库搜索路径补将libmyc.so放在usercode所在目录中也可以4. 动静态库补充gcc/g使用动静态库优先使用动态库动态库不存在则使用静态库动静态库都存在且要使用静态库使用-static选项。使用static时必须存在静态库$ gcc-ousercode usercode.c -I头文件路径 -L库文件路径-lmyc-static在linux系统下默认情况安装的大部分库都是优先安装动态库库应用程序 1 nvs软件不仅仅可以生成可执行程序也能生成动静态库5. 使用外部库不重要我们现在没接触过太多的库唯一接触过的就是C、C标准库这里我们可以推荐一个好玩的图形库ncurses安装# Centos$sudoyuminstall-yncurses-devel# ubuntu$sudoaptinstall-ylibncurses-dev系统中其实有很多库它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况的函数ncurses库// 我们代码是我用文心一言生成并调试通过的具体要什么功能大家可以试着了解一下#includestdio.h#includestring.h#includencurses.h#includeunistd.h#definePROGRESS_BAR_WIDTH30#defineBORDER_PADDING2#defineWINDOW_WIDTH(PROGRESS_BAR_WIDTH2*BORDER_PADDING2)// 加边框的宽度#defineWINDOW_HEIGHT5#definePROGRESS_INCREMENT3#defineDELAY300000// 微秒300毫秒intmain(){initscr();start_color();init_pair(1,COLOR_GREEN,COLOR_BLACK);// 已完成部分绿色前景黑色背景init_pair(2,COLOR_RED,COLOR_BLACK);// 剩余部分虽然用红色可能不太合适但为演示目的红色背景cbreak();noecho();curs_set(FALSE);intmax_y,max_x;getmaxyx(stdscr,max_y,max_x);intstart_y(max_y-WINDOW_HEIGHT)/2;intstart_x(max_x-WINDOW_WIDTH)/2;WINDOW*winnewwin(WINDOW_HEIGHT,WINDOW_WIDTH,start_y,start_x);box(win,0,0);// 加边框wrefresh(win);intprogress0;intmax_progressPROGRESS_BAR_WIDTH;while(progressmax_progress){werase(win);// 清除窗口内容// 计算已完成的进度和剩余的进度intcompletedprogress;intremainingmax_progress-progress;// 显示进度条intbar_xBORDER_PADDING1;// 进度条在窗口中的x坐标intbar_y1;// 进度条在窗口中的y坐标居中// 已完成部分attron(COLOR_PAIR(1));for(inti0;icompleted;i){mvwprintw(win,bar_y,bar_xi,#);}attroff(COLOR_PAIR(1));// 剩余部分用背景色填充attron(A_BOLD|COLOR_PAIR(2));// 加粗并设置背景色为红色仅用于演示for(inticompleted;imax_progress;i){mvwprintw(win,bar_y,bar_xi, );}attroff(A_BOLD|COLOR_PAIR(2));// 显示百分比charpercent_str[10];snprintf(percent_str,sizeof(percent_str),%d%%,(progress*100)/max_progress);intpercent_x(WINDOW_WIDTH-strlen(percent_str))/2;// 居中显示mvwprintw(win,WINDOW_HEIGHT-1,percent_x,percent_str);wrefresh(win);// 刷新窗口以显示更新// 增加进度progressPROGRESS_INCREMENT;// 延迟一段时间usleep(DELAY);}// 清理并退出ncurses模式delwin(win);endwin();return0;}
RELATED

相关推荐

Webiny event-handler-aws 的 AwsLambdaContext 与 AwsLambdaEvent:基于 DI 的 Lambda 运行时抽象实战指南

Webiny event-handler-aws 的 AwsLambdaContext 与 AwsLambdaEvent:基于 DI 的 Lambda 运行时抽象实战指南

CMS后端前端 【免费下载链接】webiny-js Open-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at…

📅 2026/10/9 2:17:13
现代 JavaScript 教程实战:用 cubic-bezier 让 CSS 尺寸动画“跳脱“边界(飞机缩放回弹动画)

现代 JavaScript 教程实战:用 cubic-bezier 让 CSS 尺寸动画“跳脱“边界(飞机缩放回弹动画)

文档教程前端 【免费下载链接】zh.javascript.info 现代 JavaScript 教程(The Modern JavaScript Tutorial),以最新的 ECMAScript 规范为基准,通过简单但足够详细的内容,为你讲解从基础到高阶的 JavaScript 相关知识。…

📅 2026/10/9 2:12:13
models.dev Issue Fixer 自动化深度解析:从 GitHub Issue 到模型目录数据修复 PR 的完整工作流

models.dev Issue Fixer 自动化深度解析:从 GitHub Issue 到模型目录数据修复 PR 的完整工作流

人工智能大模型后端前端 【免费下载链接】models.dev An open-source database of AI models. 项目地址: https://gitcode.com/gh_mirrors/mo/models.dev 点击查看 免费下载 导读 本文围绕 models.dev 仓库中的自动化 Issue 修复 Agent 配置文档 issue-fixer.md 展…

📅 2026/10/9 2:12:13
MORE NEWS

更多资讯

📰

停车场管理系统课程设计:用栈、队列、链表一题通关

简介:面向数据结构课程设计的学生,这是一份以C语言实现的停车场管理系统完整资料,源码基于链栈数据结构完成,覆盖车辆入场、出场、增删查改等核心逻辑,可自动计算停留时长与应收费用,命令行终端界面经过优化…

📰

仿微信聊天系统源码解析:WinForm桌面端IM开发实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

阿里 Qoder 智能体工作台实战:用 TaoToken 统一 Key 打通 Harness 与 Agent 工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

OpenClaw Talk 模式实战:TaoToken 统一 Key 打通 Voice Call 语音链路配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

工控数据类型与值范围详解:从PLC到Modbus的解析避坑指南

1. 从一次通讯调试翻车说起:为什么数据类型值得单独拎出来讲刚入行那会儿,我接手过一个改造项目:用上位机通过 Modbus RTU 读取一台老设备的温度值。协议文档上白纸黑字写着"温度寄存器地址 40001,单位 0.1℃"。我照着地…

📰

新电脑装机指南:从系统初始化到效率工具的科学配置思路

1. 装机思路的底层逻辑:为什么“必装清单”不能照抄每次帮朋友处理新电脑,我最怕听到的一句话就是“你直接把你的软件清单发我一份”。不是不愿意给,而是这份清单如果直接照搬,大概率会出问题。原因很简单:每个人的硬件…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬