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

idea Project 不显示文件和目录

idea Project 不显示文件和目录 File - Close Project - 重新打开项目即可删除.idea文件夹,重新打开项目即可。 原因分析: 可能与使用不同ide例如java、python打开同一项目有关 参考: https://blog.csdn.net/hgnuxc_1993/article/details/132595900 解决打开IDE…

CentOS修改yum源

这里写自定义目录标题 1、备份原来的文件下载新的文件清空并生成缓存 1、备份原来的文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup下载新的文件 下载新的文件CentOS-Base.repo 到/etc/yum.repos.d/ 注意系统版本 CentOS 5wget -O /et…

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

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的基本概念:…

uniapp安卓通过绝对路径获取文件

uniapp安卓通过绝对路径获取文件 在uniapp中,如果你想要访问安卓设备上的文件,你需要使用uniapp提供的plus.io API。这个API允许你在应用内访问设备的文件系统。 以下是一个示例代码,展示了如何使用plus.io API来获取文件: fun…

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

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

网络芯片(又称为PHY网络芯片)

Realtek RTL8152B是一种常见的主板集成网络芯片(又称为PHY网络芯片)。PHY芯片是指将网络控制芯片的运算部分交由处理器或南桥芯片处理,以简化线路设计,从而降低成本。 https://www.realtek.com/Download/List?cate_id585 Realt…

【ArrayList和LinkedList的区别】

1. 什么是ArrayList和LinkedList? ArrayList 是Java中的一个动态数组,它实现了List接口。它可以根据需要自动扩展容量,并且支持随机访问元素。LinkedList 是Java中的一个双向链表,它也实现了List接口。它通过节点之间的链接来存储元素&…

15 B端产品的迭代优化

新产品上线后,产品经理还需要不断挖掘新需求,对产品进行持续迭代升级,让产品更加成熟强大。 需求管理 需求收集 需求来源: 内部:老板战略目标分解、产品研发团队、市场营销、用户服务等。 外部:客户、行…

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…

数据库表约束

目录 一、约束的种类 二、非空约束(not null) 三、唯一性约束(unique) 3.1 字段级约束 四、主键约束(primary key,PK) 4.1 主键的概念(一张表例必须有外键的存在) 4.2 主键约束…

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

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

.dat 文件如何查看内容

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

Nginx设置目录的访问权限,方便访问静态资源

从日志信息来看,确实是权限问题(Permission denied)。我们可以重新检查并设置权限,确保 Nginx 用户有权限访问这些文件。 检查 Nginx 用户: 首先确认 Nginx 使用的用户,一般是 www-data 或 nginx。你可以在…

java HashMap代码解释

SimpleHashMap的部分抄袭解释 package com.zzc.common.utils;import lombok.extern.slf4j.Slf4j;import java.io.IOException; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.AbstractCollecti…