Linux的缓冲区与动静态库

简介: Linux的缓冲区与动静态库

缓冲区

缓冲区的意义在于节省进程进行数据IO的时间,本质是一段内存。在用户级语言层面提供的,在stdout、stdin、stderr,是一个FILE*类型(FILE是一个结构体)

如果对进程实现输出重定向并调用printf fwrite库函数和write系统调用就会发现printf 和 fwrite都输出了2次,而 write 只输出了一次。因为fork()后会生成子进程,一般C库函数写入文件时是全缓冲的而写入显示器是行缓冲。printf fwrite 库函数会自带缓冲区,发生重定向到普通文件时数据的缓冲方式由行缓冲变成了全缓冲。而放在缓冲区中的数据就不会被立即刷新,甚至fork之后直至进程退出之后才会统一刷新写入文件当中。但是fork的时候父子数据会发生写时拷贝,所以当父进程准备刷新的时候子进程也就有了同样的一份数据,随即产生两份数据。write没有变化,说明没有所谓的缓冲

缓冲区的刷新策略:

  1. 立即刷新–fflush()–无缓冲
  2. 行刷新–显示器(输出带上\n就会行刷新,显示器为了满足人的需求从左到右一行读的习惯就会采用行刷新)
  3. 缓冲区满(全缓冲)–磁盘文件–效率最高只需要一次IO
  4. 进程退出时

重定向会导致刷新策略发生了改变(由行缓冲变成了全缓冲)同时发生了写时拷贝父子进程各自刷新。因此如果没有重定向时调用printf+\n就会直接打印到显示器中,如果重定向了没有强制去刷新那么printf到普通文件中的数据并不会被刷新。

静态库

静态库:

程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库 .a

动态库

程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码 .so后缀

只需要有目标文件和头文件 那么程序就可以链接成可执行程序

如果要链接第三方的库,可以将这个库安装到系统默认指定的路径中(为了防止污染系统尽量不使用这种方式)或者指明库所在的路径和库的名称(去掉前缀和后缀)同时也要指明头文件所在的路径。需要注意即使是将第三方库安装到系统中,也需要指明库的名称才能编译,因为gcc只是知道了库的位置但gcc只认C语言的库所以需要用户自己指明。gcc默认动态链接,对于特定的库取决于用户提供的是动态库还是静态库

需要三个选项完成链接:

-I(大写i):指明头文件的搜索路径

-L: 指明库文件的搜索路径

-l(小写L):指明要链接哪个库,带上库的名称(去掉前缀和后缀)

生成静态库

将所有的目标文件打包起来就叫做静态库

首先需要用到指令:

*ar -rc XXX.a .o

将所有的目标文件打包到一个目录(库)中,再将所有的头文件放到一个目录中,最后合并这两个目录就形成了一个软件包

生成动态库

  1. 生成目标文件时需要加上 -fPIC (与位置无关码)选项
  2. 打包目标文件成动态库时需要加上 - shared 选项。因为gcc默认为动态链接所以gcc就可以完成动态库打包 gcc -shared -o XXX.so *.o
  3. 最后再将所有的头文件和库合并成一个软件包

运行动态库

因为gcc只负责编译程序而动态库是在运行的时候才链接的,所以执行程序的话操作系统需要知道动态库在哪里。

可以采取的方法:

动态库的环境变量:

$LD_LIBRARY_PATH

所以第一种方法可以把动态库的路径添加到这个环境变量里,但是这种方法不是永久有效的,环境变量只会在当前次登录系统才有效

第二种方法将软件包安装到系统的默认路径

第三种方法:

在系统里有一个路径里面全都是动态库配置文件,只需要将动态库的路径写到这个路径里即可

/etc/ld.so.conf.d/

写好配置文件后需要更新一下 ldconfig

操作完之后这个方式是永久有效的

第四种方法:

再当前目录对库所在的路径创建软链接,这样操作系统运行时就会在当前目录找到库的路径就可以访问的到了

动静态库的加载

静态库不需要加载,将代码拷贝到代码区,通过确定的地址进行访问

动态库需要加载。动态库中的指定函数的地址会写到可执行程序中,而这个地址因为在编译时加上了shared选项形成了位置无关码,所以采用的是相对地址的方法。

在程序运行时,添加到可执行程序中的是一个偏移量,库加载进来后用过偏移量就可以找到需要访问的函数

系统层面上会维护动态库的起始地址,直接建立页表与内存的映射就可以实现跳转访问,所以动态库加载一次就可以被多个进程共同使用了


相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
目录
相关文章
|
4月前
|
安全 Linux vr&ar
Linux的动态库和静态库
Linux的动态库和静态库
|
2月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
106 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
2月前
|
存储 缓存 固态存储
|
4月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
5月前
|
Oracle 关系型数据库 Linux
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
通过这一连串的步骤,可以专业且有效地在Linux下为Qt编译Oracle驱动库 `libqsqloci.so`,使得Qt应用能够通过OCI与Oracle数据库进行交互。这些步骤适用于具备一定Linux和Qt经验的开发者,并且能够为需要使用Qt开发数据库应用的专业人士提供指导。
165 1
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
|
4月前
|
Linux 网络安全 API
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
|
4月前
|
小程序 Linux 开发者
Linux之缓冲区与C库IO函数简单模拟
通过上述编程实例,可以对Linux系统中缓冲区和C库IO函数如何提高文件读写效率有了一个基本的了解。开发者需要根据应用程序的具体需求来选择合适的IO策略。
35 0
|
5月前
|
Linux 编译器 C语言
【Linux】基础IO----理解缓冲区
【Linux】基础IO----理解缓冲区
75 0
【Linux】基础IO----理解缓冲区
|
6月前
|
Linux 编译器 C语言
Linux中的pkg-config:简化库依赖管理的利器
**pkg-config**是Linux下管理库依赖的工具,它通过读取库的`.pc`文件提供编译和链接参数。使用`pkg-config --cflags --libs <library>`获取编译和链接选项,例如`gcc -o test test.c $(pkg-config --cflags --libs glib-2.0)`。能进行版本检查、参数提取、依赖管理和路径搜索。列出所有包用`pkg-config --list-all`。最佳实践包括确保库正确安装、检查版本、配置`PKG_CONFIG_PATH`及使用构建工具。
|
6月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
49 1

热门文章

最新文章