免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3502 | 回复: 7
打印 上一主题 下一主题

创建新文件后, 会影响到父目录的更改时间, 这是为什么呢? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-06-28 01:18 |只看该作者 |倒序浏览
本帖最后由 slackware12 于 2010-06-28 02:01 编辑

创建新文件后, 会影响到父目录的更改时间, 这是为什么呢?

父目录的i节点的哪个地方发生改变了??


我如下进行测试, 但没发现有父目录test有何变化 :

bash$ stat test
  File: `test'
  Size: 4096              Blocks: 8          IO Block: 4096   directory
Device: fd01h/64769d        Inode: 406463      Links: 3
Access: (0755/drwxr-xr-x)  Uid: ( 1000/ok)   Gid: (  100/   users)
Access: 2010-06-28 01:10:02.229038933 +0800
Modify: 2010-06-28 01:10:04.999913694 +0800
Change: 2010-06-28 01:10:04.999913694 +0800

bash$ echo 'hello' >test/new_file

bash$ stat test
  File: `test'
  Size: 4096              Blocks: 8          IO Block: 4096   directory
Device: fd01h/64769d        Inode: 406463      Links: 3
Access: (0755/drwxr-xr-x)  Uid: ( 1000/ ok)   Gid: (  100/   users)
Access: 2010-06-28 01:10:02.229038933 +0800
Modify: 2010-06-28 01:10:23.521916892 +0800
Change: 2010-06-28 01:10:23.521916892 +0800

论坛徽章:
1
天蝎座
日期:2013-10-23 21:11:03
2 [报告]
发表于 2010-06-28 08:30 |只看该作者
LZ看看APUE
目录文件是目录项组合而成的,每个目录项对应其下的一个文件或者子目录
创建文件会在父目录中添加一个目录项
这相当于改动了父目录文件

论坛徽章:
0
3 [报告]
发表于 2010-06-28 12:14 |只看该作者
回复 2# openspace


    我看的是《APUE》第二版的书 。

那个“文件系统”小节, 并没有文字阐述“i节点和目录块的关系”, 只是有个图稍微描述了它们而已。


根据那个图, 目录块并不属于 i节点数组的一部分, 它属于块的一部分。

创建新文件(即构造新目录项), 将改变父目录的目录块的内容, 好像没有改变到父目录的i节点的状态。  

父目录的内容只是被修改而已, 为什么父目录的i节点的状态会被改变?(目录也是一种文件, 难道目录块不属于父目录的内容, 而属于i节点的一部分?)

论坛徽章:
0
4 [报告]
发表于 2010-06-28 12:19 |只看该作者
普通文件, 它是由i节点和数据块构成的。
改变它的数据块的内容, 并不会影响i节点的状态。


而目录文件,是由i节点和目录块构成的。
改变它的目录块的内容, 将会影响i节点的状态。

这是为什么? 难道如上述所言, 目录块不属于父目录的内容, 而是属于父目录的i节点的一部分?

论坛徽章:
1
天蝎座
日期:2013-10-23 21:11:03
5 [报告]
发表于 2010-06-28 13:32 |只看该作者
这个还真没有注意过
不知道POSIX对于这种行为有没有规定
比如“改变它的数据块的内容, 并不会影响i节点的状态”
如果没有,这就取决于文件系统的实现了

论坛徽章:
0
6 [报告]
发表于 2010-06-28 15:26 |只看该作者
回复 5# openspace


    (改变它的数据块的内容, 并不会影响i节点的状态)


多谢提醒, 我这里弄错了一个问题。对于普通文件来说, 改变它的数据块的内容, 确实会影响i节点的状态(因为i节点里的size值被改变)。


但是, 对于目录文件来说, 改变它的目录块的内容, size值并没有发生变化。  那么, 在目录文件的i节点里, 到底是什么地方发生改变了?

论坛徽章:
1
天蝎座
日期:2013-10-23 21:11:03
7 [报告]
发表于 2010-06-29 08:27 |只看该作者
回复 6# slackware12


    "对于目录文件来说, 改变它的目录块的内容, size值并没有发生变化"

这里目录文件的size值是发生变化的,你所说的没有发生变化应该是指从目录的父目录中看时没有发生变化
我理解的是目录下所有文件占用的空间并不计入比如ls时查看目录大小得到的值中
你在目录文件中添加一条目录项,目录文件变化,但是目录文件对应的其父目录中的目录项长度还是不变的
刚查看了一下ext2中添加目录项的代码
  1. 474/*
  2. 475 *      Parent is locked.
  3. 476 */
  4. 477int ext2_add_link (struct dentry *dentry, struct inode *inode)
  5. 478{
  6. 479        struct inode *dir = dentry->d_parent->d_inode;
  7. 480        const char *name = dentry->d_name.name;
  8. 481        int namelen = dentry->d_name.len;
  9. 482        unsigned chunk_size = ext2_chunk_size(dir);
  10. 483        unsigned reclen = EXT2_DIR_REC_LEN(namelen);
  11. 484        unsigned short rec_len, name_len;
  12. 485        struct page *page = NULL;
  13. 486        ext2_dirent * de;
  14. 487        unsigned long npages = dir_pages(dir);
  15. 488        unsigned long n;
  16. 489        char *kaddr;
  17. 490        loff_t pos;
  18. 491        int err;
  19. 492
  20. 493        /*
  21. 494         * We take care of directory expansion in the same loop.
  22. 495         * This code plays outside i_size, so it locks the page
  23. 496         * to protect that region.
  24. 497         */
  25. 498        for (n = 0; n <= npages; n++) {
  26. 499                char *dir_end;
  27. 500
  28. 501                page = ext2_get_page(dir, n, 0);
  29. 502                err = PTR_ERR(page);
  30. 503                if (IS_ERR(page))
  31. 504                        goto out;
  32. 505                lock_page(page);
  33. 506                kaddr = page_address(page);
  34. 507                dir_end = kaddr + ext2_last_byte(dir, n);
  35. 508                de = (ext2_dirent *)kaddr;
  36. 509                kaddr += PAGE_CACHE_SIZE - reclen;
  37. 510                while ((char *)de <= kaddr) {
  38. 511                        if ((char *)de == dir_end) {
  39. 512                                /* We hit i_size */
  40. 513                                name_len = 0;
  41. 514                                rec_len = chunk_size;
  42. 515                                de->rec_len = ext2_rec_len_to_disk(chunk_size);
  43. 516                                de->inode = 0;
  44. 517                                goto got_it;
  45. 518                        }
  46. 519                        if (de->rec_len == 0) {
  47. 520                                ext2_error(dir->i_sb, __func__,
  48. 521                                        "zero-length directory entry");
  49. 522                                err = -EIO;
  50. 523                                goto out_unlock;
  51. 524                        }
  52. 525                        err = -EEXIST;
  53. 526                        if (ext2_match (namelen, name, de))
  54. 527                                goto out_unlock;
  55. 528                        name_len = EXT2_DIR_REC_LEN(de->name_len);
  56. 529                        rec_len = ext2_rec_len_from_disk(de->rec_len);
  57. 530                        if (!de->inode && rec_len >= reclen)
  58. 531                                goto got_it;
  59. 532                        if (rec_len >= name_len + reclen)
  60. 533                                goto got_it;
  61. 534                        de = (ext2_dirent *) ((char *) de + rec_len);
  62. 535                }
  63. 536                unlock_page(page);
  64. 537                ext2_put_page(page);
  65. 538        }
  66. 539        BUG();
  67. 540        return -EINVAL;
  68. 541
  69. 542got_it:
  70. 543        pos = page_offset(page) +
  71. 544                (char*)de - (char*)page_address(page);
  72. 545        err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0,
  73. 546                                                        &page, NULL);
  74. 547        if (err)
  75. 548                goto out_unlock;
  76. 549        if (de->inode) {
  77. 550                ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
  78. 551                de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len);
  79. 552                de->rec_len = ext2_rec_len_to_disk(name_len);
  80. 553                de = de1;
  81. 554        }
  82. 555        de->name_len = namelen;
  83. 556        memcpy(de->name, name, namelen);
  84. 557        de->inode = cpu_to_le32(inode->i_ino);
  85. 558        ext2_set_de_type (de, inode);
  86. 559        err = ext2_commit_chunk(page, pos, rec_len);
  87. 560        dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
  88. 561        EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
  89. 562        mark_inode_dirty(dir);
  90. 563        /* OFFSET_CACHE */
  91. 564out_put:
  92. 565        ext2_put_page(page);
  93. 566out:
  94. 567        return err;
  95. 568out_unlock:
  96. 569        unlock_page(page);
  97. 570        goto out_put;
  98. 571}
复制代码
注意  560        dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
这里mtime/ctime都发生了变化

论坛徽章:
0
8 [报告]
发表于 2010-06-29 17:26 |只看该作者
回复 7# openspace


    太非常感谢。



   PS: 怪不得linus会说, "read the fucking source code", 这代码, 胜过千言万语。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP