当前位置:主页 > 查看内容

深入理解Linux文件操作,软硬链接与动静态库

发布时间:2021-05-15 00:00| 位朋友查看

简介:目录 文件描述符句柄 系统调用接口 open() write() lseek() read() dup2() 重定向 Linux文件系统(inode与软硬链接 inode 硬链接 软连接 动态库与静态库 概念 静态库 动态库 文件描述符句柄 计算机磁盘上有很多个文件操作系统要对这些文件进行管理。就必须建……

文件描述符(句柄)

  • 计算机磁盘上有很多个文件,操作系统要对这些文件进行管理。就必须建立相应的数据结构(struct结构体)来描述这个文件,然后在通过这个文件进行管理。事实上显示器,键盘对于操作系统来讲也就是一个文件,将其用结构体描述起来,与其他文件格一样,写程序时通过这个不同文件的结构体来对文件进行操作。
  • 一个进程可能会打开多个文件,每个进程也要对这些被打开的文件进行管理,所以在每个进程的pcb(进程控制块)中会有一个结构体指针数组。数组的每一个元素都是一个指向描述文件的结构体的指针。每打开一个文件,这个数组就多一个元素,关闭一个文件数组对应位置就被置为空。文件描述符就是该数组的下标。通过文件描述符可以找到描述该文件的结构体,进而可以对文件进行操作。
  • 进程运行开始时默认打开三个文件:标准输入,标准输出,标准错误。
  • 操作系统会为新打开的文件分配最小的未被使用的数组下标,所以新打开文件时默认分配的文件描述符从3开始

系统调用接口

open()

在这里插入图片描述
open()函数,打开一个文件,第一个参数,打开文件的路径与文件名,默认在当前路径。第二个参数,打开文件的方式(可一次指定多个参数,用"|"隔开),第三个参数,如果要打开的文件不存在且第二个参数表明不存在就创建文件,第三个参数为新创建文件的权限。
第二个参数有这几个常用的:
O_CREAT:如果要打开的文件不存在,则创建该文件
O_RDONLY:打开的文件有可读权限
O_WRONLY:打开的文件有可写权限
O_RDWR:打开的文件具有可读可写权限
O_TRUNC:打开文件时清空文件内容
O_APPEND:以追加方式打开文件
返回值:成功返回文件描述符,失败返回-1;
![在这里插入图片描述](https://img-blog.csdnimg.cn/2021040513300993.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNjQ3OTQy,size_16,color_FFFFFF,t_70
)
打开当前目录下的test.txt文件,打开的文件具有可读可写权限,如果文件不存在则创建该文件且文件的权限为0664.

write()

在这里插入图片描述
write()函数,往文件内写内容。第一个参数,文件描述符,往哪个文件里写入;第二个参数,字符串,要写入的内容;第三个参数,期望写入多少个字节。
返回值:实际写入的字节数。
在这里插入图片描述
打开一个文件,往文件里写入字符串"i like linux!"。

lseek()

lseek()函数
在这里插入图片描述
lseek()函数,调整当前文件的指针,每次对文件进行操作后,指针就会跳转到操作结束的位置,下一次对文件进行操作时就从该位置开始(如写操作,第一次写入一个字符串,指针指向字符串的结尾,这使要从文件读内容时就从该位置开始)。

第一个参数:文件描述符,对哪个文件进行操作;
第二个参数:从whence指定的位置,向前或者向后移动指定字节数;
第三个参数:
SEEK_SET:调到文件起始位置
SEEK_CUR:调到文件当前读写的位置
SEEK_END:调到文件末尾位置
返回值:返回当前读写位置相对于文件开始位置的偏移量(字节)。
在这里插入图片描述
执行写操作后,调整文件指针到文件最开始的位置。

read()

在这里插入图片描述
read()函数,从文件中读取内容。
第一个参数:文件描述符,从哪个文件中读取内容;
第二个参数:读取到buf内;
第三个参数:期望读取多少个字节;
返回值:实际读到的字节数。
在这里插入图片描述
将文件内容读到字符串buff里。

dup2()

在这里插入图片描述
dup2()函数,将旧的旧的文件描述符的内容拷贝到新的文件描述符里面,两个文件描述符指向指向同一个文件。

重定向

在这里插入图片描述

  • 实际上就是往文件里面写内容,执行echo命令时,实际上就是往显示器打印字符串,从文件的角度来看就是往1号文件(标准输出)里写入了"hello world"字符串。在增加重定向符号时,就相当于关闭当前进程的1号文件,然后在当前目录打开重定向符号后面的文件名,如果没有则创建,根据文件描述符分配规则,新打开的的文件的文件描述符会是1,然后还是将字符串写入1号文件,最后关闭该文件,重新打开标准输出,标准输出文件描述符还是1。
    在这里插入图片描述

  • 追加重定向实际上就是以追加方式打开文件。

Linux文件系统(inode与软硬链接)

inode

  • Linux使用ext2文件系统,磁盘被分为好多个块,文件存放在块中。为了提高效率,文件并不一定存放在连续的块中,所以文件被分别存放在哪些块里需要被保存起来。并且一个文件不只有文件内容,还有文件的属性信息,这些东西不属于文件内容,但是也要被保存起来,由此就产生了inode。

  • 每一个对应一个唯一的inode编号,inode中保存该文件的所有属性信息以及该文件被保存在哪些块中,所用通过inode可以找到文件具体存放在磁盘的那个位置,从而对文件进行操作。

硬链接

链接就是将A文件指向B文件,对A文件进行操作就相当于对B文件进行操作

硬链接本质上没有创建新的文件,只是有一个文件名,它的inode与他连接的文件的inode一样。
命令
ln 原文件 要创建的链接文件在这里插入图片描述
两个文件的inode一样。

软连接

软连接本质上是创建了一个新的文件,该文件里保存了链接对象的文件名与路径。
命令

ln -s 原文件  要创建的链接文件

在这里插入图片描述
两个文件的inode不一样。

动态库与静态库

概念

  • 我们写的程序都会包含头文件,因为里面有我们要用到的库函数,这里所说的库就是动态库或静态库。
  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

静态库

静态库的命名

lib[库名称].a

假如一个库的文件名为libhello.a,那么这个库的实际名称为hello

在这里插入图片描述
这里我写了三份代码,myprint.h里面放函数的声明,myprint.c里面放函数的实现。
print.c里面调用函数。
要把文件生成库文件,首先要将所有的.c文件编译为.o文件,然后将.o文件进行打包生成静态库。

gcc -c *.c

将所有的.o文件打包成静态库

ar -rc libprint.a myprint.o print.o

在这里插入图片描述

然后创建mylib文件夹,将头文件与静态库放到mylib文件下。
在这里插入图片描述
这样其他程序要使用该头文件与其头文件内定义的函数,就可以在编译时指定头文件查与静态库的路径路径,然后就可以直接使用了。
在这里插入图片描述
可以看到,我当前写的程序没有包含stdio.h,也没有定义Print函数,但是包含了myprint.h。只要在编译时指定头文件与要使用的库的路径,就可以正常使用了。
在这里插入图片描述

//-I
指要包含的头文件的路径,这里头文件在当前目录的mylib/include路径下

//-L
指库文件路径,这里库文件在当前目录的mylib/lib路径下

//l
指要用的库的名字,注意这里的名字要去除前缀与后缀。

//-static
指静态链接,即链接的是一个静态库

在这里插入图片描述
然后我们对其进行编译运行也没有任何问题。

动态库

动态库的命名与静态库的名称稍有不同。

lib[库名称].so

先将所有的.c文件生成.o文件。

gcc -fPIC -c *.c

-fPIC命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。
在这里插入图片描述
然后将所有.o文件生成libprint.so动态库文件。在这里插入图片描述
将生成的动态库与.h文件放在mylib.so文件下。

在这里插入图片描述

编译时链接动态库
在这里插入图片描述
但我们在运行时却发现不可以运行,因为链接动态库时程序在运行时遇到库函数才会把库函数加载到内存里运行,而我们只是在编译时加入动态库的路径,程序运行时并不知道动态库在哪里。
在这里插入图片描述
这个环境变量是指程序在运行时找动态库的路径,只需要把我们的动态库加进去就可以了。
在这里插入图片描述

;原文链接:https://blog.csdn.net/qq_43647942/article/details/115440787
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐