-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path0230filesystem.html
2666 lines (2664 loc) · 237 KB
/
0230filesystem.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Author" content="VBird, 鸟哥">
<meta name="Description" content="Linux 的磁盘挂载等特色,以及文件系统 (filesystem) 的介绍">
<title>鸟哥的 Linux 私房菜 -- 第七章、Linux 磁盘与文件系统管理</title>
<style type="text/css">
</style>
<link href="./vbird_files/style_2013.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="tablearea">
<div class="mainarea">
<div class="block1">
<!-- 本文的档头部分 -->
<h1>第七章、Linux 磁盘与文件系统管理</h1>
<div style="text-align:right">
<span class="text_history">最近更新日期:2015/10/26</span>
</div>
<!-- 本文的档头部分 -->
<div class="abstract">
<p>系统管理员很重要的任务之一就是管理好自己的磁盘文件系统,每个分区不可太大也不能太小,
太大会造成磁盘容量的浪费,太小则会产生文件无法保存的困扰。此外,我们在前面几章谈到的文件权限与属性中,
这些权限与属性分别记录在文件系统的哪个区块内?这就得要谈到 filesystem 中的 inode 与 block 了。同时,为了虚拟化与大容量磁盘,
现在的 CentOS 7 缺省使用大容量性能较佳的 xfs 当缺省文件系统了!这也得了解一下。
在本章我们的重点在于如何制作文件系统,包括分割、格式化与挂载等,是很重要的一个章节喔!</p>
</div>
<!-- 本文的链接区部分 -->
<div class="links">
<ul>
<li><a href="0230filesystem.html#harddisk">7.1 认识 Linux 文件系统</a>
<ul>
<li><a href="0230filesystem.html#harddisk-physical">7.1.1 磁盘组成与分割的复习</a></li>
<li><a href="0230filesystem.html#harddisk-filesystem">7.1.2 文件系统特性</a>: <a href="0230filesystem.html#indexed_allocation">索引式文件系统</a></li>
<li><a href="0230filesystem.html#harddisk-inode">7.1.3 Linux 的 EXT2 文件系统(inode)</a>:
<a href="0230filesystem.html#block">data block</a>, <a href="0230filesystem.html#inode">inode table</a>, <a href="0230filesystem.html#super_block">superblock</a>,
<a href="0230filesystem.html#dumpe2fs">dumpe2fs</a></li>
<li><a href="0230filesystem.html#harddisk-dir">7.1.4 与目录树的关系</a></li>
<li><a href="0230filesystem.html#harddisk-journal">7.1.5 EXT2/EXT3 文件的访问与日志式文件系统的功能</a></li>
<li><a href="0230filesystem.html#harddisk-filerun">7.1.6 Linux 文件系统的运作</a></li>
<li><a href="0230filesystem.html#harddisk-mount">7.1.7 挂载点的意义 (mount point)</a></li>
<li><a href="0230filesystem.html#harddisk-other">7.1.8 其他 Linux 支持的文件系统与 VFS</a></li>
<li><a href="0230filesystem.html#harddisk-xfs">7.1.9 XFS 文件系统简介</a>: <a href="0230filesystem.html#xfs_info">xfs_info</a></li>
</ul></li>
<li><a href="0230filesystem.html#filesys">7.2 文件系统的简单操作</a>
<ul>
<li><a href="0230filesystem.html#filesys_1">7.2.1 磁盘与目录的容量:</a> <a href="0230filesystem.html#df">df</a>, <a href="0230filesystem.html#du">du</a></li>
<li><a href="0230filesystem.html#link">7.2.2 实体链接与符号链接:</a> <a href="0230filesystem.html#ln">ln</a></li>
</ul></li>
<li><a href="0230filesystem.html#disk">7.3 磁盘的分割、格式化、检验与挂载</a>
<ul>
<li><a href="0230filesystem.html#part_type">7.3.1 观察磁盘分割状态:</a>, <a href="0230filesystem.html#lsblk">lsblk</a>, <a href="0230filesystem.html#blkid">blkid</a>, <a href="0230filesystem.html#parted1">parted</a></li>
<li><a href="0230filesystem.html#f.disk">7.3.2 磁盘分割 gdisk/fdisk:</a> <a href="0230filesystem.html#gdisk">gdisk</a>, <a href="0230filesystem.html#partprobe">partprobe</a>, <a href="0230filesystem.html#fdisk">fdisk</a></li>
<li><a href="0230filesystem.html#format">7.3.3 磁盘格式化(建置文件系统):</a> <a href="0230filesystem.html#mkfs.xfs">mkfs.xfs</a>, <a href="0230filesystem.html#mkfs.xfs.raid">mkfs.xfs for raid</a>,
<a href="0230filesystem.html#mkfs.ext4">mkfs.ext4</a>, <a href="0230filesystem.html#mkfs">mkfs</a></li>
<li><a href="0230filesystem.html#fsck">7.3.4 文件系统检验:</a> <a href="0230filesystem.html#xfs_repair">xfs_repair</a>, <a href="0230filesystem.html#fsck.ext4">fsck.ext4</a></li>
<li><a href="0230filesystem.html#mount">7.3.5 文件系统挂载与卸载: mount</a>, <a href="0230filesystem.html#umount">umount</a></li>
<li><a href="0230filesystem.html#diskpara">7.3.6 磁盘/文件系统参数修订</a>: <a href="0230filesystem.html#mknod">mknod</a>,
<a href="0230filesystem.html#xfs_admin">xfs_admin</a>, <a href="0230filesystem.html#uuidgen">uuidgen</a>, <a href="0230filesystem.html#tune2fs">tune2fs</a></li>
</ul></li>
<li><a href="0230filesystem.html#bootup">7.4 设置开机挂载</a>
<ul>
<li><a href="0230filesystem.html#fstab">7.4.1 开机挂载 /etc/fstab 及 /etc/mtab</a></li>
<li><a href="0230filesystem.html#loop">7.4.2 特殊设备 loop 挂载(镜像档不刻录就挂载使用)</a>: <a href="0230filesystem.html#loop_dvd">挂载DVD</a>,
<a href="0230filesystem.html#loop_file">大型文件</a>, <a href="0230filesystem.html#dd">dd</a></li>
</ul></li>
<li><a href="0230filesystem.html#swap">7.5 内存置换空间(swap)之建置</a>
<ul>
<li><a href="0230filesystem.html#swapdevice">7.5.1 使用实体分区建置swap:</a> <a href="0230filesystem.html#mkswap">mkswap</a>, <a href="0230filesystem.html#free">free</a>,
<a href="0230filesystem.html#swapon">swapon</a>, <a href="0230filesystem.html#swapoff">swapoff</a></li>
<li><a href="0230filesystem.html#swapfile">7.5.2 使用文件建置swap</a></li>
</ul></li>
<li><a href="0230filesystem.html#special">7.6 文件系统的特殊观察与操作</a>
<ul>
<li><a href="0230filesystem.html#special_waste">7.6.1 磁盘空间之浪费问题</a></li>
<li><a href="0230filesystem.html#parted">7.6.2 利用 GNU 的 parted 进行分割行为 (Optional)</a></li>
</ul></li>
<li><a href="0230filesystem.html#hint">7.7 重点回顾</a></li>
<li><a href="0230filesystem.html#ex">7.8 本章习题 - 第一题一定要做</a></li>
<li><a href="0230filesystem.html#reference">7.9 参考数据与延伸阅读</a></li>
</ul>
</div>
</div>
<!-- 本文的正式部分 -->
<a id="harddisk"></a>
<div class="block1">
<h2>7.1 认识 Linux 文件系统</h2>
<p>Linux 最传统的磁盘文件系统 (filesystem) 使用的是 EXT2 这个啦!所以要了解 Linux 的文件系统就得要由认识 EXT2 开始!
而文件系统是创建在磁盘上面的,因此我们得了解磁盘的物理组成才行。磁盘物理组成的部分我们在<a href="0105computers.html#pc_hd">第零章</a>谈过了,至于磁盘分割则在<a href="0130designlinux.html#partition">第二章</a>谈过了,所以底下只会很快的复习这两部份。
重点在于 inode, block 还有 superblock 等文件系统的基本部分喔!</p>
<a id="harddisk-physical"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.1 磁盘组成与分割的复习</h2>
<p>由于各项磁盘的物理组成我们在<a href="0105computers.html#pc_hd">第零章</a>里面就介绍过,
同时<a href="0130designlinux.html#partition">第二章</a>也谈过分割的概念了,所以这个小节我们就拿之前的重点出来介绍就好了!
详细的信息请您回去那两章自行复习喔!^_^。好了,首先说明一下磁盘的物理组成,整颗磁盘的组成主要有:</p>
<ul class="text_import2">
<li>圆形的磁盘盘(主要记录数据的部分);</li>
<li>机械手臂,与在机械手臂上的磁盘读取头(可读写磁盘盘上的数据);</li>
<li>主轴马达,可以转动磁盘盘,让机械手臂的读取头在磁盘盘上读写数据。</li></ul>
<p>从上面我们知道数据保存与读取的重点在于磁盘盘,而磁盘盘上的物理组成则为(假设此磁盘为单盘片,
磁盘盘图标请参考<a href="0130designlinux.html#fig2.2.1">第二章图2.2.1的示意</a>):</p>
<ul class="text_import2">
<li>磁区(Sector)为最小的物理保存单位,且依据磁盘设计的不同,目前主要有 512bytes 与 4K 两种格式;</li>
<li>将磁区组成一个圆,那就是磁柱(Cylinder);</li>
<li>早期的分割主要以磁柱为最小分割单位,现在的分割通常使用磁区为最小分割单位(每个磁区都有其号码喔,就好像座位一样);</li>
<li>磁盘分割表主要有两种格式,一种是限制较多的 MBR 分割表,一种是较新且限制较少的 GPT 分割表。</li>
<li>MBR 分割表中,第一个磁区最重要,里面有:(1)主要开机区(Master boot record, MBR)及分割表(partition table),
其中 MBR 占有 446 bytes,而 partition table 则占有 64 bytes。</li>
<li>GPT 分割表除了分割数量扩充较多之外,支持的磁盘容量也可以超过 2TB。</li></ul>
<p>至于磁盘的文件名部份,基本上,所有实体磁盘的文件名都已经被仿真成 /dev/sd[a-p] 的格式,第一颗磁盘文件名为 /dev/sda。
而分区的文件名若以第一颗磁盘为例,则为 /dev/sda[1-128] 。除了实体磁盘之外,虚拟机的磁盘通常为 /dev/vd[a-p] 的格式。
若有使用到软件磁盘数组的话,那还有 /dev/md[0-128] 的磁盘文件名。使用的是 LVM 时,文件名则为 /dev/VGNAME/LVNAME 等格式。
关于软件磁盘数组与 LVM 我们会在后面继续介绍,这里主要介绍的以实体磁盘及虚拟磁盘为主喔!</p>
<ul class="text_import2">
<li>/dev/sd[a-p][1-128]:为实体磁盘的磁盘文件名;</li>
<li>/dev/vd[a-d][1-128]:为虚拟磁盘的磁盘文件名</li></ul>
<p>复习完物理组成后,来复习一下磁盘分割吧!如前所述,以前磁盘分割最小单位经常是磁柱,但 CentOS 7 的分割软件,
已经将最小单位改成磁区了,所以容量大小的分割可以切的更细~此外,由于新的大容量磁盘大多得要使用 GPT 分割表才能够使用全部的容量,
因此过去那个 MBR 的传统磁盘分割表限制就不会存在了。不过,由于还是有小磁盘啊!因此,
你在处理分割的时候,还是得要先查找一下,你的分割是 MBR 的分割?还是 GPT 的分割?在<a href="0157installcentos7.html">第三章的 CentOS 7 安装</a>中,
鸟哥建议过强制使用 GPT 分割喔!所以本章后续的动作,大多还是以 GPT 为主来介绍喔!旧的 MBR 相关限制回去看看第二章吧!</p>
<br></div><br>
<a id="harddisk-filesystem"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.2 文件系统特性</h2>
<p>我们都知道磁盘分割完毕后还需要进行格式化(format),之后操作系统才能够使用这个文件系统。
为什么需要进行『格式化』呢?这是因为每种操作系统所设置的文件属性/权限并不相同,
为了存放这些文件所需的数据,因此就需要将分区进行格式化,以成为操作系统能够利用的『文件系统格式(filesystem)』。</p>
<p>由此我们也能够知道,每种操作系统能够使用的文件系统并不相同。
举例来说,windows 98 以前的微软操作系统主要利用的文件系统是 FAT (或 FAT16),windows 2000 以后的版本有所谓的 NTFS
文件系统,至于 <span class="text_import2">Linux 的正统文件系统则为 Ext2 (Linux second extended file
system, ext2fs</span>)这一个。此外,在缺省的情况下,windows 操作系统是不会认识 Linux 的 Ext2 的。</p>
<p>传统的磁盘与文件系统之应用中,一个分区就是只能够被格式化成为一个文件系统,所以我们可以说一个 filesystem
就是一个 partition。但是由于新技术的利用,例如我们常听到的LVM与软件磁盘数组(software raid),
这些技术可以将一个分区格式化为多个文件系统(例如LVM),也能够将多个分区合成一个文件系统(LVM, RAID)!
所以说,目前我们在格式化时已经不再说成针对 partition 来格式化了,
通常我们可以称呼<span class="text_import2">一个可被挂载的数据为一个文件系统而不是一个分区</span>喔!</p>
<p>那么文件系统是如何运作的呢?这与操作系统的文件数据有关。较新的操作系统的文件数据除了文件实际内容外,
通常含有非常多的属性,例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。
<span class="text_import2">文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到
inode 中,至于实际数据则放置到 data block 区块中</span>。
另外,还有一个超级区块 (superblock) 会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。</p>
<p>每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:</p>
<ul class="text_import2">
<li>superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量,
以及文件系统的格式与相关信息等;</li>
<li>inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;</li>
<li>block:实际记录文件的内容,若文件太大时,会占用多个 block 。</li>
</ul>
<p>由于每个 inode 与 block 都有编号,而每个文件都会占用一个 inode ,inode 内则有文件数据放置的 block 号码。
因此,我们可以知道的是,如果能够找到文件的 inode 的话,那么自然就会知道这个文件所放置数据的 block 号码,
当然也就能够读出该文件的实际数据了。这是个比较有效率的作法,因为如此一来我们的磁盘就能够在短时间内读取出全部的数据,
读写的性能比较好啰。</p>
<a id="indexed_allocation"></a>
<p>我们将 inode 与 block 区块用图解来说明一下,如下图所示,文件系统先格式化出 inode 与 block
的区块,假设某一个文件的属性与权限数据是放置到 inode 4 号(下图较小方格内),而这个 inode 记录了文件数据的实际放置点为
2, 7, 13, 15 这四个 block 号码,此时我们的操作系统就能够据此来排列磁盘的读取顺序,可以一口气将四个 block 内容读出来!
那么数据的读取就如同下图中的箭头所指定的模样了。</p>
<a id="fig7.1.1"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/filesystem-1.jpg" alt="inode/block 数据访问示意图" title="inode/block 数据访问示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.1.1、inode/block 数据访问示意图</div>
<p>这种数据访问的方法我们称为<span class="text_import2">索引式文件系统(indexed
allocation)</span>。那有没有其他的惯用文件系统可以比较一下啊?
有的,那就是我们惯用的随身碟(闪存),随身碟使用的文件系统一般为 FAT 格式。FAT 这种格式的文件系统并没有 inode
存在,所以 FAT 没有办法将这个文件的所有 block 在一开始就读取出来。每个 block 号码都记录在前一个 block 当中,
他的读取方式有点像底下这样:</p>
<a id="fig7.1.2"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/filesystem-2.jpg" alt="FAT文件系统数据访问示意图" title="FAT文件系统数据访问示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.1.2、FAT文件系统数据访问示意图</div>
<p>上图中我们假设文件的数据依序写入1->7->4->15号这四个 block 号码中,
但这个文件系统没有办法一口气就知道四个 block 的号码,他得要一个一个的将 block 读出后,才会知道下一个 block 在何处。
如果同一个文件数据写入的 block 分散的太过厉害时,则我们的磁盘读取头将无法在磁盘转一圈就读到所有的数据,
因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!</p>
<a id="disk_replace"></a>
<p>常常会听到所谓的『磁盘重组』吧?<span class="text_import2">
需要磁盘重组的原因就是文件写入的 block 太过于离散了,此时文件读取的性能将会变的很差所致。</span>
这个时候<span class="text_import2">可以透过磁盘重组将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易啊!
</span>想当然尔,FAT 的文件系统需要三不五时的磁盘重组一下,那么 Ext2 是否需要磁盘重整呢?</p>
<p>由于 Ext2 是索引式文件系统,基本上不太需要常常进行磁盘重组的。但是如果文件系统使用太久,
常常删除/编辑/添加文件时,那么还是可能会造成文件数据太过于离散的问题,此时或许会需要进行重整一下的。
不过,老实说,鸟哥倒是没有在 Linux 操作系统上面进行过 Ext2/Ext3 文件系统的磁盘重组说!似乎不太需要啦!^_^</p>
<br></div><br>
<a id="harddisk-inode"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.3 Linux 的 EXT2 文件系统(inode)</h2>
<p>在<a href="0210filepermission.html">第五章</a>当中我们介绍过 Linux
的文件除了原有的数据内容外,还含有非常多的权限与属性,这些权限与属性是为了保护每个用户所拥有数据的隐密性。
而前一小节我们知道 filesystem 里面可能含有的 inode/block/superblock
等。为什么要谈这个呢?因为标准的 Linux 文件系统 Ext2 就是使用这种 inode 为基础的文件系统啦!</p>
<a id="ext2_filesystem"></a>
<p>而如同前一小节所说的,inode 的内容在记录文件的权限与相关属性,至于 block 区块则是在记录文件的实际内容。
而且<span class="text_import2">文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs
等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动</span>。但是如果仔细考虑一下,如果我的文件系统高达数百GB时,
那么将所有的 inode 与 block 通通放置在一起将是很不智的决定,因为 inode 与 block 的数量太庞大,不容易管理。</p>
<p>为此之故,因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的
inode/block/superblock 系统。感觉上就好像我们在当兵时,一个营里面有分成数个连,每个连有自己的联系系统,
但最终都向营部回报连上最正确的信息一般!这样分成一群群的比较好管理啦!整个来说,Ext2 格式化后有点像底下这样:</p>
<a id="fig7.1.3"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/ext2_filesystem.jpg" alt="ext2文件系统示意图" title="ext2文件系统示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.1.3、ext2文件系统示意图 (<a href="0230filesystem.html#ps1">注1</a>)</div>
<p>在整体的规划当中,<span class="text_import2">文件系统最前面有一个开机磁区(boot
sector),这个开机磁区可以安装开机管理程序</span>,
这是个非常重要的设计,因为如此一来我们就能够将不同的开机管理程序安装到个别的文件系统最前端,而不用覆盖整颗磁盘唯一的 MBR,
这样也才能够制作出多重开机的环境啊!至于每一个区块群组(block group)的六个主要内容说明如后:<br><br></p>
<a id="block"></a>
<ul class="toplist"><li>data block (数据区块)</li></ul>
<p>data block 是用来放置文件内容数据地方,<span class="text_import2">在 Ext2 文件系统中所支持的 block 大小有
1K, 2K 及 4K 三种而已</span>。在格式化时 block 的大小就固定了,且每个 block 都有编号,以方便 inode 的记录啦。
不过要注意的是,由于 block 大小的差异,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量并不相同。
因为 block 大小而产生的 Ext2 文件系统限制如下:(<a href="0230filesystem.html#ps2">注2</a>)</p>
<a id="filesystem_limit"></a>
<table class="news">
<tbody><tr style="background-color:lightblue; text-align:center"><td>Block 大小</td><td>1KB</td><td>2KB</td><td>4KB</td></tr>
<tr style="text-align: center"><td style="background-color:lightblue">最大单一文件限制</td><td>16GB</td><td>256GB</td><td>2TB</td></tr>
<tr style="text-align: center"><td style="background-color:lightblue">最大文件系统总容量</td><td>2TB</td><td>8TB</td><td>16TB</td></tr>
</tbody></table>
<p>你需要注意的是,虽然 Ext2 已经能够支持大于 2GB 以上的单一文件容量,不过某些应用程序依然使用旧的限制,
也就是说,某些程序只能够捉到小于 2GB 以下的文件而已,这就跟文件系统无关了!
举例来说,鸟哥在环工方面的应用中有一套秀图软件称为PAVE(<a href="0230filesystem.html#ps3">注3</a>),
这套软件就无法捉到鸟哥在数值模式仿真后产生的大于 2GB 以上的文件!所以后来只能找更新的软件来取代它了!</p>
<p>除此之外 Ext2 文件系统的 block 还有什么限制呢?有的!基本限制如下:</p>
<ul class="text_import2">
<li>原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);</li>
<li>每个 block 内最多只能够放置一个文件的数据;</li>
<li>承上,如果文件大于 block 的大小,则一个文件会占用多个 block 数量;</li>
<li>承上,若文件小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)。</li>
</ul>
<p>如上第四点所说,由于每个 block 仅能容纳一个文件的数据而已,因此如果你的文件都非常小,但是你的 block
在格式化时却选用最大的 4K 时,可能会产生一些容量的浪费喔!我们以底下的一个简单例题来算一下空间的浪费吧!</p>
<table class="exam"><tbody><tr><td>
例题:<div>
假设你的Ext2文件系统使用 4K block ,而该文件系统中有 10000 个小文件,每个文件大小均为 50bytes,
请问此时你的磁盘浪费多少容量?
</div>
答:<div>
由于 Ext2 文件系统中一个 block 仅能容纳一个文件,因此每个 block 会浪费『 4096 - 50 = 4046 (byte)』,
系统中总共有一万个小文件,所有文件容量为:50 (bytes) x 10000 = 488.3Kbytes,但此时浪费的容量为:『 4046 (bytes) x 10000
= 38.6MBytes 』。想一想,不到 1MB 的总文件容量却浪费将近 40MB 的容量,且文件越多将造成越多的磁盘容量浪费。
</div>
</td></tr></tbody></table>
<p>什么情况会产生上述的状况呢?例如 BBS 网站的数据啦!如果 BBS 上面的数据使用的是纯文本文件来记载每篇留言,
而留言内容如果都写上『如题』时,想一想,是否就会产生很多小文件了呢?</p>
<p>好,既然大的 block 可能会产生较严重的磁盘容量浪费,那么我们是否就将 block 大小订为 1K 即可?
这也不妥,因为如果 block 较小的话,那么大型文件将会占用数量更多的 block ,而 inode
也要记录更多的 block 号码,此时将可能导致文件系统不良的读写性能。</p>
<p>所以我们可以说,在您进行文件系统的格式化之前,请先想好该文件系统预计使用的情况。
以鸟哥来说,我的数值模式仿真平台随便一个文件都好几百 MB,那么 block 容量当然选择较大的!至少文件系统就不必记录太多的
block 号码,读写起来也比较方便啊!</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 事实上,现在的磁盘容量都太大了!所以,大概大家都只会选择 4K 的 block 大小吧!呵呵!
</fieldset><br>
<a id="inode"></a>
<ul class="toplist"><li>inode table (inode 表格)</li></ul>
<p>再来讨论一下 inode 这个玩意儿吧!如前所述 inode 的内容在记录文件的属性以及该文件实际数据是放置在哪几号 block 内!
基本上,inode 记录的文件数据至少有底下这些:(<a href="0230filesystem.html#ps4">注4</a>)</p>
<ul class="text_import2">
<li>该文件的访问模式(read/write/excute);</li>
<li>该文件的拥有者与群组(owner/group);</li>
<li>该文件的容量;</li>
<li>该文件创建或状态改变的时间(ctime);</li>
<li>最近一次的读取时间(atime);</li>
<li>最近修改的时间(mtime);</li>
<li>定义文件特性的旗标(flag),如 SetUID...;</li>
<li>该文件真正内容的指向 (pointer);</li></ul>
<p>inode 的数量与大小也是在格式化时就已经固定了,除此之外 inode 还有些什么特色呢?</p>
<ul class="text_import2">
<li>每个 inode 大小均固定为 128 bytes (新的 ext4 与 xfs 可设置到 256 bytes);</li>
<li>每个文件都仅会占用一个 inode 而已;</li>
<li>承上,因此文件系统能够创建的文件数量与 inode 的数量有关;</li>
<li>系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与用户是否符合,若符合才能够开始实际读取
block 的内容。</li>
</ul>
<p>我们约略来分析一下 EXT2 的 inode / block 与文件大小的关系好了。inode 要记录的数据非常多,但偏偏又只有 128bytes 而已,
而 inode 记录一个 block 号码要花掉 4byte ,假设我一个文件有 400MB 且每个 block 为 4K 时,
那么至少也要十万笔 block 号码的记录呢!inode 哪有这么多可记录的信息?为此我们的系统很聪明的将 inode 记录 block
号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区。这是啥?我们将 inode 的结构画一下好了。</p>
<a id="fig7.1.4"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/inode.jpg" alt="inode 结构示意图" title="inode 结构示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.1.4、inode 结构示意图</div>
<p>上图最左边为 inode 本身 (128 bytes),里面有 12 个直接指向 block 号码的对照,这 12 笔记录就能够直接取得 block 号码啦!
至于所谓的间接就是<span class="text_import2">再拿一个 block 来当作记录 block 号码的记录区,如果文件太大时,
就会使用间接的 block 来记录号码。</span>如上图 7.1.4 当中间接只是拿一个 block 来记录额外的号码而已。
同理,如果文件持续长大,那么就会利用所谓的双间接,第一个 block 仅再指出下一个记录号码的 block 在哪里,
实际记录的在第二个 block 当中。依此类推,三间接就是利用第三层 block 来记录号码啦!</p>
<p>这样子 inode 能够指定多少个 block 呢?我们以较小的 1K block 来说明好了,可以指定的情况如下:</p>
<ul>
<li>12 个直接指向: 12*1K=12K<br>
由于是直接指向,所以总共可记录 12 笔记录,因此总额大小为如上所示;<br><br></li>
<li>间接: 256*1K=256K<br>
每笔 block 号码的记录会花去 4bytes,因此 1K 的大小能够记录 256 笔记录,因此一个间接可以记录的文件大小如上;
<br><br></li>
<li>双间接: 256*256*1K=256<sup>2</sup>K<br>
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个号码,因此总额大小如上;<br><br></li>
<li>三间接: 256*256*256*1K=256<sup>3</sup>K<br>
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个第三层,每个第三层可以指定 256
个号码,因此总额大小如上;<br><br></li>
<li><span class="text_import2">总额:将直接、间接、双间接、三间接加总,得到 12 + 256 + 256*256 +
256*256*256 (K) = 16GB</span></li>
</ul>
<p>此时我们知道当文件系统将 block 格式化为 1K 大小时,能够容纳的最大文件为 16GB,比较一下<a href="0230filesystem.html#filesystem_limit">文件系统限制表</a>的结果可发现是一致的!但这个方法不能用在 2K 及 4K block 大小的计算中,
因为大于 2K 的 block 将会受到 Ext2 文件系统本身的限制,所以计算的结果会不太符合之故。</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 如果你的 Linux 依旧使用 Ext2/Ext3/Ext4 文件系统的话,例如鸟哥之前的 CentOS 6.x 系统,那么缺省还是使用 Ext4 的文件系统喔!
Ext4 文件系统的 inode 容量已经可以扩大到 256bytes 了,更大的 inode 容量,可以纪录更多的文件系统信息,包括新的 ACL 以及 SELinux 类型等,
当然,可以纪录的单一文件容量达 16TB 且单一文件系统总容量可达 1EB 哩!
</fieldset><br>
<a id="super_block"></a>
<ul class="toplist"><li>Superblock (超级区块)</li></ul>
<p>Superblock 是记录整个 filesystem 相关信息的地方, 没有 Superblock ,就没有这个 filesystem 了。他记录的信息主要有:</p>
<ul class="text_import2">
<li>block 与 inode 的总量;</li>
<li>未使用与已使用的 inode / block 数量;</li>
<li>block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128bytes 或 256bytes);</li>
<li>filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;</li>
<li>一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。</li>
</ul>
<p>Superblock 是非常重要的,因为我们这个文件系统的基本信息都写在这里,因此,如果 superblock 死掉了,
你的文件系统可能就需要花费很多时间去挽救啦!一般来说, superblock 的大小为 1024bytes。相关的 superblock
消息我们等一下会以 <a href="0230filesystem.html#dumpe2fs">dumpe2fs</a> 指令来调用出来观察喔!</p>
<a id="20090401"></a>
<p>此外,每个 block group 都可能含有 superblock 喔!但是我们也说一个文件系统应该仅有一个 superblock 而已,那是怎么回事啊?
事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock ,
而若含有 superblock 则该 superblock 主要是做为第一个 block group 内 superblock 的备份咯,这样可以进行 superblock
的救援呢!</p>
<ul class="toplist"><li>Filesystem Description (文件系统描述说明)</li></ul>
<p>这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段 (superblock, bitmap, inodemap,
data block) 分别介于哪一个 block 号码之间。这部份也能够用 <a href="0230filesystem.html#dumpe2fs">dumpe2fs</a> 来观察的。</p>
<ul class="toplist"><li>block bitmap (区块对照表)</li></ul>
<p>如果你想要添加文件时总会用到 block 吧!那你要使用哪个 block 来记录呢?当然是选择『空的 block 』来记录新文件的数据啰。
那你怎么知道哪个 block 是空的?这就得要透过 block bitmap 的辅助了。从 block bitmap 当中可以知道哪些 block
是空的,因此我们的系统就能够很快速的找到可使用的空间来处置文件啰。</p>
<p>同样的,如果你删除某些文件时,那么那些文件原本占用的 block 号码就得要释放出来,
此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为『未使用中』啰!这就是 bitmap 的功能。</p>
<ul class="toplist"><li>inode bitmap (inode 对照表)</li></ul>
<p>这个其实与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block 号码,
至于 inode bitmap 则是记录使用与未使用的 inode 号码啰!</p>
<a id="dumpe2fs"></a>
<ul class="toplist"><li>dumpe2fs: 查找 Ext 家族 superblock 信息的指令</li></ul>
<p>了解了文件系统的概念之后,再来当然是观察这个文件系统啰!刚刚谈到的各部分数据都与 block 号码有关!
每个区段与 superblock 的信息都可以使用 dumpe2fs 这个指令来查找的!不过很可惜的是,我们的 CentOS 7 现在是以 xfs 为缺省文件系统,
所以目前你的系统应该无法使用 dumpe2fs 去查找任何文件系统的。没关系,鸟哥先找自己的一部机器来跟大家介绍,
你可以在后续的格式化内容讲完之后,自己切出一个 ext4 的文件系统去查找看看即可。鸟哥这块文件系统是 1GB 的容量,使用缺省方式来进行格式化的,
观察的内容如下:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">dumpe2fs [-bh] 设备文件名</span>
<span class="term_say">选项与参数:
-b :列出保留为坏轨的部分(一般用不到吧!?)
-h :仅列出 superblock 的数据,不会列出其他的区段内容!</span>
<span class="term_hd">范例:鸟哥的一块 1GB ext4 文件系统内容</span>
[root@study ~]# <span class="term_command">blkid</span> <span class="term_note"><==这个指令可以叫出目前系统有被格式化的设备</span>
/dev/vda1: LABEL="myboot" UUID="ce4dbf1b-2b3d-4973-8234-73768e8fd659" TYPE="xfs"
/dev/vda2: LABEL="myroot" UUID="21ad8b9a-aaad-443c-b732-4e2522e95e23" TYPE="xfs"
/dev/vda3: UUID="12y99K-bv2A-y7RY-jhEW-rIWf-PcH5-SaiApN" TYPE="LVM2_member"
<span class="term_write">/dev/vda5: UUID="e20d65d9-20d4-472f-9f91-cdcfb30219d6" TYPE="ext4"</span> <span class="term_note"><==看到 ext4 了!</span>
[root@study ~]# <span class="term_command">dumpe2fs /dev/vda5</span>
dumpe2fs 1.42.9 (28-Dec-2013)
<span class="term_write">Filesystem volume name: <none></span> <span class="term_note"># 文件系统的名称(不一定会有)</span>
Last mounted on: <not available> <span class="term_note"># 上一次挂载的目录位置</span>
<span class="term_write">Filesystem UUID: e20d65d9-20d4-472f-9f91-cdcfb30219d6</span>
Filesystem magic number: 0xEF53 <span class="term_note"># 上方的 UUID 为 Linux 对设备的定义码</span>
Filesystem revision #: 1 (dynamic) <span class="term_note"># 下方的 features 为文件系统的特征数据</span>
<span class="term_write">Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent 64bit
flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize</span>
Filesystem flags: signed_directory_hash
<span class="term_write">Default mount options: user_xattr acl</span> <span class="term_note"># 缺省在挂载时会主动加上的挂载参数</span>
<span class="term_write">Filesystem state: clean</span> <span class="term_note"># 这块文件系统的状态为何,clean 是没问题</span>
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 65536 <span class="term_note"># inode 的总数</span>
Block count: 262144 <span class="term_note"># block 的总数</span>
Reserved block count: 13107 <span class="term_note"># 保留的 block 总数</span>
Free blocks: 249189 <span class="term_note"># 还有多少的 block 可用数量</span>
Free inodes: 65525 <span class="term_note"># 还有多少的 inode 可用数量</span>
First block: 0
<span class="term_write">Block size: 4096</span> <span class="term_note"># 单个 block 的容量大小</span>
Fragment size: 4096
Group descriptor size: 64
<span class="term_say">....(中间省略)....</span>
<span class="term_write">Inode size: 256</span> <span class="term_note"># inode 的容量大小!已经是 256 了喔!</span>
<span class="term_say">....(中间省略)....</span>
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 3c2568b4-1a7e-44cf-95a2-c8867fb19fbc
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M <span class="term_note"># Journal 日志式数据的可供纪录总容量</span>
Journal length: 8192
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 0-32767) <span class="term_note"># 第一块 block group 位置</span>
Checksum 0x13be, unused inodes 8181
Primary superblock at 0, Group descriptors at 1-1 <span class="term_note"># 主要 superblock 的所在喔!</span>
Reserved GDT blocks at 2-128
Block bitmap at 129 (+129), Inode bitmap at 145 (+145)
Inode table at 161-672 (+161) <span class="term_note"># inode table 的所在喔!</span>
28521 free blocks, 8181 free inodes, 2 directories, 8181 unused inodes
Free blocks: 142-144, 153-160, 4258-32767 <span class="term_note"># 底下两行说明剩余的容量有多少</span>
Free inodes: 12-8192
Group 1: (Blocks 32768-65535) [INODE_UNINIT] <span class="term_note"># 后续为更多其他的 block group 喔!</span>
<span class="term_say">....(底下省略)....</span>
<span class="term_say"># 由于数据量非常的庞大,因此鸟哥将一些信息省略输出了!上表与你的屏幕会有点差异。
# 前半部在秀出 supberblock 的内容,包括标头名称(Label)以及inode/block的相关信息
# 后面则是每个 block group 的个别信息了!您可以看到各区段数据所在的号码!
# 也就是说,基本上所有的数据还是与 block 的号码有关就是了!很重要!</span>
</pre></td></tr></tbody></table>
<p>如上所示,利用 dumpe2fs 可以查找到非常多的信息,不过依内容主要可以区分为上半部是 superblock 内容,
下半部则是每个 block group 的信息了。从上面的表格中我们可以观察到鸟哥这个 /dev/vda5 规划的 block 为 4K,
第一个 block 号码为 0 号,且 block group 内的所有信息都以 block 的号码来表示的。
然后在 superblock 中还有谈到目前这个文件系统的可用 block 与 inode 数量喔!</p>
<p>至于 block group 的内容我们单纯看 Group0 信息好了。从上表中我们可以发现:</p>
<ul>
<li>Group0 所占用的 block 号码由 0 到 32767 号,superblock 则在第 0 号的 block 区块内!</li>
<li>文件系统描述说明在第 1 号 block 中;</li>
<li>block bitmap 与 inode bitmap 则在 129 及 145 的 block 号码上。</li>
<li>至于 inode table 分布于 161-672 的 block 号码中!</li>
<li>由于 (1)一个 inode 占用 256 bytes ,(2)总共有 672 - 161 + 1(161本身) = 512 个 block 花在 inode table 上,
(3)每个 block 的大小为 4096 bytes(4K)。由这些数据可以算出 inode 的数量共有 512 * 4096 / 256 = 8192 个 inode 啦!</li>
<li>这个 Group0 目前可用的 block 有 28521 个,可用的 inode 有 8181 个;</li>
<li>剩余的 inode 号码为 12 号到 8192 号。</li></ul>
<p>如果你对文件系统的详细信息还有更多想要了解的话,那么请参考本章最后一小节的介绍喔!
否则文件系统看到这里对于基础认知您应该是已经相当足够啦!底下则是要探讨一下,
那么这个文件系统概念与实际的目录树应用有啥关连啊?</p>
<br></div><br>
<a id="harddisk-dir"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.4 与目录树的关系</h2>
<p>由前一小节的介绍我们知道在 Linux 系统下,每个文件(不管是一般文件还是目录文件)都会占用一个 inode ,
且可依据文件内容的大小来分配多个 block 给该文件使用。而由<a href="0210filepermission.html#filepermission_dir">第五章的权限说明</a>中我们知道目录的内容在记录文件名,
一般文件才是实际记录数据内容的地方。那么目录与文件在文件系统当中是如何记录数据的呢?基本上可以这样说:</p>
<ul class="toplist"><li>目录</li></ul>
<p>当我们在 Linux 下的文件系统创建一个目录时,<span class="text_import2">文件系统会分配一个 inode
与至少一块 block 给该目录</span>。其中,inode 记录该目录的相关权限与属性,并可记录分配到的那块 block 号码;
而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据。也就是说目录所占用的 block 内容在记录如下的信息:</p>
<a id="fig7.1.5"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/centos7_dir_block.jpg" alt="目录占用的 block 记录的数据示意图" title="目录占用的 block 记录的数据示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.1.5、记载于目录所属的 block 内的文件名与 inode 号码对应示意图</div>
<p>如果想要实际观察 root 家目录内的文件所占用的 inode 号码时,可以使用 ls -i 这个选项来处理:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ls -li</span>
total 8
<span class="term_write">53735697</span> -rw-------. 1 root root 1816 May 4 17:57 anaconda-ks.cfg
<span class="term_write">53745858</span> -rw-r--r--. 1 root root 1864 May 4 18:01 initial-setup-ks.cfg
</pre></td></tr></tbody></table>
<p>由于每个人所使用的电脑并不相同,系统安装时选择的项目与 partition 都不一样,因此你的环境不可能与我的 inode
号码一模一样!上表的左边所列出的 inode 仅是鸟哥的系统所显示的结果而已!而由这个目录的 block 结果我们现在就能够知道,
当你使用『 ll / 』时,出现的目录几乎都是 1024 的倍数,为什么呢?因为每个 block 的数量都是 1K, 2K, 4K 嘛!
看一下鸟哥的环境:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ll -d / /boot /usr/sbin /proc /sys</span>
dr-xr-xr-x. 17 root root 4096 May 4 17:56 / <span class="term_note"><== 1 个 4K block</span>
dr-xr-xr-x. 4 root root 4096 May 4 17:59 /boot <span class="term_note"><== 1 个 4K block</span>
dr-xr-xr-x. 155 root root 0 Jun 15 15:43 /proc <span class="term_note"><== 这两个为内存内数据,不占磁盘容量</span>
dr-xr-xr-x. 13 root root 0 Jun 15 23:43 /sys
dr-xr-xr-x. 2 root root 16384 May 4 17:55 /usr/sbin <span class="term_note"><== 4 个 4K block</span>
</pre></td></tr></tbody></table>
<p>由于鸟哥的根目录使用的 block 大小为 4K ,因此每个目录几乎都是 4K 的倍数。
其中由于 /usr/sbin 的内容比较复杂因此占用了 4 个 block !至于奇怪的 /proc
我们在<a href="0210filepermission.html#dir">第五章</a>就讲过该目录不占磁盘容量,
所以当然耗用的 block 就是 0 啰!</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 由上面的结果我们知道目录并不只会占用一个 block 而已,也就是说:
在目录底下的文件数如果太多而导致一个 block 无法容纳的下所有的文件名与 inode 对照表时,Linux
会给予该目录多一个 block 来继续记录相关的数据;
</fieldset><br>
<ul class="toplist"><li>文件:</li></ul>
<p>当我们在 Linux 下的 ext2 创建一个一般文件时, ext2 会分配一个 inode 与相对于该文件大小的 block 数量给该文件。例如:假设我的一个 block 为 4 Kbytes
,而我要创建一个 100 KBytes 的文件,那么 linux 将分配一个 inode 与 25 个 block 来保存该文件!
但同时请注意,由于 inode 仅有 12 个直接指向,因此还要多一个 block 来作为区块号码的记录喔!</p>
<ul class="toplist"><li>目录树读取:</li></ul>
<p>好了,经过上面的说明你也应该要很清楚的知道 inode 本身并不记录文件名,文件名的记录是在目录的 block 当中。
因此在<a href="0210filepermission.html#filepermission_dir">第五章文件与目录的权限</a>说明中,
我们才会提到『添加/删除/更名文件名与目录的 w 权限有关』的特色!那么因为文件名是记录在目录的 block 当中,
因此当我们要读取某个文件时,就务必会经过目录的 inode 与 block ,然后才能够找到那个待读取文件的 inode 号码,
最终才会读到正确的文件的 block 内的数据。</p>
<p>由于目录树是由根目录开始读起,因此系统透过挂载的信息可以找到挂载点的 inode 号码,此时就能够得到根目录的 inode 内容,并依据该 inode 读取根目录的 block
内的文件名数据,再一层一层的往下读到正确的文件名。举例来说,如果我想要读取 /etc/passwd 这个文件时,系统是如何读取的呢?</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ll -di / /etc /etc/passwd</span>
<span class="term_write"> 128</span> dr-xr-x<span class="term_write">r-x</span>. 17 root root 4096 May 4 17:56 /
<span class="term_write">33595521</span> drwxr-x<span class="term_write">r-x</span>. 131 root root 8192 Jun 17 00:20 /etc
<span class="term_write">36628004</span> -rw-r--<span class="term_write">r--</span>. 1 root root 2092 Jun 17 00:20 /etc/passwd
</pre></td></tr></tbody></table>
<p>在鸟哥的系统上面与 /etc/passwd 有关的目录与文件数据如上表所示,该文件的读取流程为(假设读取者身份为 dmtsai 这个一般身份用户):</p>
<ol class="text_import2">
<li>/ 的 inode:<br> 透过挂载点的信息找到 inode 号码为 128 的根目录 inode,且 inode
规范的权限让我们可以读取该 block 的内容(有 r 与 x) ;<br><br></li>
<li>/ 的 block:<br> 经过上个步骤取得 block 的号码,并找到该内容有 etc/ 目录的 inode 号码 (33595521);
<br><br></li>
<li>etc/ 的 inode:<br> 读取 33595521 号 inode 得知 dmtsai 具有 r 与 x 的权限,因此可以读取 etc/ 的 block 内容;
<br><br></li>
<li>etc/ 的 block:<br> 经过上个步骤取得 block 号码,并找到该内容有 passwd 文件的 inode 号码 (36628004);
<br><br></li>
<li>passwd 的 inode:<br> 读取 36628004 号 inode 得知 dmtsai 具有 r 的权限,因此可以读取 passwd 的 block 内容;
<br><br></li>
<li>passwd 的 block:<br> 最后将该 block 内容的数据读出来。</li>
</ol>
<ul class="toplist"><li>filesystem 大小与磁盘读取性能:</li></ul>
<p>另外,关于文件系统的使用效率上,当你的一个文件系统规划的很大时,例如 100GB 这么大时,
由于磁盘上面的数据总是来来去去的,所以,整个文件系统上面的文件通常无法连续写在一起(block 号码不会连续的意思),
而是填入式的将数据填入没有被使用的 block 当中。如果文件写入的 block 真的分的很散,
此时就会有所谓的<span class="text_import2">文件数据离散</span>的问题发生了。</p>
<p>如前所述,虽然我们的 ext2 在 inode 处已经将该文件所记录的 block 号码都记上了,
所以数据可以一次性读取,但是如果文件真的太过离散,确实还是会发生读取效率低落的问题。
因为磁盘读取头还是得要在整个文件系统中来来去去的频繁读取!
果真如此,那么可以将整个 filesystme 内的数据全部复制出来,将该 filesystem 重新格式化,
再将数据给他复制回去即可解决这个问题。</p>
<p>此外,如果 filesystem 真的太大了,那么当一个文件分别记录在这个文件系统的最前面与最后面的 block 号码中,
此时会造成磁盘的机械手臂移动幅度过大,也会造成数据读取性能的低落。而且读取头在搜索整个 filesystem 时,
也会花费比较多的时间去搜索!因此, partition 的规划并不是越大越好,
而是真的要针对您的主机用途来进行规划才行!^_^ </p>
<br></div><br>
<a id="harddisk-journal"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.5 EXT2/EXT3/EXT4 文件的访问与日志式文件系统的功能</h2>
<p>上一小节谈到的仅是读取而已,那么如果是新建一个文件或目录时,我们的文件系统是如何处理的呢?
这个时候就得要 block bitmap 及 inode bitmap 的帮忙了!假设我们想要添加一个文件,此时文件系统的行为是:</p>
<ol class="text_import2">
<li>先确定用户对于欲添加文件的目录是否具有 w 与 x 的权限,若有的话才能添加;</li>
<li>根据 inode bitmap 找到没有使用的 inode 号码,并将新文件的权限/属性写入;</li>
<li>根据 block bitmap 找到没有使用中的 block 号码,并将实际的数据写入 block 中,且更新 inode 的 block
指向数据;</li>
<li>将刚刚写入的 inode 与 block 数据同步更新 inode bitmap 与 block bitmap,并更新 superblock 的内容。</li>
</ol>
<p>一般来说,我们将 inode table 与 data block 称为数据存放区域,至于其他例如 superblock、
block bitmap 与 inode bitmap 等区段就被称为 metadata (中介数据) 啰,因为 <span class="text_import2">superblock, inode bitmap 及 block bitmap
的数据是经常变动的,每次添加、移除、编辑时都可能会影响到这三个部分的数据,因此才被称为中介数据</span>的啦。</p>
<ul class="toplist"><li>数据的不一致 (Inconsistent) 状态</li></ul>
<p>在一般正常的情况下,上述的添加动作当然可以顺利的完成。但是如果有个万一怎么办?
例如你的文件在写入文件系统时,因为不知名原因导致系统中断(例如突然的停电啊、
系统核心发生错误啊~等等的怪事发生时),所以写入的数据仅有 inode table 及 data block 而已,
最后一个同步更新中介数据的步骤并没有做完,此时就会发生 metadata 的内容与实际数据存放区产生<span class="text_import2">不一致 (Inconsistent)</span> 的情况了。</p>
<p>既然有不一致当然就得要克服!在早期的 Ext2 文件系统中,如果发生这个问题,
那么系统在重新开机的时候,就会借由 Superblock 当中记录的 valid bit (是否有挂载) 与
filesystem state (clean 与否) 等状态来判断是否强制进行数据一致性的检查!若有需要检查时则以 <a href="0230filesystem.html#fsck">e2fsck</a> 这支程序来进行的。</p>
<p>不过,这样的检查真的是很费时~因为要针对 metadata 区域与实际数据存放区来进行比对,
呵呵~得要搜索整个 filesystem 呢~如果你的文件系统有 100GB 以上,而且里面的文件数量又多时,
哇!系统真忙碌~而且在对 Internet 提供服务的服务器主机上面,
这样的检查真的会造成主机复原时间的拉长~真是麻烦~这也就造成后来所谓日志式文件系统的兴起了。</p>
<a id="journal"></a>
<ul class="toplist"><li>日志式文件系统 (Journaling filesystem)</li></ul>
<p>为了避免上述提到的文件系统不一致的情况发生,因此我们的前辈们想到一个方式,
如果在我们的 filesystem 当中规划出一个区块,该区块专门在记录写入或修订文件时的步骤,
那不就可以简化一致性检查的步骤了?也就是说:</p>
<ol class="text_import2">
<li>预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;</li>
<li>实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;</li>
<li>结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的纪录。</li></ol>
<p>在这样的进程当中,万一数据的纪录过程当中发生了问题,那么我们的系统只要去检查日志记录区块,
就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块 filesystem 去检查,
这样就可以达到快速修复 filesystem 的能力了!这就是日志式文件最基础的功能啰~</p>
<p>那么我们的 ext2 可达到这样的功能吗?当然可以啊!
就透过 ext3/ext4 即可! ext3/ext4 是 ext2 的升级版本,并且可向下兼容 ext2 版本呢!
所以啰,目前我们才建议大家,可以直接使用 ext4 这个 filesystem 啊!
如果你还记得 <a href="0230filesystem.html#dumpe2fs">dumpe2fs</a> 输出的消息,可以发现 superblock 里面含有底下这样的信息:</p>
<table class="term"><tbody><tr><td class="term"><pre>Journal inode: 8
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M
Journal length: 8192
Journal sequence: 0x00000001
</pre></td></tr></tbody></table>
<p>看到了吧!透过 inode 8 号记录 journal 区块的 block 指向,而且具有 32MB 的容量在处理日志呢!
这样对于所谓的日志式文件系统有没有比较有概念一点呢?^_^。</p>
<br></div><br>
<a id="harddisk-filerun"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.6 Linux 文件系统的运作</h2>
<p>我们现在知道了目录树与文件系统的关系了,但是由<a href="0105computers.html">第零章</a>的内容我们也知道,
所有的数据都得要加载到内存后 CPU 才能够对该数据进行处理。想一想,如果你常常编辑一个好大的文件,
在编辑的过程中又频繁的要系统来写入到磁盘中,由于磁盘写入的速度要比内存慢很多,
因此你会常常耗在等待磁盘的写入/读取上。真没效率!</p>
<p>为了解决这个效率的问题,因此我们的 Linux 使用的方式是透过一个称为异步处理 (asynchronously)
的方式。所谓的异步处理是这样的:</p>
<p>当系统加载一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设置为干净(clean)的。
<span class="text_import2">但如果内存中的文件数据被更改过了(例如你用 nano
去编辑过这个文件),此时该内存中的数据会被设置为脏的
(Dirty)。此时所有的动作都还在内存中运行,并没有写入到磁盘中</span>!
系统会不定时的将内存中设置为『Dirty』的数据写回磁盘,以保持磁盘与内存数据的一致性。
你也可以利用<a href="0160startlinux.html#sync">第四章谈到的 sync</a>指令来手动强迫写入磁盘。</p>
<p>我们知道内存的速度要比磁盘快的多,因此如果能够将常用的文件放置到内存当中,这不就会增加系统性能吗?
没错!是有这样的想法!因此我们 Linux 系统上面文件系统与内存有非常大的关系喔:</p>
<ul class="text_import2">
<li>系统会将常用的文件数据放置到主内存的缓冲区,以加速文件系统的读/写;</li>
<li>承上,因此 Linux 的物理内存最后都会被用光!这是正常的情况!可加速系统性能;</li>
<li>你可以手动使用 sync 来强迫内存中设置为 Dirty 的文件回写到磁盘中;</li>
<li>若正常关机时,关机指令会主动调用 sync 来将内存的数据回写入磁盘内;</li>
<li>但若不正常关机(如跳电、当机或其他不明原因),由于数据尚未回写到磁盘内,
因此重新开机后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。</li>
</ul>
</div><br>
<a id="harddisk-mount"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.7 挂载点的意义 (mount point)</h2>
<p>每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用。
将文件系统与目录树结合的动作我们称为『<span class="text_import2">挂载</span>』。
关于挂载的一些特性我们在<a href="0130designlinux.html#partition_install">第二章</a>稍微提过,
重点是:<span class="text_import2">挂载点一定是目录,该目录为进入该文件系统的入口。</span>
因此并不是你有任何文件系统都能使用,必须要『挂载』到目录树的某个目录后,才能够使用该文件系统的。</p>
<p>举例来说,如果你是依据鸟哥的方法<a href="0157installcentos7.html">安装你的 CentOS 7.x</a> 的话,
那么应该会有三个挂载点才是,分别是 /, /boot, /home 三个 (鸟哥的系统上对应的设备文件名为 LVM, LVM, /dev/vda2)。
那如果观察这三个目录的 inode 号码时,我们可以发现如下的情况:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ls -lid / /boot /home</span>
<span class="term_write">128</span> dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
<span class="term_write">128</span> dr-xr-xr-x. 4 root root 4096 May 4 17:59 /boot
<span class="term_write">128</span> drwxr-xr-x. 5 root root 41 Jun 17 00:20 /home
</pre></td></tr></tbody></table>
<p>看到了吧!由于 XFS filesystem 最顶层的目录之 inode 一般为 128 号,因此可以发现 /, /boot, /home 为三个不同的 filesystem 啰!
(因为每一行的文件属性并不相同,且三个目录的挂载点也均不相同之故。)
我们在<a href="0220filemanager.html">第六章一开始的路径</a>中曾经提到根目录下的 . 与 .. 是相同的东西,
因为权限是一模一样嘛!如果使用文件系统的观点来看,<span class="text_import2">同一个 filesystem
的某个 inode 只会对应到一个文件内容而已(因为一个文件占用一个 inode 之故)</span>,
因此我们可以透过判断 inode 号码来确认不同文件名是否为相同的文件喔!所以可以这样看:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ls -ild / /. /..</span>
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /.
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /..
</pre></td></tr></tbody></table>
<p>上面的信息中由于挂载点均为 / ,因此三个文件 (/, /., /..) 均在同一个 filesystem 内,而这三个文件的
inode 号码均为 128 号,因此这三个文件名都指向同一个 inode 号码,当然这三个文件的内容也就完全一模一样了!
也就是说,根目录的上层 (/..) 就是他自己!这么说,看的懂了吗? ^_^</p>
<br></div><br>
<a id="harddisk-other"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.8 其他 Linux 支持的文件系统与 VFS</h2>
<p>虽然 Linux 的标准文件系统是 ext2 ,且还有增加了日志功能的 ext3/ext4 ,事实上,Linux 还有支持很多文件系统格式的,
尤其是最近这几年推出了好几种速度很快的日志式文件系统,包括 SGI 的 XFS 文件系统,
可以适用更小型文件的 Reiserfs 文件系统,以及 Windows 的 FAT 文件系统等等,
都能够被 Linux 所支持喔!常见的支持文件系统有:</p>
<ul>
<li>传统文件系统:ext2 / minix / MS-DOS / FAT (用 vfat 模块) / iso9660 (光盘)等等;</li>
<li>日志式文件系统: ext3 /ext4 / ReiserFS / Windows' NTFS / IBM's JFS / SGI's XFS / ZFS</li>
<li>网络文件系统: NFS / SMBFS </li></ul>
<p>想要知道你的 Linux 支持的文件系统有哪些,可以察看底下这个目录:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ls -l /lib/modules/$(uname -r)/kernel/fs</span>
</pre></td></tr></tbody></table>
<p>系统目前已加载到内存中支持的文件系统则有:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">cat /proc/filesystems</span>
</pre></td></tr></tbody></table>
<ul class="list1"><li class="text_import1">Linux VFS (Virtual Filesystem Switch)</li></ul>
<p>了解了我们使用的文件系统之后,再来则是要提到,那么 Linux 的核心又是如何管理这些认识的文件系统呢?
其实,整个 Linux 的系统都是透过一个名为 Virtual Filesystem Switch 的核心功能去读取 filesystem 的。
也就是说,整个 Linux 认识的 filesystem 其实都是 VFS 在进行管理,我们用户并不需要知道每个 partition 上头的
filesystem 是什么~ VFS 会主动的帮我们做好读取的动作呢~</p>
<p>假设你的 / 使用的是 /dev/hda1 ,用 ext3 ,而 /home 使用 /dev/hda2 ,用 reiserfs ,
那么你取用 /home/dmtsai/.bashrc 时,有特别指定要用的什么文件系统的模块来读取吗?
应该是没有吧!这个就是 VFS 的功能啦!透过这个 VFS 的功能来管理所有的 filesystem,
省去我们需要自行设置读取文件系统的定义啊~方便很多!整个 VFS 可以约略用下图来说明:</p>
<a id="fig7.1.6"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/centos7_vfs.gif" alt="VFS 文件系统的示意图" title="VFS 文件系统的示意图" style="border: 0px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.1.6、VFS 文件系统的示意图</div>
<p>老实说,文件系统真的不好懂!
如果你想要对文件系统有更深入的了解,<a href="0230filesystem.html#ps5">文末的相关链接(注5)</a>务必要参考参考才好喔!</p>
<br></div><br>
<a id="harddisk-xfs"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.1.9 XFS 文件系统简介</h2>
<p>CentOS 7 开始,缺省的文件系统已经由原本的 EXT4 变成了 XFS 文件系统了!为啥 CentOS 要舍弃对 Linux 支持度最完整的 EXT 家族而改用 XFS 呢?
这是有一些原因存在的。</p>
<ul class="toplist"><li>EXT 家族当前较伤脑筋的地方:支持度最广,但格式化超慢!</li></ul>
<p>Ext 文件系统家族对于文件格式化的处理方面,采用的是预先规划出所有的 inode/block/meta data 等数据,未来系统可以直接取用,
不需要再进行动态配置的作法。这个作法在早期磁盘容量还不大的时候还算 OK 没啥问题,但时至今日,磁盘容量越来越大,连传统的 MBR 都已经被 GPT
所取代,连我们这些老人家以前听到的超大 TB 容量也已经不够看了!现在都已经说到 PB 或 EB 以上容量了呢!那你可以想像得到,当你的 TB 以上等级的传统 ext
家族文件系统在格式化的时候,光是系统要预先分配 inode 与 block 就消耗你好多好多的人类时间了...</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 之前格式化过一个 70 TB 以上的磁盘数组成为 ext4 文件系统,按下格式化,去喝了咖啡、吃了便当才回来看做完了没有...
所以,后来立刻改成 xfs 文件系统了。
</fieldset><br>
<p>另外,由于虚拟化的应用越来越广泛,而作为虚拟化磁盘来源的巨型文件 (单一文件好几个 GB 以上!) 也就越来越常见了。
这种巨型文件在处理上需要考虑到性能问题,否则虚拟磁盘的效率就会不太好看。因此,从 CentOS 7.x 开始,
文件系统已经由缺省的 Ext4 变成了 xfs 这一个较适合高容量磁盘与巨型文件性能较佳的文件系统了。</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 其实鸟哥有几组虚拟电脑教室服务器系统,里面跑的确实是 EXT4 文件系统,老实说,并不觉得比 xfs 慢!所以,对鸟哥来说,
性能并不是主要改变文件系统的考量!对于文件系统的复原速度、建置速度,可能才是鸟哥改换成 xfs 的思考点。
</fieldset><br>
<ul class="toplist"><li>XFS 文件系统的配置 (<a href="0230filesystem.html#ps6">注6</a>)</li></ul>
<p>基本上 xfs 就是一个日志式文件系统,而 CentOS 7.x 拿它当缺省的文件系统,自然就是因为最早之前,这个 xfs 就是被开发来用于高容量磁盘以及高性能文件系统之用,
因此,相当适合现在的系统环境。此外,几乎所有 Ext4 文件系统有的功能, xfs 都可以具备!也因此在本小节前几部份谈到文件系统时,
其实大部份的操作依旧是在 xfs 文件系统环境下介绍给各位的哩!</p>
<p>xfs 文件系统在数据的分布上,主要规划为三个部份,一个数据区 (data section)、一个文件系统活动登录区 (log section)以及一个即时运作区 (realtime section)。
这三个区域的数据内容如下:</p>
<div class="illus">
<ul><li>数据区 (data section)</li></ul>
<p>基本上,数据区就跟我们之前谈到的 ext 家族一样,包括 inode/data block/superblock 等数据,都放置在这个区块。
这个数据区与 ext 家族的 block group 类似,也是分为多个保存区群组 (allocation groups) 来分别放置文件系统所需要的数据。
每个保存区群组都包含了 (1)整个文件系统的 superblock、 (2)剩余空间的管理机制、 (3)inode的分配与追踪。此外,inode与 block 都是系统需要用到时,
这才动态配置产生,所以格式化动作超级快!</p>
<p class="text_import2">另外,与 ext 家族不同的是, xfs 的 block 与 inode 有多种不同的容量可供设置,block 容量可由 512bytes ~ 64K 调配,不过,Linux 的环境下,
由于内存控制的关系 (分页档 pagesize 的容量之故),因此最高可以使用的 block 大小为 4K 而已!(鸟哥尝试格式化 block 成为 16K 是没问题的,不过,Linux 核心不给挂载!
所以格式化完成后也无法使用啦!) 至于 inode 容量可由 256bytes 到 2M 这么大!不过,大概还是保留 256bytes 的默认值就很够用了!</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 总之, xfs 的这个数据区的保存区群组 (allocation groups, AG),你就将它想成是 ext 家族的 block 群组 (block groups) 就对了!本小节之前讲的都可以在这个区块内使用。
只是 inode 与 block 是动态产生,并非一开始于格式化就完成配置的。
</fieldset><br>
<ul><li>文件系统活动登录区 (log section)</li></ul>
<p>在登录区这个区域主要被用来纪录文件系统的变化,其实有点像是日志区啦!文件的变化会在这里纪录下来,直到该变化完整的写入到数据区后,
该笔纪录才会被终结。如果文件系统因为某些缘故 (例如最常见的停电) 而损毁时,系统会拿这个登录区块来进行检验,看看系统挂掉之前,
文件系统正在运作些啥动作,借以快速的修复文件系统。</p>
<p>因为系统所有动作的时候都会在这个区块做个纪录,因此这个区块的磁盘活动是相当频繁的!xfs 设计有点有趣,在这个区域中,
你可以指定外部的磁盘来作为 xfs 文件系统的日志区块喔!例如,你可以将 SSD 磁盘作为 xfs 的登录区,这样当系统需要进行任何活动时,
就可以更快速的进行工作!相当有趣!</p>
<ul><li>即时运作区 (realtime section)</li></ul>
<p>当有文件要被创建时,xfs 会在这个区段里面找一个到数个的 extent 区块,将文件放置在这个区块内,等到分配完毕后,再写入到 data section 的 inode 与 block 去!
这个 extent 区块的大小得要在格式化的时候就先指定,最小值是 4K 最大可到 1G。一般非磁盘数组的磁盘缺省为 64K 容量,而具有类似磁盘数组的 stripe
情况下,则建议 extent 设置为与 stripe 一样大较佳。这个 extent 最好不要乱动,因为可能会影响到实体磁盘的性能喔。</p>
</div>
<a id="xfs_info"></a><ul class="toplist"><li>XFS 文件系统的描述数据观察</li></ul>
<p>刚刚讲了这么多,完全无法理会耶~有没有像 EXT 家族的 dumpe2fs 去观察 superblock 内容的相关指令可以查阅呢?有啦!可以使用 xfs_info 去观察的!
详细的指令作法可以参考如下:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">xfs_info 挂载点|设备文件名</span>
<span class="term_hd">范例一:找出系统 /boot 这个挂载点底下的文件系统的 superblock 纪录</span>
[root@study ~]# <span class="term_command">df -T /boot</span>
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/vda2 xfs 1038336 133704 904632 13% /boot
<span class="term_say"># 没错!可以看得出来是 xfs 文件系统的!来观察一下内容吧!</span>
[root@study ~]# <span class="term_command">xfs_info /dev/vda2</span>
1 meta-data=/dev/vda2 <span class="term_write">isize=256</span> agcount=4, agsize=65536 blks
2 = sectsz=512 attr=2, projid32bit=1
3 = crc=0 finobt=0
4 data = <span class="term_write">bsize=4096</span> blocks=262144, imaxpct=25
5 = <span class="term_write">sunit=0 swidth=0</span> blks
6 naming =version 2 bsize=4096 ascii-ci=0 ftype=0
7 log =internal bsize=4096 blocks=2560, version=2
8 = sectsz=512 sunit=0 blks, lazy-count=1
9 realtime =none <span class="term_write">extsz=4096</span> blocks=0, rtextents=0
</pre></td></tr></tbody></table>
<p>上面的输出消息可以这样解释:</p>
<ul><li>第 1 行里面的 isize 指的是 inode 的容量,每个有 256bytes 这么大。至于 agcount 则是前面谈到的保存区群组 (allocation group) 的个数,共有 4 个,
agsize 则是指每个保存区群组具有 65536 个 block 。配合第 4 行的 block 设置为 4K,因此整个文件系统的容量应该就是 4*65536*4K 这么大!</li>
<li>第 2 行里面 sectsz 指的是逻辑磁区 (sector) 的容量设置为 512bytes 这么大的意思。</li>
<li>第 4 行里面的 bsize 指的是 block 的容量,每个 block 为 4K 的意思,共有 262144 个 block 在这个文件系统内。</li>
<li>第 5 行里面的 sunit 与 swidth 与磁盘数组的 stripe 相关性较高。这部份我们底下格式化的时候会举一个例子来说明。</li>
<li>第 7 行里面的 internal 指的是这个登录区的位置在文件系统内,而不是外部设备的意思。且占用了 4K * 2560 个 block,总共约 10M 的容量。</li>
<li>第 9 行里面的 realtime 区域,里面的 extent 容量为 4K。不过目前没有使用。</li>
</ul>
<p>由于我们并没有使用磁盘数组,因此上头这个设备里头的 sunit 与 extent 就没有额外的指定特别的值。根据 xfs(5) 的说明,这两个值会影响到你的文件系统性能,
所以格式化的时候要特别留意喔!上面的说明大致上看看即可,比较重要的部份已经用特殊字体圈起来,你可以瞧一瞧先!</p>
<br></div>
</div>
<a id="filesys"></a>
<div class="block1">
<h2>7.2 文件系统的简单操作</h2>
<p>稍微了解了文件系统后,再来我们得要知道如何查找整体文件系统的总容量与每个目录所占用的容量啰!
此外,前两章谈到的文件类型中尚未讲的很清楚的链接档 (Link file) 也会在这一小节当中介绍的。</p>
<a id="filesys_1"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.2.1 磁盘与目录的容量</h2>
<p>现在我们知道磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的。
那在文本接口底下该如何叫出这几个数据呢?底下就让我们来谈一谈这两个指令:</p>
<ul>
<li>df:列出文件系统的整体磁盘使用量;</li>
<li>du:评估文件系统的磁盘使用量(常用在推估目录所占容量)</li>
</ul>
<a id="df"></a>
<ul class="toplist"><li>df</li></ul>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">df [-ahikHTm] [目录或文件名]</span>
<span class="term_say">选项与参数:
-a :列出所有的文件系统,包括系统特有的 /proc 等文件系统;
-k :以 KBytes 的容量显示各文件系统;
-m :以 MBytes 的容量显示各文件系统;
<span style="text-decoration: underline">-h :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;</span>
-H :以 M=1000K 取代 M=1024K 的进位方式;
-T :连同该 partition 的 filesystem 名称 (例如 xfs) 也列出;
<span style="text-decoration: underline">-i :不用磁盘容量,而以 inode 的数量来显示</span></span>
<span class="term_hd">范例一:将系统内所有的 filesystem 列出来!</span>
[root@study ~]# <span class="term_command">df</span>
Filesystem <span class="term_write">1K-blocks</span> Used Available Use% Mounted on
/dev/mapper/centos-root 10475520 3409408 7066112 33% /
devtmpfs 627700 0 627700 0% /dev
tmpfs 637568 80 637488 1% /dev/shm
tmpfs 637568 24684 612884 4% /run
tmpfs 637568 0 637568 0% /sys/fs/cgroup
/dev/mapper/centos-home 5232640 67720 5164920 2% /home
/dev/vda2 1038336 133704 904632 13% /boot
<span class="term_say"># 在 Linux 底下如果 df 没有加任何选项,那么缺省会将系统内所有的
# (不含特殊内存内的文件系统与 swap) 都以 1 Kbytes 的容量来列出来!
# 至于那个 /dev/shm 是与内存有关的挂载,先不要理他!</span>
</pre></td></tr></tbody></table>
<p>先来说明一下范例一所输出的结果消息为:</p>
<ul>
<li><span class="text_import2">Filesystem</span>:代表该文件系统是在哪个 partition ,所以列出设备名称;</li>
<li><span class="text_import2">1k-blocks</span>:说明底下的数字单位是 1KB 呦!可利用 -h 或 -m 来改变容量;</li>
<li><span class="text_import2">Used</span>:顾名思义,就是使用掉的磁盘空间啦!</li>
<li><span class="text_import2">Available</span>:也就是剩下的磁盘空间大小;</li>
<li><span class="text_import2">Use%</span>:就是磁盘的使用率啦!如果使用率高达 90% 以上时,
最好需要注意一下了,免得容量不足造成系统问题喔!(例如最容易被灌爆的 /var/spool/mail 这个放置邮件的磁盘)</li>
<li><span class="text_import2">Mounted on</span>:就是磁盘挂载的目录所在啦!(挂载点啦!)</li>
</ul>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例二:将容量结果以易读的容量格式显示出来</span>
[root@study ~]# <span class="term_command">df -h</span>
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 10G 3.3G 6.8G 33% /
devtmpfs 613M 0 613M 0% /dev
tmpfs 623M 80K 623M 1% /dev/shm
tmpfs 623M 25M 599M 4% /run
tmpfs 623M 0 623M 0% /sys/fs/cgroup
/dev/mapper/centos-home 5.0G 67M 5.0G 2% /home
/dev/vda2 1014M 131M 884M 13% /boot
<span class="term_say"># 不同于范例一,这里会以 G/M 等容量格式显示出来,比较容易看啦!</span>
<span class="term_hd">范例三:将系统内的所有特殊文件格式及名称都列出来</span>
[root@study ~]# <span class="term_command">df -aT</span>
Filesystem <span class="term_write">Type</span> 1K-blocks Used Available Use% Mounted on
rootfs rootfs 10475520 3409368 7066152 33% /
proc proc 0 0 0 - /proc
sysfs sysfs 0 0 0 - /sys
devtmpfs devtmpfs 627700 0 627700 0% /dev
securityfs securityfs 0 0 0 - /sys/kernel/security
tmpfs tmpfs 637568 80 637488 1% /dev/shm
devpts devpts 0 0 0 - /dev/pts
tmpfs tmpfs 637568 24684 612884 4% /run
tmpfs tmpfs 637568 0 637568 0% /sys/fs/cgroup
<span class="term_say">.....(中间省略).....</span>
/dev/mapper/centos-root xfs 10475520 3409368 7066152 33% /
selinuxfs selinuxfs 0 0 0 - /sys/fs/selinux
<span class="term_say">.....(中间省略).....</span>
/dev/mapper/centos-home xfs 5232640 67720 5164920 2% /home
/dev/vda2 xfs 1038336 133704 904632 13% /boot
binfmt_misc binfmt_misc 0 0 0 - /proc/sys/fs/binfmt_misc
<span class="term_say"># 系统里面其实还有很多特殊的文件系统存在的。那些比较特殊的文件系统几乎
# 都是在内存当中,例如 /proc 这个挂载点。因此,这些特殊的文件系统
# 都不会占据磁盘空间喔! ^_^</span>
<span class="term_hd">范例四:将 /etc 底下的可用的磁盘容量以易读的容量格式显示</span>
[root@study ~]# <span class="term_command">df -h /etc</span>
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 10G 3.3G 6.8G 33% /
<span class="term_say"># 这个范例比较有趣一点啦,在 df 后面加上目录或者是文件时, df
# 会自动的分析该目录或文件所在的 partition ,并将该 partition 的容量显示出来,
# 所以,您就可以知道某个目录底下还有多少容量可以使用了! ^_^</span>
<span class="term_hd">范例五:将目前各个 partition 当中可用的 inode 数量列出</span>
[root@study ~]# <span class="term_command">df -ih </span>
Filesystem <span class="term_write">Inodes</span> IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10M 108K 9.9M 2% /
devtmpfs 154K 397 153K 1% /dev
tmpfs 156K 5 156K 1% /dev/shm
tmpfs 156K 497 156K 1% /run
tmpfs 156K 13 156K 1% /sys/fs/cgroup
<span class="term_say"># 这个范例则主要列出可用的 inode 剩余量与总容量。分析一下与范例一的关系,
# 你可以清楚的发现到,通常 inode 的数量剩余都比 block 还要多呢</span>
</pre></td></tr></tbody></table>
<p>由于 df 主要读取的数据几乎都是针对一整个文件系统,因此读取的范围主要是在 Superblock 内的信息,
所以这个指令显示结果的速度非常的快速!在显示的结果中你需要特别留意的是那个根目录的剩余容量!
因为我们所有的数据都是由根目录衍生出来的,因此当根目录的剩余容量剩下 0 时,那你的 Linux 可能就问题很大了。</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 说个陈年老笑话!鸟哥还在念书时,别的研究室有个管理 Sun 工作站的研究生发现,
他的磁盘明明还有好几 GB ,但是就是没有办法将光盘内几 MB 的数据 copy 进去,
他就去跟老板讲说机器坏了!嘿!明明才来维护过几天而已为何会坏了!
结果他老板就将维护商叫来骂了 2 小时左右吧!<br><br>
后来,维护商发现原来磁盘的『总空间』还有很多,
只是某个分区填满了,偏偏该研究生就是要将数据 copy 去那个分区!呵呵!
后来那个研究生就被命令『再也不许碰 Sun 主机』了~~
</fieldset><br>
<p>另外需要注意的是,如果使用 -a 这个参数时,系统会出现 /proc 这个挂载点,但是里面的东西都是
0 ,不要紧张! /proc 的东西都是 Linux 系统所需要加载的系统数据,而且是挂载在『内存当中』的,
所以当然没有占任何的磁盘空间啰!</p>
<p>至于<span class="text_import2">那个 /dev/shm/ 目录,其实是利用内存虚拟出来的磁盘空间,通常是总物理内存的一半!</span>
由于是透过内存仿真出来的磁盘,因此你在这个目录底下创建任何数据文件时,访问速度是非常快速的!(在内存内工作)
不过,也由于他是内存仿真出来的,因此这个文件系统的大小在每部主机上都不一样,而且创建的东西在下次开机时就消失了!
因为是在内存中嘛!</p>
<a id="du"></a>
<ul class="toplist"><li>du</li></ul>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">du [-ahskm] 文件或目录名称</span>
<span class="term_say">选项与参数:
-a :列出所有的文件与目录容量,因为缺省仅统计目录底下的文件量而已。
-h :以人们较易读的容量格式 (G/M) 显示;
<span style="text-decoration: underline">-s :列出总量而已,而不列出每个各别的目录占用容量;</span>
-S :不包括子目录下的总计,与 -s 有点差别。
-k :以 KBytes 列出容量显示;
-m :以 MBytes 列出容量显示;</span>
<span class="term_hd">范例一:列出目前目录下的所有文件容量</span>
[root@study ~]# <span class="term_command">du</span>
4 ./.cache/dconf <span class="term_note"><==每个目录都会列出来</span>
4 ./.cache/abrt
8 ./.cache
<span class="term_say">....(中间省略)....</span>
0 ./test4
4 ./.ssh <span class="term_note"><==包括隐藏档的目录</span>
76 . <span class="term_note"><==这个目录(.)所占用的总量</span>
<span class="term_say"># 直接输入 du 没有加任何选项时,则 du 会分析『目前所在目录』
# 的文件与目录所占用的磁盘空间。但是,实际显示时,仅会显示目录容量(不含文件),
# 因此 . 目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量喔!
# 此外,输出的数值数据为 1K 大小的容量单位。</span>
<span class="term_hd">范例二:同范例一,但是将文件的容量也列出来</span>
[root@study ~]# <span class="term_command">du -a</span>
4 ./.bash_logout <span class="term_note"><==有文件的列表了</span>
4 ./.bash_profile
4 ./.bashrc
<span class="term_say">....(中间省略)....</span>
4 ./.ssh/known_hosts
4 ./.ssh
76 .
<span class="term_hd">范例三:检查根目录底下每个目录所占用的容量</span>
[root@study ~]# <span class="term_command">du -sm /*</span>
0 /bin
99 /boot
<span class="term_say">....(中间省略)....</span>
du: cannot access ‘/proc/17772/task/17772/fd/4’: No such file or directory
du: cannot access ‘/proc/17772/fdinfo/4’: No such file or directory
0 /proc <span class="term_note"><==不会占用硬盘空间!</span>
1 /root
25 /run
<span class="term_say">....(中间省略)....</span>
3126 /usr <span class="term_note"><==系统初期最大就是他了啦!</span>
117 /var
<span class="term_say"># 这是个很常被使用的功能~利用通配符 * 来代表每个目录,如果想要检查某个目录下,
# 哪个次目录占用最大的容量,可以用这个方法找出来。值得注意的是,如果刚刚安装好 Linux 时,
# 那么整个系统容量最大的应该是 /usr 。而 /proc 虽然有列出容量,但是那个容量是在内存中,
# 不占磁盘空间。至于 /proc 里头会列出一堆『No such file or directory』 的错误,
# 别担心!因为是内存内的进程,进程运行结束就会消失,因此会有些目录找不到,是正确的!</span>
</pre></td></tr></tbody></table>
<p>与 df 不一样的是,du 这个指令其实会直接到文件系统内去搜索所有的文件数据,
所以上述第三个范例指令的运作会运行一小段时间!此外,在缺省的情况下,容量的输出是以 KB 来设计的,
如果你想要知道目录占了多少 MB ,那么就使用 -m 这个参数即可啰!而,
如果你只想要知道该目录占了多少容量的话,使用 -s 就可以啦!</p>
<a id="20090830"></a>
<p>至于 -S 这个选项部分,由于 du 缺省会将所有文件的大小均列出,因此假设你在 /etc 底下使用 du 时,
所有的文件大小,包括 /etc 底下的次目录容量也会被计算一次。然后最终的容量 (/etc) 也会加总一次,
因此很多朋友都会误会 du 分析的结果不太对劲。所以啰,如果想要列出某目录下的全部数据,
或许也可以加上 -S 的选项,减少次目录的加总喔!</p>
<br></div><br>
<a id="link"></a>
<div class="block2"><div class="gototop"><a href="0230filesystem.html#top">Top</a></div>
<h2>7.2.2 实体链接与符号链接: ln</h2>
<p>关于链接(link)数据我们第五章的<a href="0210filepermission.html#filepermission_perm">Linux文件属性</a>及<a href="0210filepermission.html#filepermission_type">Linux文件种类与扩展名</a>当中提过一些信息,
不过当时由于尚未讲到文件系统,因此无法较完整的介绍链接档啦。不过在上一小节谈完了文件系统后,
我们可以来了解一下链接档这玩意儿了。</p>
<p>在 Linux 底下的链接档有两种,一种是类似 Windows 的捷径功能的文件,可以让你快速的链接到目标文件(或目录);
另一种则是透过文件系统的 inode 链接来产生新文件名,而不是产生新文件!这种称为实体链接 (hard link)。
这两种玩意儿是完全不一样的东西呢!现在就分别来谈谈。</p>
<a id="hard_link"></a>
<ul class="toplist"><li>Hard Link (实体链接, 硬式链接或实际链接)</li></ul>
<p>在前一小节当中,我们知道几件重要的信息,包括:</p>
<ul>
<li>每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向;</li>
<li>想要读取该文件,必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取。</li>
</ul>
<p>也就是说,其实文件名只与目录有关,但是文件内容则与 inode 有关。那么想一想,
<span class="text_import2">有没有可能有多个文件名对应到同一个 inode 号码呢?</span>有的!那就是 hard link 的由来。
所以简单的说:<span class="text_import2">hard link 只是在某个目录下添加一笔文件名链接到某 inode 号码的关连记录而已。
</span></p>
<p>举个例子来说,假设我系统有个 /root/crontab 他是 /etc/crontab 的实体链接,也就是说这两个文件名链接到同一个 inode ,
自然这两个文件名的所有相关信息都会一模一样(除了文件名之外)。实际的情况可以如下所示:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ll -i /etc/crontab</span>
<span class="term_write">34474855</span> -rw-r--r--. <span class="term_write">1</span> root root 451 Jun 10 2014 /etc/crontab
[root@study ~]# <span class="term_command">ln /etc/crontab .</span> <span class="term_note"><==创建实体链接的指令</span>
[root@study ~]# <span class="term_command">ll -i /etc/crontab crontab</span>
<span class="term_write">34474855</span> -rw-r--r--. <span class="term_write">2</span> root root 451 Jun 10 2014 crontab
<span class="term_write">34474855</span> -rw-r--r--. <span class="term_write">2</span> root root 451 Jun 10 2014 /etc/crontab
</pre></td></tr></tbody></table>
<p>你可以发现两个文件名都链接到 34474855 这个 inode 号码,所以您瞧瞧,是否文件的权限/属性完全一样呢?
因为这两个『文件名』其实是一模一样的『文件』啦!而且你也会发现第二个字段由原本的 1 变成 2 了!
那个字段称为『链接』,这个字段的意义为:『<span class="text_import2">有多少个文件名链接到这个 inode 号码</span>』的意思。
如果将读取到正确数据的方式画成示意图,就类似如下画面:</p>
<a id="fig7.2.1"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/hard_link1.gif" alt="实体链接的文件读取示意图" title="实体链接的文件读取示意图" style="border: 0px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.2.1、实体链接的文件读取示意图</div>
<p>上图的意思是,你可以透过 1 或 2 的目录之 inode 指定的 block
找到两个不同的文件名,而不管使用哪个文件名均可以指到 real 那个 inode
去读取到最终数据!那这样有什么好处呢?最大的好处就是『安全』!如同上图中,
<span class="text_import2">如果你将任何一个『文件名』删除,其实 inode 与 block 都还是存在的!</span>
此时你可以透过另一个『文件名』来读取到正确的文件数据喔!此外,不论你使用哪个『文件名』来编辑,
最终的结果都会写入到相同的 inode 与 block 中,因此均能进行数据的修改哩!</p>
<p>一般来说,使用 hard link 设置链接档时,磁盘的空间与 inode 的数目都不会改变!
我们还是由图 7.2.1 来看,由图中可以知道, hard link 只是在某个目录下的 block
多写入一个关连数据而已,既不会增加 inode 也不会耗用 block 数量哩!</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> hard link 的制作中,其实还是可能会改变系统的 block 的,那就是当你添加这笔数据却刚好将目录的 block
填满时,就可能会新加一个 block 来记录文件名关连性,而导致磁盘空间的变化!不过,一般 hard link
所用掉的关连数据量很小,所以通常不会改变 inode 与磁盘空间的大小喔!
</fieldset><br>
<p>由图 7.2.1 其实我们也能够知道,事实上 hard link 应该仅能在单一文件系统中进行的,应该是不能够跨文件系统才对!
因为图 7.2.1 就是在同一个 filesystem 上嘛!所以 hard link 是有限制的:</p>
<ul class="text_import2">
<li>不能跨 Filesystem;</li>
<li>不能 link 目录。</li></ul>
<p>不能跨 Filesystem 还好理解,那不能 hard link 到目录又是怎么回事呢?这是因为如果使用 hard link 链接到目录时,
链接的数据需要连同被链接目录底下的所有数据都创建链接,举例来说,如果你要将 /etc
使用实体链接创建一个 /etc_hd 的目录时,那么在 /etc_hd 底下的所有文件名同时都与 /etc
底下的文件名要创建 hard link 的,而不是仅链接到 /etc_hd 与 /etc 而已。
并且,未来如果需要在 /etc_hd 底下创建新文件时,连带的,
/etc 底下的数据又得要创建一次 hard link ,因此造成环境相当大的复杂度。
所以啰,目前 hard link 对于目录暂时还是不支持的啊!</p>
<a id="slink"></a>
<ul class="toplist"><li>Symbolic Link (符号链接,亦即是捷径)</li></ul>
<p>相对于 hard link , Symbolic link 可就好理解多了,基本上,
<span class="text_import2">Symbolic link 就是在创建一个独立的文件,而这个文件会让数据的读取指向他
link 的那个文件的文件名</span>!由于只是利用文件来做为指向的动作,
所以,<span class="text_import2">当来源档被删除之后,symbolic link 的文件会『开不了』</span>,
会一直说『无法开启某文件!』。实际上就是找不到原始『文件名』而已啦!</p>
<p>举例来说,我们先创建一个符号链接档链接到 /etc/crontab 去看看:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ln -s /etc/crontab crontab2</span>
[root@study ~]# <span class="term_command">ll -i /etc/crontab /root/crontab2</span>
<span class="term_write">34474855</span> -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
<span class="term_write">53745909</span> lrwxrwxrwx. 1 root root <span class="term_write">12</span> Jun 23 22:31 <span class="term_write">/root/crontab2 -> /etc/crontab</span>
</pre></td></tr></tbody></table>
<p>由上表的结果我们可以知道两个文件指向不同的 inode 号码,当然就是两个独立的文件存在!
而且<span class="text_import2">链接档的重要内容就是他会写上目标文件的『文件名』</span>,
你可以发现为什么上表中链接档的大小为 12 bytes 呢?
因为箭头(-->)右边的文件名『/etc/crontab』总共有 12 个英文,每个英文占用 1 个 bytes ,所以文件大小就是 12bytes了!</p>
<p>关于上述的说明,我们以如下图标来解释:</p>
<a id="fig7.2.2"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/symbolic_link1.gif" alt="符号链接的文件读取示意图" title="符号链接的文件读取示意图" style="border: 0px solid black; padding: 10px "></div>
<div style="text-align: center;">图7.2.2、符号链接的文件读取示意图</div>
<p>由 1 号 inode 读取到链接档的内容仅有文件名,根据文件名链接到正确的目录去取得目标文件的 inode ,
最终就能够读取到正确的数据了。你可以发现的是,如果目标文件(/etc/crontab)被删除了,那么整个环节就会无法继续进行下去,
所以就会发生无法透过链接档读取的问题了!</p>
<p>这里还是得特别留意,这个 <span class="text_import2">Symbolic Link 与 Windows
的捷径可以给他划上等号,由 Symbolic link 所创建的文件为一个独立的新的文件,所以会占用掉
inode 与 block </span>喔!</p>
<hr>
<p>由上面的说明来看,似乎 hard link 比较安全,因为即使某一个目录下的关连数据被杀掉了,
也没有关系,只要有任何一个目录下存在着关连数据,那么该文件就不会不见!举上面的例子来说,我的
/etc/crontab 与 /root/crontab 指向同一个文件,如果我删除了 /etc/crontab