Linux虚拟文件系统--文件路径名的解析(4)--符号链接
2012-11-21 21:14
281 查看
符号链接也是一种文件,只不过其内容是另一个文件的路径名。对于符号链接的处理,要注意避免死循环的产生,如一个符号链接指向其本身。符号链接可能包含了符号链接,因此内核采用递归的方式来处理这个问题,为了避免符号链接的死循环而导致无穷递归,内核采用link_count和total_link_count来跟踪符号链接的处理,其中前者表示连续的符号链接数,后者表示总共的符号链接数,两者都不能超过各自的限制,否则内核会放弃解析。
这里可以看到解析的过程又回到了link_path_walk()(见前文),因此实现了递归的过程。
static inline int do_follow_link(struct path *path, struct nameidata *nd) { int err = -ELOOP; /*如果处理的链接数超过下面的限制则会放弃搜索(因为有可能陷入死循环)*/ /*link_count表示连续的符号链接数,其值不能超过8,total_link_count表示总共的 链接数,气值不能超过40*/ if (current->link_count >= MAX_NESTED_LINKS) goto loop; if (current->total_link_count >= 40) goto loop; BUG_ON(nd->depth >= MAX_NESTED_LINKS); cond_resched(); err = security_inode_follow_link(path->dentry, nd); if (err) goto loop; /*每处理一次符号链接,link_count,total_link_count和depth都要加1*/ current->link_count++; current->total_link_count++;// nd->depth++; /*主要是调用特定于文件系统的follow_link函数进行符号链接的跟踪*/ err = __do_follow_link(path, nd); /*每执行完一次符号链接,link_count和depth都要减1*/ current->link_count--; nd->depth--; return err; loop: path_put_conditional(path, nd); path_put(&nd->path); return err; }
static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) { int error; void *cookie; struct dentry *dentry = path->dentry; touch_atime(path->mnt, dentry); nd_set_link(nd, NULL);//在saved_names中清除当前解析的符号链接路径 if (path->mnt != nd->path.mnt) { path_to_nameidata(path, nd); dget(dentry); } mntget(path->mnt); /*调用特定于文件系统的follow_link方法来跟踪符号链接,并将符号链接中保存的路径名提取出来 存放在nd的saved_names中*/ cookie = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(cookie); if (!IS_ERR(cookie)) { char *s = nd_get_link(nd);//提取saved_names中的路径 error = 0; if (s)//路径存在,则继续解析,__vfs_follow_link将会调用link_path_walk,因此对于 //路径中存在多个符号链接的情况,这是一个递归的过程 error = __vfs_follow_link(nd, s); if (dentry->d_inode->i_op->put_link) dentry->d_inode->i_op->put_link(dentry, nd, cookie); } path_put(path); return error; }
static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) { int res = 0; char *name; if (IS_ERR(link)) goto fail; if (*link == '/') { set_root(nd); path_put(&nd->path); nd->path = nd->root; path_get(&nd->root); } res = link_path_walk(link, nd); if (nd->depth || res || nd->last_type!=LAST_NORM) return res; /* * If it is an iterative symlinks resolution in open_namei() we * have to copy the last component. And all that crap because of * bloody create() on broken symlinks. Furrfu... */ name = __getname(); if (unlikely(!name)) { path_put(&nd->path); return -ENOMEM; } strcpy(name, nd->last.name); nd->last.name = name; return 0; fail: path_put(&nd->path); return PTR_ERR(link); }
这里可以看到解析的过程又回到了link_path_walk()(见前文),因此实现了递归的过程。
相关文章推荐
- [Perl][文件操作]判断文件是否为符号链接(Unicode路径)
- Linux虚拟文件系统--文件路径名的解析(1)--整体过程
- readlink 获取符号链接,获取文件绝对路径
- Linux虚拟文件系统--文件路径名的解析(3)--普通文件名
- gcc指定头文件路径及动态链接库路径
- VS链接提示无法解析的外部符号 __imp__fopen解决办法
- 黑马程序员--Java基础加强--09.【MyEclipse的class文件所在的目录配置】【相对路径解析】【个人总结】
- 非MFC工程,采用静态链接MFc时,出现无法解析的外部符号CoInitialize
- 为WinDbg设置符号文件路径
- Linux中ELF文件动态链接的加载、解析及实例分析(一): 加载
- VS2012编译文件报错——error LNK2001: 无法解析的外部符号 __imp___CrtDbgReportW
- Linux是如何解析文件路径名的????
- 关于我遇到的“LNK 2019无法解析的外部符号”的链接错误
- pwd显示链接文件的真实路径
- C++中使用pthread.h头文件报错 - 无法解析的外部符号 __imp__pthread_create,该符号在函数 _main 中被引用
- PHP之文件系统处理_解析目录路径
- 使用log4cplus时遇到的链接错误:无法解析的外部符号 "public: __thiscall log4cplus::RollingFileAppender::RollingFileAppende
- c++ 链接mysql:error LNK2019: 无法解析的外部符号
- 使用XML作为项目的配置文件使用,并解析之,获得数据作为链接数据库的参数
- CentOS中设置.so链接文件路径