linux源码文件名,Linux中文件名解析处理源码分析

Linux中文件名解析处理源码分析

前言

Linux中对一个文件进行操作的时候,一件很重要的事情是对文件名进行解析处理,并且找到对应文件的inode对象,然后创建表示文件的file对象。在此,对文件名解析过程,并且如何找到对应inode的过程进行源码分析。分析代码基于Linux-3.2版本。

关键函数分析

不管是通过应用层的API函数还是在内核中打开一个文件,最终都需要调用filp_open函数,该函数的主要职责就是解析文件名,找到文件对应的inode对象,然后分配内存创建file对象,最后执行该文件对应的file->open函数。

filp_open的核心处理函数是path_openat,该函数分析如下:

static struct file *path_openat(int dfd, const char *pathname,

struct nameidata *nd, const struct open_flags *op, int flags)

{

struct file *base = NULL;

struct file *filp;

struct path path;

int error;

/* 创建一个file对象 */

filp = get_empty_filp();

if (!filp)

return ERR_PTR(-ENFILE);

.filp->f_flags = op->open_flag;

nd->intent.open.file = filp;

nd->intent.open.flags = open_to_namei_flags(op->open_flag);

nd->intent.open.create_mode = op->mode;

/* 初始化检索的起始目录,判断起始目录是根目录还是当前目录,并且初始化nd->inode对象,为link_path_walk函数的解析处理做准备。 */

error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);

if (unlikely(error))

goto out_filp;

.current->total_link_count = 0;

/* 关键的字符串解析处理函数,其核心思想是分级解析字符串,通过字符串对应的目录项找到下一级目录的inode节点。该函数的具体分析如下。 */

error = link_path_walk(pathname, nd);

if (unlikely(error))

goto out_filp;

/* do_last函数创建或者获取文件对应的inode对象,并且初始化file对象,至此一个表示打开文件的内存对象filp诞生 */

filp = do_last(nd, &path, op, pathname);

while (unlikely(!filp)) { /* trailing symlink */

struct path link = path;

void *cookie;

if (!(nd->flags & LOOKUP_FOLLOW)) {

path_put_conditional(&path, nd);

path_put(&nd->path);

filp = ERR_PTR(-ELOOP);

break;

}

nd->flags |= LOOKUP_PARENT;

nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);

error = follow_link(&link, nd, &cookie);

if (unlikely(error))

filp = ERR_PTR(error);

else

filp = do_last(nd, &path, op, pathname);

put_link(nd, &link, cookie);

}

out:

if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))

path_put(&nd->root);

if (base)

fput(base);

release_open_intent(nd);

return filp;

.out_filp:

filp = ERR_PTR(error);

goto out;

}

link_path_walk函数完成了基本的名字解析功能,是名字字符串解析处理实现的核心。该函数的实现基于分级解析处理的思想。例如,当需要解析“/dev/mapper/map0”字符串时,其首先需要判断从何处开始解析?根目录还是当前目录?案例是从根目录开始解析,那么获取根目录的dentry对象并开始分析后继字符串。以’/’字符为界按序提取字符串,首先我们可以提取”dev”字符串,并且计算该字符串的hash值,通过该hash值查找detry下的inode hash表,就可以得到/dev/目录的inode对象。依次类推,最后解析得到”/dev/mapper/”目录的inode对象以及文件名”map0”。至此,link_path_walk函数的使命完成,最后可以通过do_last函数获取或者创建文件inode。link_path_walk函数分析如下:

static int link_path_walk(const char *name, struct nameidata *nd)

{

struct path next;

int err;

/* 移除’/’字符 */

while (*name=='/')

name++;

/* 如果解析已经完成,直接返回 */

if (!*name)

return 0;

./* At this point we know we have a real path component. */

for(;;) {

unsigned long hash;

struct qstr this;

unsigned int c;

int type;

/* inode访问的permission检查 */

err = may_lookup(nd);

if (err)

break;

.this.name = name;

c = *(const unsigned char *)name;

/* 初始化hash值 */

hash = init_name_hash();

do {

name++;

/* 累计计算名字字符串的hash值 */

hash = partial_name_hash(c, hash);

c = *(const unsigned char *)name;

/* 如果遇到’/’字符,结束一次hash计算统计 */

} while (c && (c != '/'));

/* 得到字符串长度和hash结果 */

this.len = name - (const char *) this.name;

this.hash = end_name_hash(hash);

.type = LAST_NORM;

/* LAST_DOT和LAST_DOTDOT情形判断 */

if (this.name[0] == '.') switch (this.len) {

case 2: /* LAST_DOTDOT是上级目录 */

if (this.name[1] == '.') {

type = LAST_DOTDOT;

nd->flags |= LOOKUP_JUMPED;

}

break;

case 1: /* LAST_DOT是当前目录 */

type = LAST_DOT;

}

if (likely(type == LAST_NORM)) {

/* LAST_NORM标记说明是需要通过本地目录进行字符串解析 */

struct dentry *parent = nd->path.dentry;

nd->flags &= ~LOOKUP_JUMPED;

if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {

/* 如果该标记有效,需要重新计算hash值 */

err = parent->d_op->d_hash(parent, nd->inode,

&this);

if (err <0)

break;

}

}

/* 如果字符串已经解析完毕,直接跳转到last_component */

/* remove trailing slashes? */

if (!c)

goto last_component;

while (*++name == '/');

if (!*name)

goto last_component;

/* 通过walk_component函数找到解析字符串对应的inode,并且将nd->inode改称最新inode,准备继续解析后面的字符串信息。因为目录项所管理的inode在系统中通过hash表进行维护,因此,通过hash值可以很容易的找到inode。如果内存中还不存在inode对象,对于ext3文件系统会通过ext3_lookup函数从磁盘上获取inode的元数据信息,并且构造目录项中所有的inode对象。 */

err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);

if (err <0)

return err;

.if (err) {

err = nested_symlink(&next, nd);

if (err)

return err;

}

if (can_lookup(nd->inode))

continue;

/* 字符串还没有解析完毕,但是当前的inode已经继续不允许解析处理了,所以,返回错误码 */

err = -ENOTDIR;

break;

/* here ends the main loop */

.last_component:

/* 最后一个字符串不需要解析处理,需要由do_last函数来处理,此处结束解析,正确返回 */

nd->last = this;

nd->last_type = type;

return 0;

}

terminate_walk(nd);

return err;

}

小结

文件名解析处理是文件系统的必备功能,通过文件名的解析索引到表示文件的inode内存对象,并且创建文件对象file。在文件名解析的过程中,首先需要确定的是检索起始点,然后通过hash table查找目录项以及检索文件。在查找的过程中,需要考虑文件访问的权限以及符号连接等问题。总体来说这些代码难度不是很大,但是需要有一个整体的思路,就可以更好的理解分析代码了,这里只是对名字解析过程中的几个关键函数进行抛砖引玉式的分析。不正之处,敬请指出。

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

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

相关文章

帝国cms linux伪静态规则,帝国cms7.2伪静态规则怎么写

一、在linux主机下实现伪静态确认虚拟主机是否支持rewrite伪静态.htaccess文件。添加.htaccess 文件&#xff0c;把htaccess 文件放在网站根目录。二、在win主机下实现伪静态确认虚拟主机是否支持rewrite伪静态httpd.ini文件。添加httpd.ini文件&#xff0c;把httpd.ini文件放入…

linux core 永久生效,【调试】Core Dump是什么?Linux下如何正确永久开启?

内容简介【调试】Core Dump是什么&#xff1f;Linux下如何正确永久开启&#xff1f;Core Dump是什么&#xff1f;Linux下如何正确永久开启&#xff1f;Core Dump是什么&#xff1f;Core Dump乍听之下很抽象。当程序运行的过程中异常终止或崩溃&#xff0c;操作系统会将程序当时…

linux故障排查书籍,Linux系统故障排查和修复技巧.docx

fsck -y /cievZhdab(fsck为文件系统检测修复命令&#xff0c;“-y”设定检测到错误自动修复&#xff0c;Zdev/hda6 为发生错误的硬盘分区&#xff0c;请依据具体情况更改此参数) 系统修复完成后&#xff0c;用命令“reboot&#xff0c;重新启动即可? 案例三、GRUB选项设置错误…

用于用户C语言标识符,下列可用于C语言用户标识符的一组是( )

摘要&#xff1a;下列不属于骨肉瘤患者常见护理问题()于C语言用户组Since people send nonverbal signals through multiple channels simultaneously, it is impossible to increase our nonverbal communication competence by becoming more aware of how it operates in sp…

c语言编程常见问题解答,C语言编程常见问题解答之常用函数的包含文件

函数 包含 类别 功能_atold math.h 数学子程序 把字符串转换为浮点数_beginthread process.h 进程控制子程序 启动执行一个新线程_bios_disk bios.h 接口子程序 输出BIOS磁…

c语言猜四位数游戏猜10次,C语言猜数字游戏--随机生成4个不相同的数字从小到大排序,用户开始游戏,如果用户猜对数字和数字对应的位置,界面回馈A,如果数字正确位置不正确,则回馈B...

1.看程序运行截图吧&#xff01;&#xff01;由于博主本人较笨&#xff0c;就不动画演示了&#xff0c;如果动画的话可能将是一个漫长的过程&#xff01;猜数字游戏.png2.游戏题目随机生成4个不相同的数字从小到大排序&#xff0c;用户开始游戏&#xff0c;如果用户猜对数字和数…

双端堆c语言,数据结构——双端堆(C语言)

定义双端堆&#xff1a;是一棵完全二叉树&#xff0c;该完全二叉树要么为空&#xff0c;要么同时满足下列性质&#xff1a;(1) 根节点不包含元素&#xff1b;(2) 左子树是一个最小堆&#xff1b;(3) 右子树是一个最大堆&#xff1b;(4) 如果右子树不空&#xff0c;令i是左子树中…

C语言和我的世界指令哪个难,我的世界难度有什么区别 难度选择指令介绍

我的世界中的难度(Difficulty)可以在Minecraft的选项菜单内切换。更改这个选项将直接影响到游戏本身。选项中并没有设定影响攻击性生物的可生成数量&#xff0c;包括和平模式。目前游戏共有和平、简单、普通和困难4种难度。我的世界难度区别和平&#xff1a;会生成攻击性生物&a…

w ndows10即将停止更新,微软开始警告Windows 10 v1909用户即将停止更新服务

如果您仍在运行Windows 10版本1909&#xff0c;版本1903或更早版本&#xff0c;则可能已经在系统任务栏中注意到一条新消息&#xff1a;Windows 10版本即将终止服务。根据Windows 10 May 2020 Update或2020年10月Update。为了将用户升级到最新版本的Windows 10&#xff0c;“您…

筛法求素数c 语言,位筛法求素数,有段代码看不懂,有大佬可以来说一下

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼就是BITArray[ (i -3)/ CHAR_BIT ]其中i从0开始&#xff0c;那下标不就为负了&#xff1f;而指向的又是哪个数据&#xff1f;下面是完整代码。#include #include #include #include #include #include#include int main( ){unsigne…

c语言中日期间的天数怎么计算,关于计算两个日期间天数的代码,大家来看看...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼这是原贴:http://post.baidu.com/f?kz100411727这是原码:#include "stdio.h"main(){long int i,a[2],b[2],c[2],x[12]{0,31,59,90,120,151,181,212,243,273,304,334},y,z[2];scanf("%ld-%ld-%ld %ld-%ld-%ld"…

linux nf conntrack,Linux基于mark的策略路由以及nf_conntrack RELATED

谈到什么是意义&#xff0c;话题总显得很大&#xff0c;近日每晚都和老城里的朋友聊老城的文化&#xff0c;老城的老房子&#xff0c;老城的叫卖声&#xff0c;老城的方言…进行了很多的思考&#xff0c;也挺充实。至于技术方面&#xff0c;也有跟朋友以及前同事聊过&#xff0…

android 根据资源名称,如何在Android中按名称访问可绘制资源

你可以做这样的事情。public static Drawable getDrawable(String name) {Context context YourApplication.getContext();int resourceId context.getResources().getIdentifier(name, "drawable", YourApplication.getContext().getPackageName());return contex…

Android10不能用谷歌,谷歌真的很严格,一大波老APP将不能在安卓10.0运行

苹果iOS的一大优点就是软件生态&#xff0c;第三方APP都会主动适配新的iOS系统以及手机。虽然说Android的开放性是也是一大优点&#xff0c;但是第三方软件参差不齐的优化适配水平也让安卓的用户非常头疼。不过谷歌每年都在致力于让Android的软件生态更好。根据XDA的报道&#…

android 回归测试,android测试:monkey使用方法

android测试&#xff1a;monkey使用方法Android Sdk给我们提供了Monkey和Monkeyrunner这两个自动化测试工具。一、什么是MonkeyMonkey是一个命令行工具&#xff0c;可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流&#xff0c;实现对正在开发的应用程序进行压…

c语言编程季节输出春夏秋冬,c语言编程题: 用枚类型定义春、夏、秋、冬四个季节...

满意答案bcabcdefg2013.07.28采纳率&#xff1a;49% 等级&#xff1a;12已帮助&#xff1a;5373人#includeenum season{spring 1,summer,autumn,winter,};season GetSeasonByMonth(char month){if(month < 3 && month>1)return spring;else if(month < 6 …

android fragment addtobackstack,Android Fragment Back Stack的问题

我对android片段Backstack的工作方式遇到了一个很大的问题&#xff0c;对于提供的任何帮助将不胜感激。假设您有3个片段[1] [2] [3]我希望用户能够导航[1] > [2] > [3]但在返回的途中(按返回按钮)[3] > [1]。就像我想象的那样&#xff0c;这可以通过addToBackStack(..…

华为升级harmonyos的机型名单,华为鸿蒙 OS 2.0 系统适配名单已出,四月推送,天玑机型暂时无缘...

原标题&#xff1a;华为鸿蒙 OS 2.0 系统适配名单已出&#xff0c;四月推送&#xff0c;天玑机型暂时无缘华为官方在 2020 年发布了旗下自研系统“HarmonyOS 2.0”版本&#xff0c;发布会现场展示了 HarmonyOS 2.0 开发者 Beta 版本&#xff0c;并开启开发者 Beta 的公测。此外…

android如何实现QQ信息通知,android NotificationListenerService监听通知栏(qq 微信 短信)...

【实例简介】android NotificationListenerService 监听通知栏&#xff0c;android NotificationListenerService 监听通知栏 android NotificationListenerService 监听通知栏【实例截图】【核心代码】NLsevice└── NLsevice├── AndroidManifest.xml├── bin│ ├──…

rsync android app,如何rsync到android

问题描述如何连接到我的Android设备以rsync音乐(或其他东西)&#xff1f;最佳解决思路实际上在MTP /usb上使用rsync这比每个人都说的容易&#xff0c;首先注意到当GVFS安装MTP挂载时&#xff0c;它将在下面可用。您可以通过在图形file-browser(thunar /nautilus /etc)中打开手机…