系统编程--Linux下文件的“其他操作”函数

这里写目录标题

  • 文件存储理论补充
    • dentry、inode
  • 文件其他操作
    • stat函数
      • 作用
      • 函数原型
      • 代码(以获取文件大小为例)
      • 补充(获取文件类型)
    • lstat函数
      • 作用
      • 函数原型
      • 代码
      • 补充(获取文件权限)
      • 总结
    • tips
    • link函数
      • 作用
      • 简介
      • 函数原型
      • 代码(模拟mv命令进行文件重命名)
    • unlink
      • 作用
      • 简介
      • 代码
    • 补充:隐式回收
      • 问题产生
      • 解决问题
    • readlink
    • rename

文件存储理论补充

dentry、inode

在这里插入图片描述

首先我们知道,inode,在创建硬链接的时候用到过,如下图:
在这里插入图片描述
当我们创建一个文件的硬链接时,该硬链接会有一个与文件一样的Inode

但是Indoe是什么:
Inode是一个结构体,存储着文件属性的结构体,他会存储一个文件的各种属性,以及“该文件在磁盘中的位置”,但是没有存储文件名

而dentry,存储着文件名+该文件的inode,相当于是一个目录,其名字也是"目录项"

当我们描述一个文件时,首先会根据dentry,找到他的inode,之后就知道了该文件的各种属性,而通过inode记录的文件的磁盘位置,就可以看到文件的内容了

而我们平时创建硬链接的底层原理是:
在这里插入图片描述
创建一个硬链接,就会创建出一个dentry,其文件名就是硬链接的文件名,匹配的就是目标文件的inode,这样就建立了硬链接,这也是为什么硬链接会与原文件有相同的inode

而删除硬链接,以及删除文件:
在这里插入图片描述
删除硬链接,其实就是删除dentry,删除一个dentry,其硬链接计数就会减一

当删除完所有的硬链接,然后又删除了文件,那么就会把所有的dentry都删除了,那么这个文件的inode就没有dentry引用了

但是此时,在磁盘中的文件安然无恙,也就是说,删除文件并不会真正的去磁盘中删除文件,而这个磁盘的内容,只有在没有dentry引用其inode的情况下,会被其他文件所覆盖,覆盖了才是真正意义的删除

数据恢复:
在这里插入图片描述
如果磁盘文件内容还没有被覆盖,我们就可以对该部分数据再次建立一个inode以及dentry,就可以做到对数据的恢复

文件其他操作

stat函数

man 2卷

作用

获取文件的各种属性

函数原型

在这里插入图片描述
参数一:文件路径(精确到文件名)
参数二:传出参数,指向struct stat类型的变量的指针

其中 stat结构体的内容:(实际上就是inode的内容,也就是我们平时ls -l (小L)显示的内容)
在这里插入图片描述

在这里插入图片描述

代码(以获取文件大小为例)

在这里插入图片描述
最终在sbuf结构体中已经有了该文件的所有属性,想打印哪个就打印哪个

这里我们打印文件的大小,这个可以实现与“lseek获取文件大小”相同的效果,且该方式是推荐的方法

注意使用%ld进行打印,其类型为unsinged long int

补充(获取文件类型)

在这里插入图片描述
拿到stat结构体变量中的数据后,在该结构体中有一个st_mode属性,利用该属性,配合其提供的宏函数,我们可以完成上图中的一些判断(如判断该文件是否是一个普通文件、还是一个目录?…)

而宏函数一般只返回0或1,也就是返回真或者假,他会告诉你是或不是

代码:
在这里插入图片描述

但是:
当我们测试其他类型没有问题,但当我们测试“符号链接”类型时,出现了问题:

首先我们创建两个符号链接:
在这里插入图片描述
在这里插入图片描述

结果是:在这里插入图片描述

可以看到,最终打印的都是符号链接所指向的最终的实体文件,该现象称为stat穿透,默认情况下stat是穿透的,如何解决,看下一个函数

lstat函数

作用

解决stat函数的“穿透”现象

函数原型

与stat函数原型一样

代码

在这里插入图片描述
与stat函数使用规则一样,只不过加了一个 “l” (小L)

结果:
在这里插入图片描述

在这里插入图片描述
实际上,我们的vim、cat,都是穿透的(作用到最终指向的实体文件)
而ls -l 是不穿透的 (作用于“链接本身”)

补充(获取文件权限)

在这里插入图片描述
在man中的demo没有使用宏函数进行文件类型的判断,而是使用了位运算

简单解释一下:
这里还是用到了位图:
在这里插入图片描述
一个位图,有2字节,16位,从右向左,每三个为一组,一共三组,共9位,分别代表不同组的文件权限(用户、用户组、其他用户)
再往左三位是特殊权限位
最开始的四位是文件类型,四位,转为八进制其总数就是17(即017,0是八进制的前缀)

上图中的S_IFMI就是017,也就是其二进制为1111 000 000 000 000,由于他前面都是1,所以可以作为掩码使用,所以st_mode & S_IFMT,最终得到S_IFMT下面的宏,就对应其表示的信息,由此可见,使用该方式,不仅可以获取到文件类型(宏函数可以获取),还可以获取到不同组的执行权限等信息(宏函数获取不到):
在这里插入图片描述

总结

在这里插入图片描述
因为lstat与stat没有其他区别,而且lstat不会进行穿透,所以,以后我们直接使用lstat就可以了

tips

在这里插入图片描述
在一些重要的函数的man手册中,我们点击“G”,会跳到最下面,这里可能会有一个当前函数的demo示例

link函数

man 2卷

作用

在这里插入图片描述
我们之前创建硬链接,都是通过命令行的ln命令,但是在代码中,我们不可能去到终端敲命令,所以就有了link函数,他就是负责创建硬链接的,实际上,是为文件新建一个dentry项

通过上面这张图我们也能知道,硬链接不像软链接,他在ll时,并不会表现为链接文件名,而是类似于创建了一个新文件,这也符合硬链接的原理:创建多个dentry,指向inode,所以,一个文件被刚创建时,系统就自动的为其创建了一个dentry,这就是我们常见的文件

简介

在这里插入图片描述
建立硬链接,也就是新建dentry项,而使用mv命令修改文件名时,也是修改了dentry,并不对真正的文件做操作(利用原先的dentry,创建出一个新的dentry,之后将原先的系统创建的dentry删除,就完成了文件的改名)

函数原型

在这里插入图片描述
参数一:原先的文件的dentry路径(精确到文件名)
当我们创建一个新的文件时,系统在磁盘写入了文件之后,会自动创建一个dentry,这个就是我们平时看到的文件

参数二:新的dentry路径(若没有,系统自动创建,一般是没有,因为硬链接都是新建的)

代码(模拟mv命令进行文件重命名)

在这里插入图片描述

效果:
在这里插入图片描述
先利用原先系统创建的dentry,建立新的dentry,之后将原先的那个删掉,使用unlink函数,直接传入文件路径即可

unlink

作用

解除一个硬链接(或者当前文件只有一个dentry时(也就是硬链接计数为1,即文件刚创建的状态),对当前文件进行“删除”(只是让其具备删除条件))

简介

在这里插入图片描述
可以看到,这里也说了,当一个文件的目录项(dentry)没有时,该文件会被操作系统择机释放,因此,我们删除一个文件,只是让文件具备了被释放的条件,什么时候释放,由系统决定,且打开该文件的进程必须关闭了,才能被释放

代码

需求:我们要在一个程序运行时,创建并打开一个文件,在程序结束时,这个文件要被销毁

在这里插入图片描述
在这里插入图片描述
我们在程序的末尾,在return之前,将该文件unlink掉,就可以实现上述的需求了

在程序第35行,设置了一个getchar(),该函数的作用是与用户进行IO交互,这里相当于“阻塞”,阻塞程序,不让程序结束,这样可以方便我们进行测试,(例如在另一个终端查看程序未结束时,那个临时文件在不在)

但是,假如说我们的程序在执行到39行之前,程序崩了,那么无法执行后续的代码便使得主函数退出了,这样的话,那个临时文件就不会被删除,如下图:
在这里插入图片描述
假如说,我们在34行,对p这个只读变量进行写入操作,那么会发生段错误(访问非法内存,或更改只读变量),程序崩溃,由此一来,那个临时文件不会被删除

如何解决:
在这里插入图片描述
直接将该部分unlink代码,放到open后面

我们不用担心在这里把临时文件unlink掉之后,后续的代码就找不到文件了,这个是不会的,因为unlink,只是将dentry删除,文件还在磁盘,等待所有使用该文件的进程结束了,系统才会择机释放,当前进程使用着临时文件,所以该文件不会被释放,仍然存在,这样,就不怕后续发生程序崩溃导致unlink没执行了

而如果程序正常进行,此时就算有阻塞,我们开另一个终端去查该临时文件,也是找不到的,而向该文件写入的内容,是被写入到了内核缓冲区里面

补充:隐式回收

问题产生

在这里插入图片描述
我们程序发生了段错误,程序崩溃,后续的close没有执行,那这个fd会一直占用着系统资源吗(占位符3,0、1、2是标准输入输出出错)

解决问题

在这里插入图片描述
答案是不会,因为程序的进程一旦被退出,那么该进程所有的内存资源都会被回收,这一过程称为“隐式回收”,也就是一个进程被关闭时,所有的内存会被释放(包括泄露的和不泄露的),但是也不能忽视内存泄漏,因为很多程序是一直处于开启状态进行监听的,程序一直运行,无法关闭,就无法隐式回收

readlink

在这里插入图片描述
在我们创建一个软链接后,其软链接的大小是指:创建连接时,敲入的链接文件的路径,被他当做字符串存了起来

而我们如何查看一个已有的软链接的指向呢,使用cat是不行的,因为他会进行穿透

所以使用一个命令:readlink,就可以拿到软链接链接的文件路径(创建时使用的相对路径会显示相对路径,创建时使用的绝对路径,就会显示绝对路径)
在这里插入图片描述
该命令也有一个函数,将结果返回到缓冲区buf中

rename

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/48366.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端页面:用户交互持续时间跟踪(duration)user-interaction-tracker

引言 在用户至上的时代,精准把握用户行为已成为产品优化的关键。本文将详细介绍 user-interaction-tracker 库,它提供了一种高效的解决方案,用于跟踪用户交互的持续时间,并提升项目埋点的效率。通过本文,你将了解到如…

使用水星Mecury人形机器人搭建VR遥操作控制平台!

VR遥操作机械臂是一种将虚拟现实技术与机械臂控制相结合的系统,使用户可以通过虚拟现实设备操控和交互实际的机械臂。这种技术可以应用于多个领域,包括远程操作、培训、危险环境中的工作等。 双臂人形机器人是一种模拟人体上半身结构,包括头部…

跨域浏览器解决前端跨域问题

1.问题背景 这是一种属于非主流的解决跨域的方案,但是也是可以正常使用而且比较简单的。如果需要使用主流的解决前端跨域方案,请参考这篇文章。 我这边其实是优先建议大家使用主流的跨域方案,如果主流的实在不行,那么就使用跨域…

多路复用IO、TCP并发模型

时分复用 CPU单核在同一时刻只能做一件事情,一种解决办法是对CPU进行时分复用(多个事件流将CPU切割成多个时间片,不同事件流的时间片交替进行)。在计算机系统中,我们用线程或者进程来表示一条执行流,通过不同的线程或进程在操作系…

通过POST请求往Elastic批量插入数据

文章目录 引言I 请求文档请求参数请求例子引言 调试工具:Apifox 需求: 向Elasticsearch中的’test_index’索引批量插入文档 情况认证: Basic Auth 在 Header 添加参数 Authorization,其值为在 Basic 之后拼接空格,以及经过 Base64 编码的 {{Username}}:{{Password}} 示…

H3CNE(STP)

8.1 二层环路与STP的介绍 8.1.1 二层环路 8.1.2 冲突域 8.1.3 二层环路带来的问题 8.1.4 STP的基本概念:桥ID 8.1.5 STP的基本概念:根桥 8.1.6 STP的基本概念:Cost 8.1.7 STP的基本概念:Port ID 8.1.8 STP的基本概念:…

Ubuntu22.04下 MySQL8创建并使用存储过程

在Ubuntu下的MySQL 8中创建并使用存储过程: 使用mysql命令登录到MySQL服务器,例如: mysql -u root -p输入root用户的密码。 选择你想要创建存储过程的数据库,例如: CREATE DATABASE mydb;USE mydb;CREATE TABLE us…

pikachu Fileinclusion(local)

随便选择一个都试试 发现url上数字会变 发现文件名确实是file1.php~file5.php 那么会不会还有别的burp抓包选中数字 设置6-100的爆破 strat attack 678异常还有个100也是 先改一下试试看 其他的会报错 但是通过这我们可以得到路径 先写一个 下一步 读取系统文件 windows系统肯定…

【unity 新手教程 001/100】安装与窗口布局介绍

欢迎关注 、订阅专栏 【unity 新手教程】谢谢你的支持!💜💜 Unity下载与安装 👉点击跳转详细图文步骤:Unity Hub Unity 编辑器 窗口布局: Hierarchy: 层级窗口 | 默认 Sample Scene (main camera、direc…

矩阵分析——线性积分方程组的矩阵解法研究

矩阵分析——线性积分方程组的矩阵解法研究 前言线性积分方程组的矩阵解法研究 前言 “矩阵分析”是一门选修课,当时选这门课程的原因是想着图像处理就涉及到很多矩阵运算。但没想到的是这门课程吧虽然是选修,最后的结课要求是让我们写一篇“论文”&…

.dat 文件如何查看内容

第一种通过hexdump -C hexdump -C potk-00199D-0435-20000201.dat 命令查看 第二种 vscode ,将文件拖到vscode 工作区,选中要显示的乱码,点击右上角HEX图标,如下面两张图示

UM980高精度RTK定位模块支持哪些通信接口?

注 产品参数信息请以和芯星通最新版官方手册为准。

python-NLP:1中文分词

文章目录 规则分词正向最大匹配法逆向最大匹配法双向最大匹配法 统计分词语言模型HMM模型 jieba分词分词关键词提取词性标注 规则分词 基于规则的分词是一种机械分词方法,主要是通过维护词典,在切分语句时,将语句的每个字符串与词表中的词进行…

Java代码基础算法练习-字符串分类统计-2024.07.24

任务描述: 输入一行字符(字符串长度不超过255),分别统计出其中英文字母、数字、空格和其他 字符的个数。(提示,空格ASCALL码值为32) 解决思路: 输入一字符串,先判断是否…

对递归的一些理解。力扣206题:翻转链表

今天在刷力扣的时候,在写一道翻转链表的题目的过程中,在尝试使用递归解决该问题的时候,第一版代码却每次都返回的是null,这个错误让我尝试去debug了一下,最终找出了问题,并且让我对递归有了一些更深的理解&…

顶级电子合同平台推荐:2024年精选

本文将介绍以下10款工具:e签宝、法大大、上上签、金格签约、契约锁、DocuSign、Concord、PandaDoc、Agiloft、Evisort。 在当今数字化时代,选择一个合适的电子合同平台可能会让人感到困惑,如何判断哪个平台最适合企业的需求?电子合…

Java之数组应用-选择排序-插入排序

已经完全掌握了冒泡排序和二分查找的同学,可以自己尝试学习选择、插入排序。不要求今天全部掌握,最近2-3天掌握即可! 1 选择排序 选择排序(Selection Sort)的原理有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次…

超低功耗ARM Cortex-M33 TZ MCU STM32WBA54、STM32WBA55:通过提升无线性能实现更出色的用户体验

摘要 STM32WBA54、STM32WBA55产品系列同时支持多种无线标准,包括Bluetooth低功耗 5.4(已认证)、Zigbee、Thread以及可用作Thread边界路由器的Matter。 该产品系列具有出色的灵活性和更强的安全性,可帮助开发人员应对不断变化的无…

24暑假算法刷题 | Day21 | LeetCode 669. 修剪二叉搜索树,108. 将有序数组转换为二叉搜索树,538. 把二叉搜索树转换为累加树

目录 669. 修剪二叉搜索树题目描述题解 108. 将有序数组转换为二叉搜索树题目描述题解 538. 把二叉搜索树转换为累加树题目描述题解 669. 修剪二叉搜索树 点此跳转题目链接 题目描述 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪…

vite环境下使用bootstrap

环境 nodejs 18 pnpm 初始化 pnpm init pnpm add -D vite --registry http://registry.npm.taobao.org pnpm add bootstrap popperjs/core --registry http://registry.npm.taobao.org pnpm add -D sass --registry http://registry.npm.taobao.org新建vite.config.js cons…