歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux虛擬文件系統--文件路徑名的解析(4)--符號鏈接

Linux虛擬文件系統--文件路徑名的解析(4)--符號鏈接

日期:2017/2/28 14:56:30   编辑:Linux教程

符號鏈接也是一種文件,只不過其內容是另一個文件的路徑名。對於符號鏈接的處理,要注意避免死循環的產生,如一個符號鏈接指向其本身。符號鏈接可能包含了符號鏈接,因此內核采用遞歸的方式來處理這個問題,為了避免符號鏈接的死循環而導致無窮遞歸,內核采用link_count和total_link_count來跟蹤符號鏈接的處理,其中前者表示連續的符號鏈接數,後者表示總共的符號鏈接數,兩者都不能超過各自的限制,否則內核會放棄解析。

相關閱讀: http://www.linuxidc.com/search.aspx?where=nkey&keyword=3305

  1. staticinlineint do_follow_link(struct path *path, struct nameidata *nd)
  2. {
  3. int err = -ELOOP;
  4. /*如果處理的鏈接數超過下面的限制則會放棄搜索(因為有可能陷入死循環)*/
  5. /*link_count表示連續的符號鏈接數,其值不能超過8,total_link_count表示總共的
  6. 鏈接數,氣值不能超過40*/
  7. if (current->link_count >= MAX_NESTED_LINKS)
  8. goto loop;
  9. if (current->total_link_count >= 40)
  10. goto loop;
  11. BUG_ON(nd->depth >= MAX_NESTED_LINKS);
  12. cond_resched();
  13. err = security_inode_follow_link(path->dentry, nd);
  14. if (err)
  15. goto loop;
  16. /*每處理一次符號鏈接,link_count,total_link_count和depth都要加1*/
  17. current->link_count++;
  18. current->total_link_count++;//
  19. nd->depth++;
  20. /*主要是調用特定於文件系統的follow_link函數進行符號鏈接的跟蹤*/
  21. err = __do_follow_link(path, nd);
  22. /*每執行完一次符號鏈接,link_count和depth都要減1*/
  23. current->link_count--;
  24. nd->depth--;
  25. return err;
  26. loop:
  27. path_put_conditional(path, nd);
  28. path_put(&nd->path);
  29. return err;
  30. }
  1. static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
  2. {
  3. int error;
  4. void *cookie;
  5. struct dentry *dentry = path->dentry;
  6. touch_atime(path->mnt, dentry);
  7. nd_set_link(nd, NULL);//在saved_names中清除當前解析的符號鏈接路徑
  8. if (path->mnt != nd->path.mnt) {
  9. path_to_nameidata(path, nd);
  10. dget(dentry);
  11. }
  12. mntget(path->mnt);
  13. /*調用特定於文件系統的follow_link方法來跟蹤符號鏈接,並將符號鏈接中保存的路徑名提取出來
  14. 存放在nd的saved_names中*/
  15. cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
  16. error = PTR_ERR(cookie);
  17. if (!IS_ERR(cookie)) {
  18. char *s = nd_get_link(nd);//提取saved_names中的路徑
  19. error = 0;
  20. if (s)//路徑存在,則繼續解析,__vfs_follow_link將會調用link_path_walk,因此對於
  21. //路徑中存在多個符號鏈接的情況,這是一個遞歸的過程
  22. error = __vfs_follow_link(nd, s);
  23. if (dentry->d_inode->i_op->put_link)
  24. dentry->d_inode->i_op->put_link(dentry, nd, cookie);
  25. }
  26. path_put(path);
  27. return error;
  28. }
  1. static __always_inline int __vfs_follow_link(struct nameidata *nd, constchar *link)
  2. {
  3. int res = 0;
  4. char *name;
  5. if (IS_ERR(link))
  6. goto fail;
  7. if (*link == '/') {
  8. set_root(nd);
  9. path_put(&nd->path);
  10. nd->path = nd->root;
  11. path_get(&nd->root);
  12. }
  13. res = link_path_walk(link, nd);
  14. if (nd->depth || res || nd->last_type!=LAST_NORM)
  15. return res;
  16. /*
  17. * If it is an iterative symlinks resolution in open_namei() we
  18. * have to copy the last component. And all that crap because of
  19. * bloody create() on broken symlinks. Furrfu...
  20. */
  21. name = __getname();
  22. if (unlikely(!name)) {
  23. path_put(&nd->path);
  24. return -ENOMEM;
  25. }
  26. strcpy(name, nd->last.name);
  27. nd->last.name = name;
  28. return 0;
  29. fail:
  30. path_put(&nd->path);
  31. return PTR_ERR(link);
  32. }
Copyright © Linux教程網 All Rights Reserved