Linux基础IO-3

本文介绍了Linux中文件描述符和文件流指针的概念,以及重定向的原理和实现。文件描述符是系统调用接口操作文件的标识,而文件流指针是库函数处理文件的方式。重定向允许在不修改程序逻辑的情况下改变输入输出目标。此外,文章还探讨了动态库和静态库的生成与使用,动态库在运行时加载,而静态库将代码直接包含在可执行文件中。
摘要由CSDN通过智能技术生成

本次博客来对基础IO这一内容进行一个收尾。

目录

1.文件描述符和文件流指针

2.重定向

2.1内容

2.2原理引入

2.3原理

3.动态库与静态库的生成和使用

3.1内容

3.2生成库

3.2.1动态库

3.2.2静态库

3.3使用库

1.文件描述符和文件流指针

在正式开始本次博客内容之前, 我们来引出两个名词--“文件描述符”和“文件流指针。”这是上一篇博客中所遗留的一部分内容。

其中文件描述符就是系统调用接口open打开文件所返回的整形数字,它本质上是内核中文件描述信息数组的下标。进而当需要对文件进行操作时,便以文件描述符作为下标,找到对应的文件描述信息,来对文件进行操作。

而文件流指针就是库函数fopen打开文件所返回的FILE*指针。在Linux中,文件流指针内部便封装了文件描述符。

2.重定向

2.1内容

重定向的作用就是将原本要写入A文件的数据,在不改变程序逻辑的前提下,写入到B文件之中。

  • >:清空重定向;
  • >>:追加重定向。

2.2原理引入

了解玩重定向的内容之后,我们来简述一下重定向的原理,即重定向是如何实现的。

在我们通过系统调用接口或者库函数来打开文件时,会存在一个sturct file型的结构体来对文件进行一个描述,便于我们后续的操作。在Linux中对于正在运行中的程序会存在pcb来对其进行描述,打开文件这个操作也不例外,必然也存在对应的描述信息。

在讲解进程概念的时候,我们了解过对于pcb的底层实现上也是作为一个task_struct的结构体出现的,该结构体中一个指针指向struct files_struct结构体来对打开文件的信息进行描述,在struct files_struct结构体中存在一个struct file *fd_arry[]数组。

大致了解完文件打开之后的Linux底层后,当我们执行一个程序的时候,系统便会默认打开三个文件:标准输出-0;标准输出-1;标准错误-2。

如何对于文件描述符的分配规则是:最小未使用原则,即struct file *fd_arry[]数组从中下标从小到大进行分配,我们来通过代码对上述内容进行一个演示:

从ccfile.c和其执行结果我们可以看出,打开test.txt所分配到的文件描述符fd = 3,这与我们前文中的描述相符。因为struct file *fd_arry[]数组的前3位已经会被默认打开的3种文件描述符占用。

2.3原理

在了解完Linux中系统描述符的分配规则和存储位置后,我们言归正传来聊一聊重定向的原理。

重定向原理其实也十分简单,它本质上就是将一个描述符所对应位置的文件描述信息地址,替换成另外一个文件的描述。这便实现了在不改变逻辑的情况下,改变了所操作的文件。

3.动态库与静态库的生成和使用

3.1内容

这一部分内容我们来了解5个名词:库文件、动态库、静态库、动态链接和静态链接。

库文件:(库文件中包含着的便是我们常用的库函数),库文件是将已实现的代码进行打包封装,并不是为了生成可执行程序,而是将其作为接口来供我们使用。

动态库:和位置无关代码打包。静态库:单独的文件。

动态链接:生成可执行程序的时候,连接动态库,记录库中的符号表,并且多个程序运行时在内存可以共享同一个动态库。运行时依赖动态库存在,因为程序运行时才将动态库加载到内存当中。

静态链接:生成可执行程序的时候,连接静态库,直接将库中所用到的函数实现,拿到可执行程序之中,不存在运行依赖,效率较高。但是生成的可执行程序较大,并且如果运行了多个用到同一个静态库的程序,则代码内存中可能存在冗余。

3.2生成库

生成库的作用就是将大量已经实现的代码打包起来,便于以后的多次使用。在Linux中对于库的生成也有与之相对应的指令,不同的指令来生成动态库和静态库。

  1. 先将所有的原码进行编译汇编成各自的二进制指令:gcc test.c -o test.o;
  2. 将所有的二进制文件给打包到一起。

3.2.1动态库

动态库:gcc -fPIC -c test.c -o test.o(生成动态库的所需要的二进制文件指令),gcc --shared test.c -o libmytest.so(生成.so文件,即动态库文件)。(Linux中动态库命名:以lib作为前缀,以.so作为后缀,中间是库名称)

其中,-fPIC是告诉编译器,在编译生成指令的时候产生和位置无关的代码(变量指令都是相对偏移指令)。当一个动态库被映射到不同进程的虚拟地址时,映射的位置也不尽相同。

因此,main函数对其的调用就会变得的麻烦(动态库具体位置不同,且其是运行时才被加载),所以在所有的main中所调用的库函数都只是记录一个相对偏移量,最后根据实际映射的起始地址开始计算。

3.2.2静态库

静态库:gcc -c test.c -o test.o(先汇编生成二进制指令),ar -cr libmytest.a test.o(生成静态库文件test.o)。(Linux中静态库命名:以lib作为前缀,.a作为后缀)

3.3使用库

使用 -l 来告诉编译器需要使用那一个库,gcc main.c -o main -lmytest。

但是这种直接使用的方式大概率会产生报错,因为编译器默认会在指定目录(/user/lib64)查找对应的库文件,而我们未将其放置在系统指定目录中,所以会出错。

那么解决该问题存在两种方式,一种针对报错情况直接进行解决,即将我们的库文件放置到系统指定目录之中;另一种是通过配置环境变量的方式。

  1. 将库文件放置到指定目录中:64位操作系统 -- /user/lib64,32位操作系统 -- /user/lib32;
  2. 设置环境变量:export LIBRARY_PATH=${LIBRARY_PATH}:./ -- 将库文件所在目录添加到环境变量值中, export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:./ -- 添加运行加载库文件的路径。
  3. 还有一种方式来加载库,不过这种方式只适用于加载静态库与,因为它无法设置运行程序时的库加载路径,所以我们单独来看。gcc -L选项,gcc main.c -o -L./-lmytest。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值