关于inode,dentry结合软链接及硬链接的实验
一、背景
在之前的博客 缺页异常导致的iowait打印出相关文件的绝对路径-CSDN博客 里 2.2.3 一节里,我们讲到了file,fd,inode,dentry,super_block这几个概念,在这篇博客里,我们针对inode和dentry做一些实验,针对的是软链接和硬链接的场景。
二、实验源码及最普通常见的场景
2.1 实验源码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/dcache.h>
#include <linux/namei.h>// 模块参数
static char *filepath = "/tmp/testfile"; // 默认文件路径
module_param(filepath, charp, S_IRUGO);
MODULE_PARM_DESC(filepath, "Path of the file to open");char buffer[4096];int getfullpath(struct inode *inode)
{struct dentry *dentry;hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {char *path;path = dentry_path_raw(dentry, buffer, PAGE_SIZE);if (IS_ERR(path)){continue; }printk("dentry name = %s , path = %s\n", dentry->d_name.name, path);}return 0;
}static int __init my_module_init(void) {struct file *file;printk(KERN_INFO "Opening file: %s\n", filepath);// 打开文件file = filp_open(filepath, O_RDONLY, 0);if (IS_ERR(file)) {printk(KERN_ERR "Error opening file: %ld\n", PTR_ERR(file));return PTR_ERR(file);}getfullpath(file->f_inode);// 关闭文件filp_close(file, NULL);return -EINVAL;
}static void __exit my_module_exit(void) {printk(KERN_INFO "Module exiting\n");
}module_init(my_module_init);
module_exit(my_module_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zhaoxin");
MODULE_DESCRIPTION("A simple module to read dentry from a file's inode");
2.2 源码分析
上面的源码还是比较简单的,在内核模块里打开一个文件,使用传入的filepath参数,要注意,如果用file_path这个名字会造成和内核里的file_path的符号相冲突导致编译不过的情况。
内核模块根据传入的filepath的路径(可以是相对路径)打开文件,然后使用打开的文件里的file->f_inode作为参数,传给getfullpath函数,这个getfullpath函数改造自之前的博客 缺页异常导致的iowait打印出相关文件的绝对路径-CSDN博客 里的 2.2.3 一节里的getfullpath函数,改得更简单,只是打印到dmesg里:

insmod ko一定会返回失败,为了方便调试,不用rmmod,可直接再运行insmod:

2.3 最普通场景的场景的运行情况
我们创建一个aa.txt文件,然后执行insmod testinode.ko filepath=aa.txt
dmesg的内容如下:

这时候,这个aa.txt就一个文件,没有创建过相关的硬链接或软链接。
三、增加一个硬链接后的运行情况
我们通过如下命令创建一个硬链接:
ln aa.txt bb.txt
然后执行一样的命令:
insmod testinode.ko filepath=aa.txt
dmesg里的内容如下:

如果用:
insmod testinode.ko filepath=bb.txt
dmesg里的内容是一样的:

可以看到,如果创建一个硬链接后,用其中任意一个符号来open文件,通过其对应的inode遍历得到的dentry全路径是一模一样的。
为了进一步做实验,我们把inode的指针也打出来:

可以从上图里看到,无论是打开aa.txt还是打开bb.txt,其inode的地址是一样的。
四、增加一个软链接后的运行情况
通过ln -s bb.txt slinkbb.txt之后,再运行抓到的dmesg情况:

可以看到用软链接的名字来open和用硬链接的名字来open,得到的file的f_inode地址是一样的,自然通过f_inode指针遍历得到的dentry也是一样的。
我们用file里的f_path.dentry来打印出其name:
do {char *path;path = dentry_path_raw(file->f_path.dentry, buffer, PAGE_SIZE);if (IS_ERR(path)){break;}printk("[2] dentry name = %s , path = %s\n", file->f_path.dentry->d_name.name, path);} while(0);
得到的dmesg如下:

说明file里的f_path.dentry可以得到它的软链接的源头文件路径。
4.1 软链接不同于硬链接,会新分配一个inode
通过ls -li如下图就可以看到新增一个硬链接并不会新增一个inode,而新增一个软链接就会新增一个inode(另外,之所以用open出来的file看似关联不上这个新的inode,因为它已经在filp_open期间根据软链接的inode找到了实体文件)

另外,软链接可以链接一个文件夹或一个不存在的文件,而硬链接不行。
4.2 软链接相关的内核实现
我们看一下软链接相关的内核实现,看看是哪里分配的一个inode。
创建软链接的系统调用是symlink,如下图实现:

看一下它调用的do_symlinkat的实现:

上图里创建软链接的核心函数是红色框出的vfs_symlink函数,如下图调用的是对应文件系统的symlink实现:

比如ext4的symlink实现,如下图里的ext4_new_inode_start_handle函数来创建新的inode:

然后调用下图里的ext4_add_nondir函数来把创建出来的inode放到所在的目录的数据块里(也建立了inode和dentry的链接):

相关文章:
关于inode,dentry结合软链接及硬链接的实验
一、背景 在之前的博客 缺页异常导致的iowait打印出相关文件的绝对路径-CSDN博客 里 2.2.3 一节里,我们讲到了file,fd,inode,dentry,super_block这几个概念,在这篇博客里,我们针对inode和dentr…...
PandasAI:当数据分析遇上自然语言处理
数据科学的新范式 在数据爆炸的时代,传统的数据分析工具正面临着前所未有的挑战。数据科学家们常常需要花费70%的时间在数据清洗和探索上,而真正的价值创造时间却被大幅压缩。PandasAI的出现,正在改变这一现状——它将生成式AI的强大能力注入…...
Unity网络开发基础 (3) Socket入门 TCP同步连接 与 简单封装练习
本文章不作任何商业用途 仅作学习与交流 教程来自Unity唐老狮 关于练习题部分是我观看教程之后自己实现 所以和老师写法可能不太一样 唐老师说掌握其基本思路即可,因为前端程序一般不需要去写后端逻辑 1.认识Socket的重要API Socket是什么 Socket(套接字࿰…...
做题记录:和为K的子数组
来自leetcode 560 前言 自己只会暴力,这里就是记录一下前缀和哈希表的做法,来自灵神的前缀和哈希表:从两次遍历到一次遍历,附变形题 正文 首先,这道题无法使用滑动窗口,因为滑动窗口需要满足单调性&am…...
VMware虚拟机卡顿、CPU利用率低、编译Linux内核慢,问题解决与实验对比
目录 一、总结在前面(节约时间就只看这里)0 环境说明1 遇到的问题:2 问题的原因:3 解决办法:4 实验验证:5 关于虚拟机内核数量设置6 关于强行指定Vm能用的CPU内核 二、管理员启动,实验对比实验1…...
【7】数据结构的队列篇章
目录标题 队列的定义顺序队列的实现初始化入队出队顺序队列总代码与调试 循环队列的实现初始化入队出队获取队首元素循环队列总代码与调试 链式队列的实现链式队列的初始化入队出队获取队首元素链式队列总代码与调试 队列的定义 定义:队列(Queue&#x…...
颜色归一化操作
当我们不太关注图像具体细节,只关注图像大致的内容时,为了避免光照角度、光照强度对图像的影响,可以采用下面进行归一化操作。这种颜色系统具有通道对表面方向、照明方向具有鲁棒性的特性,适用于图像分割等领域,在机器…...
2874. 有序三元组中的最大值 II
给你一个下标从 0 开始的整数数组 。nums 请你从所有满足 的下标三元组 中,找出并返回下标三元组的最大值。 如果所有满足条件的三元组的值都是负数,则返回 。i < j < k(i, j, k)0 下标三元组 的值等于 。(i, j, k)(nums[i] - nums[j]) * nums[k…...
05-Spring Security 认证与授权机制源码解析
Spring Security 认证与授权机制源码解析 结合之前的IOC、AOP、事务管理, 这一篇讲讲Spring 的安全性,以下是小弟对Spring Security的一些理解,以及在真实面试中碰到的一些问题做了些整理,欢迎各位大佬一起观摩指点!&a…...
深度学习处理文本(6)
理解词嵌入 重要的是,进行one-hot编码时,你做了一个与特征工程有关的决策。你向模型中注入了有关特征空间结构的基本假设。这个假设是:你所编码的不同词元之间是相互独立的。事实上,one-hot向量之间都是相互正交的。对于单词而言…...
STL-vector的使用
1.STL-vector 向量是可以改变其大小的线性序列容器。向量使用连续的空间存储元素,表明向量可以像数组通过下标来访问元素,但是向量的大小可以动态变化。向量的容量可能大于其元素需要的实际容量,向量通过消耗更多的内存来换取存储管理效率。…...
MySQL深入
体系结构 连接层:主要处理客户端的连接进行授权认证、校验权限等相关操作 服务层:如sql的接口、解析、优化在这里完成,所有跨存储引擎的操作在这里完成 引擎层:索引是在存储引擎层实现的,所以不同的存储引擎他的索引…...
为什么LoRA在目标检测方向不奏效?
最近在思考,为啥目标检测方向没有出现LORA的相关用法,搜索到了一篇文章,挺有深度的。 Why LoRA Struggles with Object Detection (and Why I Learned This the Hard Way) 链接:https://medium.com/predict/why-lora-struggles-with-object-detection-and-why-i-learned-…...
Vue面试常考内容[从宏观到微观]
以下是Vue面试常考内容的系统性解析,从框架设计思想到源码实现细节,结合最新技术动态(截至2025年4月)整理而成: 一、宏观层面:Vue设计哲学与框架定位 渐进式框架核心 • 分层可扩展架构:从视图层核心逐步集成路由、状态管理等能力,支持"按需取用"的渐进式开发…...
Genspark:重新定义搜索体验的AI智能体引擎
关于我们 飞书-华彬智融知识库 由前百度高管景鲲(Eric Jing)和朱凯华(Kay Zhu)联合创立的AI搜索引擎Genspark,正以革命性的技术架构和用户导向的设计理念,为全球用户带来一场搜索体验的范式革命。本文将基…...
从零实现Json-Rpc框架】- 项目实现 - 服务端主题实现及整体封装
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
AI助力PPT制作,让演示变得轻松高效
AI助力PPT制作,让演示变得轻松高效!随着科技的进步,AI技术早已渗透到各行各业,特别是在办公领域,AI制作PPT已不再是未来的梦想,而是现实的工具。以前你可能需要花费数小时来制作一个完美的PPT,如…...
React-01React创建第一个项目(npm install -g create-react-app)
1. React特点 JSX是javaScript语法的扩展,React开发不一定使用JSX。单向响应的数据流,React实现单向数据流,减少重复代码,比传统数据绑定更简单。等等 JSX是js的语法扩展,允许在js中编写类似HTML的代码 const …...
HTML应用指南:利用POST请求获取三大运营商5G基站位置信息(二)
在当前信息技术迅猛发展的背景下,第五代移动通信(5G)技术作为新一代的无线通信标准,正逐步成为推动社会进步和产业升级的关键驱动力。三大电信运营商(中国移动、中国联通、中国电信)在全国范围内的5G基站部署,不仅极大地提升了网络性能,也为智能城市、物联网、自动驾驶…...
C++学习笔记之内存管理
仅用于记录学习理解 选择题答案及解析 globalVar:C(数据段 (静态区)) 解析:全局变量存放在数据段(静态区),生命周期从程序开始到结束,程序运行期间一直存在。 staticGlobalVar&…...
针对 MySQL 数据库中 主键/唯一约束的更新方法 和 ON DUPLICATE KEY UPDATE 语法的详细说明及示例,并以表格总结
以下是针对 MySQL 数据库中 主键/唯一约束的更新方法 和 ON DUPLICATE KEY UPDATE 语法的详细说明及示例,并以表格总结: 一、主键的更新 1. 更新主键的条件 允许更新:MySQL 允许更新主键列,但需满足以下条件: 唯一性…...
day21 学习笔记
文章目录 前言一、删除数据二、索引操作1.loc方法2.iloc方法 三、添加数据1.loc方法添加数据2.concat方法拼接数据 四、重置索引 前言 通过今天的学习,我掌握了对Pandas对象数据元素进行增删操作以及重置索引的操作 一、删除数据 DataFrame.drop(labelsNone, axis…...
【MyBatis】深入解析 MyBatis XML 开发:增删改查操作和方法命名规范、@Param 重命名参数、XML 返回自增主键方法
增删改查操作 接下来,我们来实现一下用户的增加、删除和修改的操作。 增( Insert ) UserInfoMapper接口: 我们写好UserInfoMapper接口后,自动生成 XML 代码; UserInfoMapper.xml实现: 增删改查方法命名规范 如果我们…...
【Pandas】pandas DataFrame select_dtypes
Pandas2.2 DataFrame Attributes and underlying data 方法描述DataFrame.index用于获取 DataFrame 的行索引DataFrame.columns用于获取 DataFrame 的列标签DataFrame.dtypes用于获取 DataFrame 中每一列的数据类型DataFrame.info([verbose, buf, max_cols, …])用于提供 Dat…...
使用Python构建Kafka示例项目
新建项目 mkdir python-kafka-test cd python-kafka-test 安装依赖 pip install confluent_kafka 创建配置文件 # Kafka配置文件# Kafka服务器配置 KAFKA_CONFIG {bootstrap.servers: localhost:9092,# 生产者特定配置producer: {client.id: python-kafka-producer,acks:…...
本地化部署DeepSeek-R1蒸馏大模型:基于飞桨PaddleNLP 3.0的实战指南
目录 一、飞桨框架3.0:大模型推理新范式的开启1.1 自动并行机制革新:解放多卡推理1.2 推理-训练统一设计:一套代码全流程复用 二、本地部署DeepSeek-R1-Distill-Llama-8B的实战流程2.1 机器环境说明2.2 模型与推理脚本准备2.3 启动 Docker 容…...
VBA 64位API声明语句第008讲
跟我学VBA,我这里专注VBA, 授人以渔。我98年开始,从源码接触VBA已经20余年了,随着年龄的增长,越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友,都来学习VBA,利用VBA,起码可以提高…...
Linux信号——信号的保存(2)
关于core和term两种终止方式 core是什么? 将进程在内存中的核心数据(与调试有关)转存到磁盘中形成core,core.pid的文件。 core dump:核心转储。 core与term的区别: term只是普通的终止,而core终止方式还要…...
PyQt6实例_A股日数据维护工具_权息数据增量更新线程
目录 前置: 代码: 1 工作类 2 数据库交互 3 主界面启用子线程 视频: 前置: 1 本系列将以 “PyQt6实例_A股日数据维护工具” 开头放置在“PyQt6实例”专栏 专栏地址 https://blog.csdn.net/m0_37967652/category_12929760.h…...
【蓝桥杯嵌入式——学习笔记一】2016年第七届省赛真题重难点解析记录,闭坑指南(文末附完整代码)
在读题过程中发现本次使用的是串口2,需要配置串口2。 但在查看产品手册时发现PA14同时也是SWCLK。 所以在使用串口2时需要拔下跳线帽去连接CH340。 可能是用到串口2的缘故,在烧录时发现报了一个错误。这时我们要想烧录得按着复位键去点击烧录,…...
