b97902HW 板


LINE

简介 link, stat, chdir, opendir 在开始介绍档案操作的函式之前,我先简单的介绍一下档案系统(File System),与一些和档案系统有关的概念。 简介档案系统 (File System) 不知道大家有没有自己安装作业系统(例如:Windows 或者 Ubuntu 之 类的) 的经验。在很多时候,我们必须使用 fdisk/spfdisk/chfdisk 之类的软体把硬碟分割成若干个 partition(分割区)。然後,分别将 每一个分割区格式化为特定的档案系统,例如 ext4, ext3, ufs2, ntfs, vfat32 等等。例如我们可以把硬碟分割成以下的样子: sda1 sda2 sda3 <- 我的作业系统是使用 sd[a-d] ┌──┬───┬───┬───┐ 当作磁碟机代号,可能有一些 │MBR │ext4 │ext4 │fat32 │ 同学的作业系统是使用 └──┴───┴───┴───┘ hd[a-d] 作为磁碟机代号。 / \ ┌──────┬───────┬───────┬─── │Boot Sector │Block Group 1 │Block Group 2 │... └──────┴───────┴───────┴─── / \ ┌───┬───┬──────┬─────┬───┬───┐ │Super │fs │inode used │block used│inode │block │ │Block │desc │bitmask │bitmask │table │table │ └───┴───┴──────┴─────┴───┴───┘ ref. http://web.mit.edu/tytso/www/linux/ext2intro.html#section:ext2fs 上面是一个硬碟大概的样子,如果看不懂,也没有关系,我想要让大 家知道的是黄色的部分:inode table 与 block table。在 Unix-like 作业系统当中,大部分的档案系统都是由 inode 与 block 组成。 我们可以把档案系统类比成图书馆:inode table 就像是图书馆的索 引,每一个 inode 就会储存和档案有关的资料,如档案的拥有者、 有效群组、更改时间、档案大小、档案的「所在地」等等。而 block table 就像是一排一排的书柜,会有很多的书本。 另外,每一个档案都会有一个对应的 inode。 不过档案系统和图书馆还是有些微的不同: (1) inode 和一般的书目索引不同,大多数的 Unix-like 作业系统 是不会储存档案名称的。取而代之的是一个独一无二的书籍编 号:st_ino。我们如果要查寻一个档案的相关资料,实际上作业 系统是用 st_ino 来从 inode table 找出对应的 inode。 事实上如果各位真得去看 Linux 的程式码,你会发现 ext4 档案 系统的 inode struct 也是没有 st_ino 这个栏位的!(当然也没 有 filename 之类的栏位) 因为 st_ino 在 ext4 档案系统当中, 就是该笔 inode 在 inode table 当中的 index (inode table 长 得有一点像是阵列)。 ref. http://lxr.linux.no/linux+*/fs/ext4/ext4.h#L441 至於为什麽不用「档案名称」当作索引,或者是为什麽要使用 st_ino 来当索引。现在我可以给大家第一个理由:用数字从阵列找出第 n 个 元素,只需要 O(1) 的时间,而用字串搜寻,很难达到 O(1),及便做 到 O(1) 也一定比阵列计算还要慢。另外,事实上还有一些设计上的 考量,我们稍候介绍 Link (档案连结) 的时候会再提到。 还有一点要注意:先前我说到 st_ino 是一个独一无二的档案编号。 这一句话可能要进一步说明一下。这里的独一无二,是对同一个 partition 而言。理由很简单:既然 st_ino 是 inode 在 inode table 当中的 index,所以二个不同的 partition 当然有可能有相 同的 index。所以 st_ino 只有在同一个 partition 之中,是独一 无二的! (2) 在大多数的档案系统当中,大的档案不一定会连续地储存在 block table 里面。大的档案可能会被分成若干个 block 然後被储存到不同的的地 方。所以 inode 储存的「档案位置」更准确地说,是「档案碎片的位 置」。例如一个 11kb 的档案,可能 0-4kb 是在一个 block,4-8kb 是在一个 block,8-11kb 是储存在另一个 block。 而如果一个档案占用一个 block,这一个 block 就完全归他所有,其 他的档案不能和他共享同一个 block。而且根据统计,在大多数的情 况,Unix-like 作业系统会有很多的小档案。所以一般一个 block 的 大小都不大,大约是 1-4kb。 也因为多数的档案都不大,所以 inode 本身的 struct 就不会储存 很多 block number。例如:在 ext4 的 inode struct 里面,就只 有 15 个 block number slot。 ref. http://lxr.linux.no/#linux+v2.6.33/fs/ext4/ext4.h#L464 不过这 15 个 block number slot 只有前 12 个真得是用来储存 档案的 block number,我们称之为 direct block。而剩下的三个 我们分别称之为 indirect block, double indirect block, third indirect block,这三个栏位会指向一个「储存 block number 的 block」,用以处理比较大的档案。示意图如下: struct inode { ... int32_t i_block[15] = { blockno1, blockno2, blockno3, .... blockno11, blockno12, IND_BLOCK ----> 指向一个「储有 block number 的 block」 blockno_ind_1, blockno_ind_2, .... blockno_ind_1024 DIND_BLOCK ---> 指向一个「储存有「储存有 block number 的 block」的 block blockno_dind_1 =====> blockno_dind_1_ind_1 blockno_dind_1_ind_2 blockno_dind_1_ind_3 ... blockno_dind_1_ind_1024 blockno_dind_2 =====> blockno_dind_2_ind_1 blockno_dind_2_ind_2 blockno_dind_2_ind_3 ... blockno_dind_2_ind_1024 ... blockno_dind_1024 ===> blockno_dind_1024_ind_1 .... TIND_BLOCK ---> ... (以此类推) }; ... }; ref. http://lxr.linux.no/#linux+v2.6.33/fs/ext4/ext4.h#L464 http://lxr.linux.no/#linux+v2.6.33/fs/ext4/ext4.h#L464 所有东西都是档案 在 Unix 之下,所有的东西都是档案!一般的档案如:文件、网页、 可执行档都是一般档案;目录是一种档案;Symbolic Link 是档案; 装置是一种「特殊」的档案;甚至网路的 Socket 也是档案。 这种世界万物都是档案是一个很重要的概念! 而档案的种类主要有七种,我们之後谈到 stat 之後,就有办法查询 一个档案是属於哪一类,我先把六个种类列下来: Regular File:一般的档案,如:纯文字档、可执行档、图片...等等。 Directory:资料夹Link:软的档案连结,Symbolic link 又称 Soft link。 Block Special File:装置档案,如:硬碟 (dev/sd*, dev/hd*, ...) Character Special File:装置档案,如:Terminal (/dev/tty*) Socket:网路连线。 FIFO:Named Pipe (IPC) 不过本篇的重点只会放在前三者。 Hard Link 与 Symbolic Link 档案连结主要分成 Hard link 与 Symbolic Link (Soft link) 二种。Hard link 在档案系统当中,一定要存在着对应的 inode,而 且目标 inode 会被若干个 Hard Link 共用。而 Symbolic Link 有 一点像是 Windows 作业系统下的「捷径」,他本身是一个档案,其 内容是一个路径。 不过 Symbolic Link 比 Windows 捷径稍微强大一点,因为 Unix 大部分的系统呼叫(例如:open/opendir/chdir 等等) 都会自动追纵到 Symbolic Link 的目标,所以在不少情况下,存取 Symbolic Link 就 像是存取目标档案。 那 Hard Link 和 Symbolic Link 有什麽不同呢? 1. Hard Link 一定要指向一个 inode,所以 Hard Link 一定会是有 效的!而 Symbolic Link 则不一定有效,他有可能指向不存在的 档案。 2. Hard Link 因为和 inode 绑在一起,所以不能够跨越 partition, 也不能跨越 file system;不过 Symbolic 是记录路径,所以可以 夸越 partition,也可以跨越 file system。 3. Hard Link 会共用一个 inode,而 Symbolic Link 有自己的 inode, 有自己的 block (用来储存路径)。 4. 使用者自己没有办法使用 link() 系统呼叫建立指向目录的 Hard Link。而 Symbolic Link 可以指向目录。(ps. 老师的投影片上说 root 可以建位指向目录的 Hard Link,不过我测试的时候,都是 没有办法的。) 再谈 Hard Link 我想,看到这里你一定越看越觉得奇怪,什麽 st_ino,那我们常见的 档案路径存到那里去了呢?Unix 的系统呼叫清一色都是要我们传入档 案路径呀?那作业系统要怎麽把档案路径转成 st_ino 呢? 另一个问题是:我们怎麽档案系统谈到一半就跳到 Link 了呢?在回答 这一个问题之前,先让我问一个问题:目录是什麽?他是怎麽实作出来 的? 我们先前有把图书馆拿出来和档案系统类比,现在我们再把「目录」的 概念对应到「字典」。目录的功用就是把档名对应到 inode。而目录本 身是一个档案(还记得吧?),所以他自己也有自己的 inode。所以 inode 与「目录」的关系图如下: inode table ┌────┐ │... │ block number: 15678 ├────┤ ┌───┬──────────┐ 2 │15678 ●--------------------> │st_ino│filename │ ├────┤ ├───┼──────────┤ │... │ │2 │. │ │2 │.. │ │54321 │boot │ │86327 │home │ │56312 │opt │ │9875 │var │ │4587 │tmp │ │3426 │opt │ └───┴──────────┘ 而所谓的 Hard Link 就是在「目录档案」或者该称之为目录的「档 名-inode 对照表」加上一笔记录,指向同一个 inode。例如: +---------------------------------+ | inode table | | ┌────┐ | | │... │ | block number: 15678 \├────┤ | ┌────┬────────┐ 3142│15678 ●----------------------+->│ st_ino│filename │ ├────┤ ┌──────┐ | ├────┼────────┤ 3143│16543 ●---->│block 16543 │ +----●3142 │. │ // ├────┤ └──────┘ │ ?? │.. │ || │... │ +----●3143 │testfile │ || |+---●3143 │hardlink │ || || └────┴────────┘ |+----------------------------------+| +------------------------------------+ 另外,为了维持 Hard Link 的正确性,并且避免一个 inode 在还有 Hard Link 的时候就被删掉,所以 inode 会储存一个 st_nlink 值, 用来计算有多少 Hard Link 连结到这个 inode。在 ext4 档案系统 当中,inode struct 存有一个 i_links_count 就是 st_nlink。 ref. http://lxr.linux.no/#linux+v2.6.33/fs/ext4/ext4.h#L450 对了,既然提到了目录,我们就顺便说明一个目录的 st_nlink 值。 一个目录里面,至少有 " . " 与 " .. " 这二个档名。" . " 是目 录本身的 inode; " .. " 是其父目录的 inode。 另外,对於非根目录,必定存在一个父目录拥有指向自己的 hard link;而根目录的 " .. " 被定义成自己的 inode。所以每一个 资料夹的 st_nlink 值一定会大於或等於 2。以下是 ls 指令的执行 结果: $ ls -al 桌面 drwxr-xr-x 4 logan logan 4096 2010-04-11 00:06 . drwxr-xr-x 93 logan logan 4096 2010-04-11 00:05 .. drwxr-xr-x 2 logan logan 4096 2010-04-02 21:44 DE-hw2 drwxr-xr-x 2 logan logan 4096 2010-04-08 21:18 SP-hw2-testsuite -rw-r--r-- 1 logan logan 3439 2010-04-10 11:46 untitled.txt 我的「桌面」资料夹下,有二个资料夹:DE-hw2 与 SP-hw2-testsuite, 还有一个档案 untitled.txt。另外你看到了我把一个 "4" 用淡蓝色 标起来,这一个数字就是 st_nlink,这里为什麽我的「桌面」资料夹 会有 4 个 hard link 指向他呢?答案是因为他有二个子资料夹,分 别都有 " .. " 指向他,加上原有的二个就有四个 hard link 了! 而 DE-hw2 与 SP-hw2-testsuite 就只有二个 hard link。 当然,对於看得到的 Regular File 而言,st_nlink 就一定会大於 或等於 1,不然你绝对无法用 ls 之类的命令看到他。上面例子当中 的 untitled.txt 就只有一个从「桌面」指向它的 Hard Link。 我们再回头想一想:为什麽 inode 不储存档案名称?在知道 Hard link 之後,我们知道一个档案他是可以有不同的档名的!我可以 有二个 Hard link 指向同一个 inode,所以 inode 储存哪一个档 名都不对,因此 inode 不应该储存档名。 等等!鸡生蛋蛋生鸡? 有些很细心的同学可能会注意到:我们要靠 inode 才能找到 block, 并读取其档案内容,然而我们又要透过 block 来找出某个档案的 inode,这岂不是鸡生蛋蛋生鸡?谁来告诉我根目录的 inode 或者 是 block 在哪里呢? 同样的问题,我们可以以图书馆来类比。假设今天我们的书目索引 可能在任何书柜上,我该如何找到第一本书目索引呢?当然,这个 问题并不困难,因为书目索引的位置是固定的。 同样的,对於档案系统根目录的 inode 而言也是这样,例如在 ext4 档案系统之中,根目录的 st_ino 一定是 2,所以我们可 以透过这一个 inode 找到根目录的「档案内容」。 ref. http://lxr.linux.no/#linux+v2.6.33/fs/ext4/ext4.h#L147 http://uranus.chrysocome.net/explore2fs/es2fs.htm 回头介绍 Symbolic Link 我们刚才有提到 Symbolic Link 本身只是一个比较「特别」的档案, 档案的内容只有一个档案路径,用来表示目标「档案」。既然 Symbolic Link 是一个档案,所以他有自己的 inode,有自己的 block (用来 储存档案路径)。所以他的结构大概长这样: inode table ┌────┐ │... │+-------------------+ block number: 98468 ├────┤| | ┌────┬────────┐ 1142│98468 ●--+ block: 76747 +->│ st_ino│filename │ ├────┤ ┌──────┐ ├────┼────────┤ 1143│76747 ●---->│/home │ │ 1142 │. │ / ├────┤ └──────┘ │ ?? │.. │ | │... │ +-------●1143 │testfile │ | | └────┴────────┘ +----------------------------------+ 不过因为 Symbolic Link 只储存一个路径,我们当然可以创造出各式 各样可能产生问题的 Symbolic Link:例如把自己的档案路径存为目 标路径,这样就可以创造一个无限回圈。或者,做一个 Symbolic Link 到父目录也可以产生类似的效果。 为了避免让作业系统当掉,大部分的作业系统对 Symbolic Link 的 跳跃次数都会加以设限(大部分的系统不是做已走访检查,因为这 可能很浪费时间) 所以下面的 Symbolic Link 虽然正确,但是如果 你呼叫 stat("l0", &sb) 你会发现系统会回传 ELOOP。 l0 -> l1 -> l2 -> l3 -> l4 -> l5 -> l6 -> l7 -> l8 -> l9 -> some.txt ps. 跳跃次数限制的次数不一定是 8,不过我们可以透过 SYMLOOP_MAX 得知 跳路次数的限制。 未完.待续。 -- LoganChien ----- from PTT2 个板 logan ----- --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.224.97.11
1F:推 Hseuler:推推~ 04/11 14:47
2F:推 jimmy319:太用心 太专业了 推 04/14 23:59
3F:推 averangeall:有看有推 真的是太精美了 04/18 18:49
4F:→ Bingojkt:教学文全消推3@w< 04/19 18:15







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:iOS站内搜寻

TOP