[文件系统]文件系统学习笔记(六)———pathwalk(1)

path_lookup函数 
path_walk函数
一:基本概念:

path_lookup函数的适用场景:open() stat() 等函数传进去的字符串的路径在内核里面都要转换成相应的inode节点和dentry结构体,执行这一任务的标准过程就是分析路径名并把它拆分成一个文件名序列。除了最后一个文件名以外,所有的文件名都必定是目录,如果路径名的第一个字符是“/”,例如:/usr/share/system-configure-ext2/test.conf,那么这个路径名是绝对路径,因此从current->fs->root(进程的根目录),所标识的目录开始搜索。否则,路径名是相对路径,因此从currrent->fs->pwd(进程的当前目录)所标识的目录开始搜索。

在对第一个目录的索引节点进行处理的过程中,代码要检查与第一个名字匹配的目录项,以获得相应的索引节点,然后,从缓存或磁盘读出包含那个索引节点的目录文件,并检查与第二个名字匹配的目录项,以获得相应的索引节点。对于包含在路径中的每个名字,这个过程反复执行。
在进行以上几点的时候要作如下考虑:
1,对每个目录的访问权必须进行检查,以验证是否允许进程读取这一目录的内容。
2,文件名可能是与任意一个路径名对应的符号链接;在这种情况下,分析必须扩展到那个路径名的所有分量。
3,符号链接可能导致循环引用;内核必须考虑这个可能性,并能在出现这种情况时将循环终止。
4,文件名可能是一个已安装文件系统的安装点。这种情况必须检测到,这样,查找操作必须延伸到新的文件系统。
5,路径名查找应该在发出系统调用的进程的命名空间中完成。由具有不同命名空间的两个进程使用的相同路径名,可能指定了不同的文件。

二:,path_lookup的入口函数是kern_path()函数,

[cpp] view plaincopy

  1. int kern_path(const char*name,unsigned int flags,struct path*path),

[cpp] view plaincopy

  1. 1920 long do_mount(char *dev_name, char *dir_name, char *type_page,
  2. 1921                   unsigned long flags, void *data_page)
  3. 1922 {
  4. 1923         struct path path;
  5. 1924         int retval = 0;
  6. 1940         retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);

name:指向要解析的文件路径名的指针,flags:标志的值,表示将会怎样访问查找的文件,nd:nameidata数据结构的地址,这个结构存放了查找操作的结果。

LOOKUP_FOLLOW:如果最后一个分量是符号链接,则解释(追踪)它
LOOKUP_DIRECTORY:最后一个分量必须是目录
LOOKUP_CONTINUE:在路径名中还有文件名要检查
LOOKUP_PARENT:查找最后一个分量名所在的目录
LOOKUP_NOALT:不考虑模拟根目录(在80x86体系结构中没有用)
LOOKUP_OPEN:试图打开一个文件
LOOKUP_CREATE:试图创建一个文件(如果不存在)

LOOKUP_ACCESS:试图为一个文件检查用户的权限

kern_path()函数最终会调用到do_path_lookup()函数,原型是:

[cpp] view plaincopy

  1. static int do_path_lookup(int dfd,const char*name,unsigned int flasgs,struct nameidata*nd)

do_path_lookup()函数最终会调用到path_lookupat()函数,原型是:

[cpp] view plaincopy

  1. static int path_lookupat(int dfd,const char*name,unsigned int flags,struct nameidata*nd)

dfd的含义:
1、当路径为相对路径,并dfd为特殊值AT_FDCWD,它被解释为相对于调用进程的当前工作目录。
2、当路径为相对路径,且没有设置,则从dfd指定的文件目录开始查找
3、当路径为绝对路径,dfd被忽略,从根目录开始查找
当path_lookup()返回时,结果参数nd指向的nameidata结构用与路径名查找操作有关的数据来填充:

[cpp] view plaincopy

  1. 18 struct nameidata {
  2. 19         struct path     path;   //保存当前路径分量的父路径,在该路径下查找路径分量
  3. 20         struct qstr     last;   //last包含了需要查找的名称,它是一个快速字符串,不仅包含字符串本身,还包含字符串长度和一个散列值。
  4. 21         struct path     root;   //当从根目录开始查找,需要设置root
  5. 22         unsigned int    flags;
  6. 23         int             last_type;  //路径名最后一个分量类型(当LOOKUP_PAPRENT设置时使用)
  7. 24         unsigned        depth;      //符号链接嵌套的当前级别
  8. 25         char *saved_names[MAX_NESTED_LINKS + 1];   //与嵌套的符号链接关联的路径名数组
  9. 27         /* Intent data */
  10. 28         union {
  11. 29                 struct open_intent open;    //单个成员联合体,指定如何访问文件
  12. 30         } intent;
  13. 31 };

LAST_NORM:最后一个分量是普通文件名
LAST_ROOT:最后一个分量是“/”(也就是整个路径名为“/”)
LAST_DOT:最后一个分量是“.”
LAST_DOTDOT:最后一个分量是“..”
LAST_BIND:最后一个分量是链接到特殊文件系统的符号链接
三:代码执行流程
目前使用的是RCU walk,写时拷贝,读写锁。

时间: 2024-10-03 14:55:48

[文件系统]文件系统学习笔记(六)———pathwalk(1)的相关文章

python之raw_input()(学习笔记六)

python之raw_input()(学习笔记六) 我们经常使用raw_input()读取用户的输入,如下例子所示: >>> name = raw_input('please input your name:'),截图如下: 下面简单说下,raw_input()与if搭配使用,脚本如下: #!/usr/bin/env python # -*- coding:utf-8 -*- birth = raw_input('birth:') if birth < 2000: print '0

swift学习笔记(六)析构过程和使用闭包对属性进行默认值赋值

一.通过闭包和函数实现属性的默认值 当某个存储属性的默认值需要定制时,可以通过闭包或全局函数来为其提供定制的默认值. 注:全局函数结构体和枚举使用关键字static标注    函数则使用class关键字标注 当对一个属性使用闭包函数进行赋值时,每当此属性所述的类型被创建实例时,对应的闭包或函数会被调用,而他们的返回值会被作为属性的默认值. ESC: Class SomeCLass{ let someProperty:SomeType={ //给someProperty赋一个默认值 //返回一个与

java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessController的checkPerssiom方法,访问控制器AccessController的栈检查机制又遍历整个 PerssiomCollection来判断具体拥有什么权限一旦发现栈中一个权限不允许的时候抛出异常否则简单的返回,这个过程实际上比我的描述要复杂 得多,这里我只是简单的一句带过,因为这

初探swift语言的学习笔记六(ARC-自动引用计数,内存管理)

Swift使用自动引用计数(ARC)来管理应用程序的内存使用.这表示内存管理已经是Swift的一部分,在大多数情况下,你并不需要考虑内存的管理.当实例并不再被需要时,ARC会自动释放这些实例所使用的内存. 另外需要注意的: 引用计数仅仅作用于类实例上.结构和枚举是值类型,而非引用类型,所以不能被引用存储和传递. swift的ARC工作过程 每当创建一个类的实例,ARC分配一个内存块来存储这个实例的信息,包含了类型信息和实例的属性值信息. 另外当实例不再被使用时,ARC会释放实例所占用的内存,这些

Linux System Programming 学习笔记(六) 进程调度

1. 进程调度 the process scheduler is the component of a kernel that selects which process to run next. 进程调度器需要使 处理器使用率最大化,并且提供 使多个进程并发执行的虚拟 Deciding which processes run, when, and for how long is the process scheduler's fundamental responsibility. 时间片:th

Lua学习笔记(六):函数-续

Lua中的函数是带有词法定界(lexical scoping)的第一类值(first-class values).第一类值指:在Lua中函数和其他值(数值.字符串)一样,函数可以被存放在变量中,也可以存放在表中,可以作为函数的参数,还可以作为函数的返回值.词法定界指:嵌套的函数可以访问他外部函数中的变量.这一特性给Lua提供了强大的编程能力. Lua中关于函数稍微难以理解的是函数也可以没有名字,匿名的.当我们提到函数名(比如print),实际上是说一个指向函数的变量,像持有其他类型的变量一样:

laravel3学习笔记(六)

原作者博客:ieqi.net ==================================================================================================== ORM Laravel3中MVC体系中Model里最重要的组成部分无疑是ORM了,ORM — object-relational mapper — 将数据操作面向对象化,使得整个web框架的核心风格统一,降低整体复杂度,为开发者提供便利. Laravel3中的ORM叫

IBatis.Net学习笔记六--再谈查询

在IBatis.Net学习笔记五--常用的查询方式 中我提到了一些IBatis.Net中的查询,特别是配置文件的写法. 后来通过大家的讨论,特别是Anders Cui 的提醒,又发现了其他的多表查询的方式.在上一篇文章中我提到了三种方式,都是各有利弊:第一种方式当数据关联很多的情况下,实体类会很复杂:第二种方式比较灵活,但是不太符合OO的思想(不过,可以适当使用):第三种方式最主要的问题就是性能不太理想,配置比较麻烦. 下面是第四种多表查询的方式,相对第二种多了一点配置,但是其他方面都很好(当然

[傅里叶变换及其应用学习笔记] 六. 热方程讨论

这份是本人的学习笔记,课程为网易公开课上的斯坦福大学公开课:傅里叶变换及其应用. 上节课讲到,在对非周期函数进行傅里叶分析时,有 $C_k = \displaystyle{\frac{1}{T}\int_{-\frac{T}{2}}^{\frac{T}{2}}f(t)e^{-2\pi i\frac{k}{T}t}dt }$ $f(t) = \displaystyle{\sum_{k=-\infty}^{\infty}C_ke^{2\pi i\frac{k}{T}t} }$ 我们希望仅让$T\to

ActiveMQ学习笔记(六)——JMS消息类型

1.前言 ActiveMQ学习笔记(四)--通过ActiveMQ收发消息http://my.oschina.net/xiaoxishan/blog/380446 和ActiveMQ学习笔记(五)--使用Spring JMS收发消息http://my.oschina.net/xiaoxishan/blog/381209   中,发送和接受的消息类型都是TextMessage,即文本消息(如下面的代码所示).显然消息类型只有文本类型是不能满足要求的. //发送文本消息  session.create