无忧启动论坛

标题: 最简单的 Linux 文件系统是哪个? [打印本页]

作者: 不点    时间: 2019-3-5 10:43
标题: 最简单的 Linux 文件系统是哪个?
Linux 的文件系统有一大堆,每个文件系统都有自己的优点。但是,我认为 “简单就是美”。我开这个帖子,希望通过探讨学到知识。

大家最熟悉的文件系统,莫过于微软的 FAT 了。也许它不能算作“最”简单,但也算比较简单了。它的几个部分非常单纯:

保留空间(含有引导扇区)
FAT 表
FAT 表的备份
根目录表
数据区


FAT 文件系统用了几十年,没啥问题。只是文件长度限制为 4G 以内,才逐渐显示出瓶颈。遗憾的是,FAT 文件系统的目录项,没有权限设置相关字段,无法直接用作 Linux 的主文件系统,只能作为辅助的文件系统(mount 之后仅仅存放普通数据文件)。

由于 Linux 的文件系统太多,而一个人精力有限,很难逐个学习了解,所以,我希望有兴趣者,能一起讨论,互相帮助,少走弯路。

今天先贴一篇 blog 文章,作为学习的开端:


从零开始编写一个简单的Linux文件系统

作者:shuxiaogd
来源:CSDN
原文:https://blog.csdn.net/shuxiaogd/article/details/48829671
版权声明:本文为博主原创文章,转载请附上博文链接!


最近想研究一下 Linux 文件系统,最好的开始当然是自己写一个简单的文件系统,并能够 mount 上。

这方面的工作其实已经有很多人做过了,比如 IBM Linux 技术中心的教程:


Linux FileSystems in 21 Days( A step by step introduction to writing a Linux Filesystem)


点此下载源代码 samplefs


作者: forlight-edg    时间: 2019-3-5 12:27
插眼
作者: 2013olly    时间: 2019-3-5 13:08
不管底层是什么文件系统,上层的vfs文件系统基本绕不过去吧,能学懂vfs,其他文件系统也就知道怎么学了

上层文件系统可以认为是一个<文件路径,vfs-inode>的映射,底层文件系统则是<vfs-inode,real-inode>的映射,找到文件系统里自己实现的inode基本就可以读文件了。

个人的linux文件系统学习时用的方法,仅供参考
作者: 不点    时间: 2019-3-5 14:42
ext2/3/4的inode结构说明
https://www.cnblogs.com/liuxuzzz/p/5348545.html

上述 blog 对比了 ext2/3 和 ext4 的 inode 结构,在文章结尾,给出了相关链接。值得一看。

作者: 不点    时间: 2019-3-5 14:53
2013olly 发表于 2019-3-5 13:08
不管底层是什么文件系统,上层的vfs文件系统基本绕不过去吧,能学懂vfs,其他文件系统也就知道怎么学了

...

不是泛泛地学习,而是提出一个问题:如何让它“简单”。比如说,一个像微软 FAT 那样简单的文件系统,又能满足桌面 Linux 的使用,这样就 OK。

当然了,“简单”之后,肯定会损失某些东西,比如损失速度、性能,或者损失存储效率,等等。

但既然选择“简单”,就比较注重“简单”,而能够接受在其他方面的不足。

这不是技术,而是哲学。


作者: 不点    时间: 2019-3-5 15:38
漫谈 Linux 标准的文件系统 (Ext2/Ext3/Ext4)
http://www.cnblogs.com/justmine/p/9128730.html

这篇文章讲了很多基本概念。比如:
inode(索引节点)
记录文件的权限、属性和数据所在块 block 的号码,每个文件都有且仅有一个的 inode,每个 inode 都有自己的编号,可以把 inode 简单地理解为文档索引。

    备注:在磁盘格式化后,inode 的大小和数量都已经固定了,大小均为128 Bytes(新的 Ext4 和 xfs 为 256 Bytes)。读取文件时,先读取 inode 里面记录的文件属性和权限,匹配正确后,才会读取文件内容(block)。在 Linux 系统中,实际使用 inode 来识别文件,而不是用文件名,类似于用户标识和昵称的设计。



作者: slore    时间: 2019-3-5 22:39
如果作为文件系统学习的话,越小越好。

Menuet OS 1.4MB,不过这货不是Linux。Linux体系的话4MB?




  1. title MenuetOS
  2. find --set-root --ignore-floppies /M6413060.IMG
  3. map --mem /M6413060.IMG (fd0)
  4. map --hook
  5. chainloader (fd0)+1
  6. rootnoverify (fd0)
复制代码



M6413060.7z (804.76 KB, 下载次数: 41)
作者: pcfan120    时间: 2019-3-5 22:54
多谢大神的分享,学习下。。。
作者: 红毛樱木    时间: 2019-3-5 23:46
slore 发表于 2019-3-5 22:39
如果作为文件系统学习的话,越小越好。

Menuet OS 1.4MB,不过这货不是Linux。Linux体系的话4MB?

这玩意怎么这么厉害。。。
作者: 不点    时间: 2019-3-6 09:09
今天贴点 exFAT 的资料。从 exFAT 卷的布局可以了解,总体布局与 FAT32 相似,但缺少“保留扇区”这样一个区域。FAT32 的保留扇区数不是定死的。现在的“主引导区”就相当于原来的“保留扇区”区域,但现在它是固定的,总共占用 24 个扇区,不多也不少。这一点,算是与以往 FAT 系列文件系统最大的差别了。


exFAT volume layout

Offset, sectors
Size, sectors
Block
Comments
Main Boot Region(主引导区,占用 12 扇区)
0
1
Boot Sector
引导扇区(1个)
1
8
Extended Boot Sectors
扩展的引导扇区(8个)
9
1
OEM Parameters
OEM 参数扇区(1个)
10
1
Reserved
保留扇区(1个)
11
1
Boot Checksum
校验和扇区(1个)
Backup Boot Region(备份引导区,占用 12 扇区)
12
1
Boot Sector

13
8
Extended Boot Sectors

21
1
OEM Parameters

22
1
Reserved

23
1
Boot Checksum

FAT Region(文件分配表区)
24
FatOffset - 24
FAT Alignment
Boot Sectors contain FatOffset
FatOffset
FatLength
First FAT
Boot Sectors contain FatOffset and FatLength
FatOffset + FatLength
FatLength
Second FAT
For TexFAT only
Data Region(数据区)
FatOffset + FatLength * NumberOfFats
ClusterHeapOffset – (FatOffset + FatLength * NumberOfFats)
Cluster Heap Alignment
簇堆对齐
ClusterHeapOffset
ClusterCount * 2^SectorsPerClusterShift
Cluster Heap
簇堆起始扇区号
和占用扇区数
ClusterHeapOffset + ClusterCount * 2^SectorsPerClusterShift
VolumeLength – (ClusterHeapOffset + ClusterCount * 2^SectorsPerClusterShift)
Excess Space
尾部多余的空间


作者: 2013olly    时间: 2019-3-6 10:52
不点 发表于 2019-3-5 14:53
不是泛泛地学习,而是提出一个问题:如何让它“简单”。比如说,一个像微软 FAT 那样简单的文件系统,又 ...

那么,假如在fat基础上添加一两个字段,用来存放权限,软链接等内容,其他基本不怎么改,这是否算一个简单的文件系统?

如果真的实现了这样一个文件系统,文件系统和linux的接口部分估计不会太简单了,因为需要满足像vfs提供inode节点等功能,可能需要不少封装和模拟才可以实现。

如果实现一个和vfs比较相近的文件系统,接口和处理代码应该会简单很多,但是文件系统的二进制结构可能就没那么简单了。
作者: 不点    时间: 2019-3-6 12:01
exFAT Boot Sector
Offset
Size
Description
Comments
0 (0x00)
3
JumpBoot
0xEB7690
3 (0x03)
8
FileSystemName
"EXFAT>
11 (0x0B)
53
MustBeZero

64 (0x40)
8
PartitionOffset
In sectors; if 0, shall be ignored ——分区的起始扇区号(64位
72 (0x48)
8
VolumeLength
Size of exFAT volume in sectors —— 卷的扇区总数(64位
80 (0x50)
4
FatOffset
In sectors —— FAT 表的起始扇区号,应该是相对于分区起始吧
84 (0x54)
4
FatLength
In sectors. May exceed the required space in order to align the second FAT
88 (0x58)
4
ClusterHeapOffset
In sectors ——簇堆的起始扇区号,应该是相对于分区起始吧
92 (0x5C)
4
ClusterCount
2^32-11 is the maximum number of clusters could be described
96 (0x60)
4
RootDirectoryCluster
根目录的簇号
100 (0x64)
4
VolumeSerialNumber
卷序列号
104 (0x68)
2
FileSystemRevision
as MAJOR.minor, major revision is high byte, minor is low byte; currently 01.00 —— 文件系统版本号
106 (0x6A)
2
VolumeFlags * ↓
卷的标志
Offset
Size
Field
0
1
ActiveFat 0 - First FAT and Allocation Bitmap are active, 1- Second.
1
1
VolumeDirty (0-clean, 1-dirty)
2
1
MediaFailure (0 – no failures reported or they already marked as BAD clusters) 1- some read/write operations failed)
3
1
ClearToZero (no meaning)
4
12
Reserved (no meaning)
108 (0x6C)
1

BytesPerSectorShift
Power of 2. Minimum 9 (512 bytes per sector), maximum 12 (4096 bytes per sector)
109 (0x6D)
1
SectorsPerCluster Shift
Power of 2. Minimum 0 (1 sector per cluster), maximum 25 – BytesPerSectorShift, so max cluster size is 32 MB
110 (0x6E)
1

NumberOfFats
2 is for TexFAT only
111 (0x6F)
1
DriveSelect
Extended INT 13h drive number; typically 0x80 ——暗示,主板需要支持 EBIOS(LBA),而不是通常的 CHS。
112 (0x70)
1

PercentInUse
0..100 – percentage of allocated clusters rounded down to the integer 0xFF – percentage is not available
113 (0x71)
7
Reserved

120 (0x78)
390

BootCode

510 (0x1FE)
2
BootSignature
0xAA55 —— 这个启动标志固定位于 510 处,不是位于大扇区的尾部。
512 (0x200)
2^BytesPerSectorShift - 512
ExcessSpace
Not used —— 如果扇区大小超过 512 字节,多余的部分不使用。

只有分区起始扇区号和分区长度,是 64 位值,其他的量都是小值( 32 位以内的值)。这提示我们在设计一个新文件系统的时候,没必要把所有的值,都弄成 64 位。


作者: 不点    时间: 2019-3-6 12:11
2013olly 发表于 2019-3-6 10:52
那么,假如在fat基础上添加一两个字段,用来存放权限,软链接等内容,其他基本不怎么改,这是否算一个简 ...


exFAT 是微软的,大概只能用来学习、研究,不能企图把它改造成符合 Linux 要求的根文件系统。微软不会提供这种方便(或者说,可能性),因为那不符合微软的利益。前面我已经说了,假如有可能那样改造的话,估计早都有人做了。
作者: 不点    时间: 2019-3-6 14:34
exFAT - Extended Boot Sector
Offset
Size
Description
Comments
0 (0x00)
2^BytesPerSectorShift - 4
ExtendedBootCode

2^BytesPerSectorShift - 4
4
ExtendedBootSignature
0xAA550000
Whole sector is used for boot code except last 4 bytes used for signature in each sector.If Extended Boot Sector is not used, it should be filled with 0x00.Extended signature must be preserved.

对于大扇区来说,这次是使用整个扇区,而不是只有开头的 512 字节。而且,扩展引导标志是在整个扇区的尾部,而不是只在 512 字节之前。猜测这可能是因为,当 boot sector 接管控制后,已经知道了扇区大小,因此,扩展引导代码部分就可以使用整个的大扇区了。


作者: 不点    时间: 2019-3-6 17:30
exFAT - File Allocation Table (FAT)      

File Allocation Table (FAT) may contain 1 or 2 FATs, as defined in NumberOfFats field. ActiveFat field in VolumeFlags in the Main Boot Sector determines which FAT is active.

The first cluster is cluster 2, as in FAT32. Each FatEntry represents one cluster.

In exFAT, FAT is not used for tracking an allocation; an Allocation Bitmap is used for this purpose. FAT is only used for keeping chains of clusters of fragmented files. If a file is not fragmented, FAT table does not need to be updated. A Stream Extensions Directory Entry should be consulted to determine if the FAT chain is valid or not. If FAT chain is not valid, it does not need to be zeroed.

Offset
Size
Description
Comments
0 (0x00)
4
FatEntry[0]
Media type (should be 0xFFFFFFF8)
4 (0x04)
4
FatEntry[1]
Must be 0xFFFFFFFF
8 (0x08)
4
FatEntry[2]
First cluster
...
...
...
...
(ClusterCount + 1) * 4
4
FatEntry[ClusterCount + 1]
Last cluster
(ClusterCount + 2) * 4
Remainder of sector
ExcessSpace


Valid values of FAT entries:

Value 0x00000000 does not mean the cluster is free, it is an undefined value.
The second FAT table (presents only in TexFAT) is located immediately after the first one and has the same size.

Cluster Heap

The cluster heap is a set of clusters which hold data in exFAT. It contains:

The allocation status of clusters in cluster heap is tracked by Bitmap Allocation Table which itself located inside the cluster heap.

从上述描述可以知道,exFAT 在很多方面都像 FAT32。它的 FAT 表项(簇号)都是 32 位的,所以,它不是 FAT64。它可以看成是改进型的 FAT32。



与 FAT32 不同,exFAT 的 FAT 表是专门用来服务于“文件碎片”的。FAT32 的文件分配表还用于跟踪空间的分配情况。在 exFAT 中,开辟了新的 “职能部门”—— Bitmap Allocation Table ——用于跟踪空间分配情况。文件无碎片时,可以不更新对应的 FAT 表项。这意味着,当文件无碎片时,FAT 表里面的原有记录,可能是错的,不能反映真实的分配情况。


我觉得还是更新了好。一个连续的文件,更新一下 FAT 表,也不会造成多大的性能损失。好处是确保 FAT 表能够反映真实分配情况。这样,第三方工具恢复误删的文件,成功的可能性就大一些。 Bitmap Allocation Table 只对提升性能有用。一个精简的文件系统,不需要 Bitmap Allocation Table,就是说,原先的 FAT32 的那种处理,就算是可以了。


再一个细节的讨论,就是有关“0xFFFFFFFF — end of file (EOF mark)” 的。这是文件的最后一簇,它没有后续的簇号,因此,使用了 0xFFFFFFFF 来当作结束的标志。但是,这个结束标志带来的信息却仅仅是 “结束”而已,没能提供更加有用的信息。在设计某个新的文件系统时,如果用该文件的起始簇号来取代此处的 0xFFFFFFFF,则能够提供有价值的信息。就是说,当遇到起始簇号时,就认为到达了文件的结尾,这完全能够清晰地表明文件“结束”了。这样做的好处是,第三方恢复工具能够从一个 chain 的随便某个簇号开始,顺藤摸瓜,最终能找到起始簇号。如果是以 0xFFFFFFFF 结束,则无法方便快捷地找到起始簇号(需要遍历整个 FAT 表,才能找到起始簇号)。




作者: junyee    时间: 2019-3-6 22:04
slore 发表于 2019-3-5 22:39
如果作为文件系统学习的话,越小越好。

Menuet OS 1.4MB,不过这货不是Linux。Linux体系的话4MB?

当年玩过一个小系统,好像是1.4M,,还能驱动网卡,内置几个小游戏。不过忘记名字了。
作者: 不点    时间: 2019-3-7 06:55
exFAT — Directory Structure


exFAT uses tree structure to describe relationship between files and directories. The root of the directory tree is defined by directory located at RootDirectoryCluster. Subdirectories are single-linked to there parents. There is no special (.) and (..) directories pointing to itself and to parent like in FAT16/FAT32.
Each directory consists of a series of directory entries. Directory entries are classified as critical/benign and primary/secondary as follows:
Critical entries are required while benign entries are optional. Primary directory entries correspond to the entries in file system and describe main characteristics. Secondary directory entries extend the metadata associated with a primary directory entry end follow it.
A group of primary/secondary entries make up a directory entry set describing a file or directory. The first directory entry in the set is a primary directory entry. All subsequent entries, if any, must be secondary directory entries.
Each directory entry derives from Generica Directory Entry template. Size of directory entry is 32 bytes.
Offset
Size
Description
Comments
0 (0x00)
1
EntryType ↓

Bits
Size
Description
Comments
0-4
5
Code
5
1
Importance
0 — Critical entry, 1 — Benign entry
6
1
Category
0 — Primary entry, 1 — Secondary entry
7
1
In use status
0 – Not in use, 1 – In use
1 (0x01)
19
CustomDefined

20 (0x14)
4
FirstCluster
0 – no cluster allocation 2..ClusterCount+1 – cluster index
24 (0x18)
8
DataLength
In bytes
EntryType can have the following values:

Generic Primary Directory Entry Template

Offset
Size
Description
Comments
0 (0x00)
1
EntryType ↓

1 (0x01)
1
SecondaryCount
Number of secondary entries which immediately follow this primary entry and together comprise a directory entry set. Valid value is 0..255
2 (0x02)
2
SetChecksum
Checksum of all directory entries in the given set excluding this field. See EntrySetCheckSum().
4 (0x04)
2
GeneralPrimaryFlags

Bits
Size
Description
Comments
0
1
AllocationPossible
0-not possible (FirstCluster and DataLength undefined), 1-possible
1
1
NoFatChain
0-FAT cluster chain is valid 1-FAT cluster chain is not used (contiguous data)
2
14
CustomDefined

6 (0x06)
14
CustomDefined

20 (0x14)
4
FirstCluster

24 (0x18)
8
DataLength

All critical primary directory entries are located in root directory (except file directory entries). Benign primary directory enries are optional. If one benign primary entry is not recognized, all directory entry set is ignored.

Generic Secondary Directory Entry Template

Offset
Size
Description
Comments
0 (0x00)
1
EntryType ↓

1 (0x01)
1
GeneralSecondaryFlags

Bits
Size
Description
Comments
0
1
AllocationPossible

1
1
NoFatChain

2
14
CustomDefined

2 (0x02)
18
CustomDefined

20 (0x014)
4
FirstCluster

24 (0x018)
8
DataLength


Defined Directory Entries

EntryType
Primary
Critical
Code
Directory Entry
0x81
·
·
1
Allocation Bitmap
0x82
·
·
2
Up-case Table
0x83
·
·
3
Volume Label
0x85
·

5
File
0xA0
·
·
0
Volume GUID
0xA1
·

1
TexFAT Padding
0xA2
·

2
Windows CE Access Control Table
0xC0

·
0
Stream Extension
0xC1

·
1
File Name


可以看到,簇号占用 32 位,文件大小占用 64 位。我们留意,exFAT 对于 FAT32 的改进,最要紧的,也就在于将文件大小从 32 位扩展为 64 位。


作者: 不点    时间: 2019-3-7 08:44
exFAT — File Directory Entry

File directory entry describes files and directories. It is a primary critical directory entry and must be immediately followed by 1 Stream Extension directory entry and from 1 to 17 File Name directory entries . Those 3-19 directory entries comprise a directory entry set describing a single file or a directory.
Offset
Size
Description
Comments
0 (0x00)
1
EntryType
0x85
1 (0x01)
1
SecondaryCount
Must be from 2 to 18
2 (0x02)
2
SetChecksum

4 (0x04)
2
FileAttributes

Bits
Size
Attribute
Comments
0
1
ReadOnly

1
1
Hidden

2
1
System

3
1
Reserved1
这里保留了 1 个 bit
4
1
Directory

5
1
Archive

6
10
Reserved2
这里保留了 10 个 bit
6 (0x06)
2
Reserved1
这里保留了 2 个字节
8 (0x08)
4
CreateTimestamp

12 (0x0C)
4
LastModifiedTimestamp

16 (0x10)
4
LastAccessedTimestamp

20 (0x14)
1
Create10msIncrement
0..199
21 (0x15)
1
LastModified10msIncrement
0..199
22 (0x16)
1
CreateTimezoneOffset
Offset from UTC in 15 min increments
23 (0x17)
1
LastModifiedTimezoneOffset
Offset from UTC in 15 min increments
24 (0x18)
1
LastAccessedTimezoneOffset
Offset from UTC in 15 min increments
25 (0x19)
7
Reserved2
这里保留了 7 个字节


File Name Directory Entry
     
Offset
Size
Description
Comments
0 (0x00)
1
EntryType
0xC1
1 (0x01)
1
GeneralSecondaryFlags

Bits
Size
Attribute
Comments
0
1
AllocationPossible
Must be 0
1
1
NoFatChain
Must be 0
2
14
CustomDefined

2 (0x02)
30
FileName

File Name directory entries must immediately follow the Steam Extension directory entry in the number of NameLength/15 rounded up.
The maximum number of File Name entries is 17, each can hold up to 15 Unicode characters and the maximum file name length is 255. Unused portion of FileName field must be set to 0x0000.

Invalid File Name Characters


Character Code
Character
Description
0x0000 – 0x001F

Control codes
0x0022
"
Quotation mark
0x002A
*
Asterisk
0x002F
/
Forward slash
0x003A
:
Colon
0x003C
<
Less than
0x003E
>
Greater than
0x003F
?
Question mark
0x005C
\
Back slash
0x007C
|
Vertical bar

可以看到,exFAT 的目录项中,确实有一些保留位和保留字节。这为支持 Linux 权限设置,提供了可能性。但是,这些保留的字段,微软将来也有可能使用。如果真的要着手进行改造的话,就得猜测微软到底将来会怎么使用这些字段,以及可能的冲突会有多大,严重不严重。即便能够改造,也不一定值得去改造。exFAT 沿用了微软的很多习惯,这些习惯,与 Linux 有冲突。比如,文件名不区分大小写,这反而是个问题,因为你还得花费精力去比较文件名,让大小写一样的文件名视为相同的,这就增加了负担,不如像 Linux 目前这样 “区分大小写”,更简单、方便。再比如,一个长文件名,在 exFAT 的目录项中分为好多碎片,这也不如 Linux 的 ext2 目录项中的文件名是连续的一个字符串,来得更合理。


又比如,微软习惯于在目录项中存储 unicode 文件名(UTF-16 格式),这带来的好处不一定有多大。我认为(如果设计)一个(新的) Linux 的文件系统,应该在目录项中存储 UTF-8 格式的文件名。分析如下:(一)UTF-16 和 UTF-8 都是变长的。UTF-16 的好处是,在常用文字 65536 个字符(BMP)以内,统一都是 2 字节。但在 BMP 以外,需要 4 字节。而且,UTF-16 最大只能处理 unicode 的码点 0x10FFFF,目前虽然够用,但将来 unicode 字符集完善以后,就处理不了了。UTF-8 的好处是,可以处理全部 unicode 码点,没有死角。UTF-8 的缺点是,在 65536 个字符以内,UTF-8 是变长的,可能在 1 到 3 个字节之间变动。汉字是 3 个字节。当然了,谁如果不是吃饱了撑的,也不会在文件名中采用 BMP 以外的冷僻字符。因此,在变长问题上,UTF-16 稍稍占优。(二)UTF-16 在普通的终端使用上,还是不行的,需要转换。而 UTF-8 几乎在 Linux 下取得事实工业标准的地位了。使用时不需要转换。比如,ls 命令列出的文件名,与磁盘上保存的文件名是一样的字符串,都是 UTF-8 格式。(三)UTF-16 和 UTF-32 都存在 “字节序” (大小端)问题,UTF-8 不存在这样的问题。(四)UTF-16 在 65536 个字符(BMP)以内,节约了汉字的空间占用(只占 2 字节),比 UTF-8 的 3 字节,少占用一个字节。但它浪费了英文字符一个字节:UTF-8 只需一个字节,UTF-16 需要 2 个字节(UTF-32 需要 4 个字节)。然而,英文字符文件名是更频繁使用的文件名,尤其是对于 Linux 用户来说,更是这样,因此,这种浪费就有点大了。当然了,在文件名方面,浪费一些字节,也不是很要紧的。一个长篇小说的浪费,才算是浪费。综合以上几条,在 Linux 的文件系统内部直接采用 UTF-8 文件名,相比于 UTF-16 和 UTF-32,优势更大一些。



exFAT 的文件名和目录项信息集中放在了一起;Linux 的 ext2 中的目录项只记录文件名和 inode 的对应关系,而由另外的 inode 结构来记录文件的信息。我认为,Linux 的 ext2 的做法更好一点。但是,Linux 的 ext2 中,对磁盘块多级寻址,还是复杂了。微软的 FAT 和 exFAT 中都是用单一的簇号链(链接表)来寻址,这在逻辑上是非常简单的。




作者: 不点    时间: 2019-3-7 10:33
本帖最后由 不点 于 2019-3-30 10:27 编辑

Linux 文件系统中的一个特性——硬链接——好像是微软不曾使用的(更正:NTFS 好像也支持硬链接)。当然了,硬链接究竟能有多大用处的问题,也值得讨论。不过,现在先不讨论这个问题。贴一篇文章,了解这方面的知识。

理解 Linux 的硬链接与软链接
https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/

摘录如下:

由于硬链接是有着相同 inode 号仅文件名不同的文件,因此硬链接存在以下几点特性:

    文件有相同的 inode 及 data block;
    只能对已存在的文件进行创建;
    不能交叉文件系统进行硬链接的创建;
    不能对目录进行创建,只可对文件创建;
    删除一个硬链接文件并不影响其他有相同 inode 号的文件。

软链接的创建与使用没有类似硬链接的诸多限制:

    软链接有自己的文件属性及权限等;
    可对不存在的文件或目录创建软链接;
    软链接可交叉文件系统;
    软链接可对文件或目录创建;
    创建软链接时,链接计数 i_nlink 不会增加;
    删除软链接并不影响被指向的文件,但若被指向的原文件被删除,则相关软连接被称为死链接(即 dangling link,若被指向路径文件被重新创建,死链接可恢复为正常的软链接)。


上述文章还提到了“文件太多导致 inode 被用光(无法创建新文件了),但文件系统的空闲空间却还有很多”的情况。这说明,固定 inode 数目的文件系统设计,也有它不合理的一面。微软的文件系统不存在这个问题(更正:支持硬链接的 NTFS 是否存在这个问题,也未可知)。


作者: 不点    时间: 2019-3-8 11:46
ext4 — Linear (Classic) Directories


By default, each directory lists its entries in an “almost-linear”array. I write “almost” because it’s not a linear array in the memorysense because directory entries are not split across filesystem blocks.Therefore, it is more accurate to say that a directory is a series ofdata blocks and that each block contains a linear array of directoryentries. The end of each per-block array is signified by reaching theend of the block; the last entry in the block has a record length thattakes it all the way to the end of the block. The end of the entiredirectory is of course signified by reaching the end of the file. Unuseddirectory entries are signified by inode = 0. By default the filesystemuses struct ext4_dir_entry_2 for directory entries unless the“filetype” feature flag is not set, in which case it usesstruct ext4_dir_entry.
The original directory entry format is struct ext4_dir_entry, whichis at most 263 bytes long, though on disk you’ll need to referencedirent.rec_len to know for sure.

OffsetSizeNameDescription
0x0__le32inodeNumber of the inode that this directory entry points to.
0x4__le16rec_lenLength of this directory entry. Must be a multiple of 4.
0x6__le16name_lenLength of the file name.
0x8charname[EXT4_NAME_LEN]File name.

Since file names cannot be longer than 255 bytes, the new directoryentry format shortens the rec_len field and uses the space for a filetype flag, probably to avoid having to load every inode during directorytree traversal. This format is ext4_dir_entry_2, which is at most263 bytes long, though on disk you’ll need to referencedirent.rec_len to know for sure.

OffsetSizeNameDescription
0x0__le32inodeNumber of the inode that this directory entry points to.
0x4__le16rec_lenLength of this directory entry.
0x6__u8name_lenLength of the file name.
0x7__u8file_typeFile type code, see ftype table below.
0x8charname[EXT4_NAME_LEN]File name.

The directory file type is one of the following values:

ValueDescription
0x0Unknown.
0x1Regular file.
0x2Directory.
0x3Character device file.
0x4Block device file.
0x5FIFO.
0x6Socket.
0x7Symbolic link.

ext4 的上述目录结构,非常简单,它只把文件名同 inode 号码对应起来,就完事。然而,为了加快目录项的定位,后来还发明了 Hash Tree Directories,非常复杂。它为了与 ext2 兼容,可能没法对上述目录结构进行大的修改,所以,只能另外设计一个结构,而不是直接修改现有结构。假如我们要设计一个新的文件系统,就不必考虑与 ext2 的兼容问题了,因此,我们可以直接改进目录表的结构。比如说,改成这样:


OffsetSizeNameDescription
0x0__le32inodeNumber of the inode that this directory entry points to.
0x4__le16rec_lenLength of this directory entry.
0x6__u8name_lenLength of the file name.
0x7__u8file_typeFile type code.
0x8__le32hashFile name hash.
0xCcharname[EXT4_NAME_LEN]File name.

同一目录下的文件名,使用的频度是不同的。可以再增加一个字段,用来表示访问次数。访问次数多的,调整到该目录的第一磁盘块(或者前 4 个磁盘块),让它更容易被找到。


另外,目录结构也不一定从一开始就是目录项的记录。可以在开头有一个说明性的 super 区域,记录着该目录的一些变量或信息。比如,有个变量表示本信息域的长度,指示实际的目录项从哪里开始。另外有两个变量分别记录该目录下最大的访问次数和最小的访问次数。当最小的访问次数已经达到最大访问次数的一半时,应该把本目录下所有文件的访问次数都减去这个最小值。当最大值将要溢出时,把本目录下所有文件的访问次数都除以 2。



对于很久(比如 30 天)都没有修改的文件(看修改时间就可知道这一点),操作系统应该在空闲时,对其进行整理碎块,让它变成连续的。inode 结构中应该有个字段,表示文件是否连续(就像微软所做的那样)。


作者: 2011os_defend    时间: 2019-3-8 22:04
还有几个我认为比较好的文件系统,JFS,XFS,综合实际使用比较,最终停留在EXT4和XFS上,整体觉得XFS更优秀一些,前辈有空可以研究一下,另外一个复杂的文件系统我个人并不喜欢,比如ZFS也很好。

对于个人而言,能可靠,稳定,快速,安全的保存和读写数据就是最本质的需求,过多的特性增加复杂度,有时实用价值也不大。
作者: 不点    时间: 2019-3-9 01:08
2011os_defend 发表于 2019-3-8 22:04
还有几个我认为比较好的文件系统,JFS,XFS,综合实际使用比较,最终停留在EXT4和XFS上,整体觉得XFS更优秀 ...

一楼给出的那个 IBM 教程,比较了各个文件系统的代码量,发现 XFS 的代码量是最大的,达到 7 万行。ext3 是最小的,只有 1 万行。因此,XFS 不是一个简单的文件系统。
作者: 不点    时间: 2019-3-10 15:38
本帖最后由 不点 于 2019-3-10 15:43 编辑

Unix 传统的 user-group-other 权限设置,被认为是不够用的,因此发展了 POSIX ACL(访问控制列表),我理解为 “附加的(或辅助的)权限控制”。相应地,在 inode 结构里面,也增加了 ACL 域。ACL 只用在特殊场合,传统的权限控制仍是基本的。如果我们为每个文件都预留很多 ACL 空间,浪费太严重。如果预留的空间少了,又可能不够用。这就看到,固定大小的 inode,暴露出了缺点。解决办法是,改进文件系统的设计,让 inode 结构长度可变。

既然 inode 结构长度都可以不固定了,那么,考虑干脆把它与文件内容放在一起。比如,将它放在文件簇链的尾部,不占用额外的空间。当然了,如果尾部剩余的空间不够用,那就多分配一簇的空间。通常 1 簇至少有 4K,足够用了。无论是否额外分配一簇,inode 结构都存放在链的最后一簇。最后一簇的簇号,就当成 inode 号码。簇尾部的 inode 结构,可以设置成倒序的,即,从后向前记录每个结构成员。当然,要有个 inode 合法标志之类的东西,放在簇的末尾几个字节中。结构中也有一个字段,记录着文件的起始簇号。

上述讨论,适用于普通文件以及目录。对于特殊文件,例如设备、软链接等,它们占用的信息很少,可以考虑将它们的 inode 信息记录在目录项里面,不放在簇链中(若放在簇链中,就太浪费了)。这些特殊文件,由于存放在目录项中,因此,它们的 inode 号可以无定义,或者说,不存在。

长度为 1K 的小文件(这里是指普通文件,不考虑目录),也可以直接放在目录项中(这种情况无 inode 号)。对于无 inode 号的文件,它们是无法用来进行硬链接的。


作者: 不点    时间: 2019-3-10 16:00
嗯,得补充一个重要的理念。一个文件系统用起来是否简单,与它设计起来是否简单,是不同的概念。操作系统会让差别变得不可见,用户无法从直觉上感知文件系统是否简单。

然而,一个复杂的文件系统,有可能被高手、黑客隐藏用户不知道的某些东西,比如,偷窃用户的资料。你可能是在某个安全保密部门工作,你的电脑可能没有上网(只在安全的内部网工作),但是,你有可能用你的 U 盘跟外界交流文件,在外面上网。这个 U 盘里面的文件系统,就可能充当间谍,在你不知情的情况下,把重要的秘密信息带出去。文件系统越简单,就越不容易隐藏那些对你不利的东西。一个高手,可以混进开源队伍里面,在操作系统以及文件系统里面制造隐蔽的后门。

作者: gnuxwy    时间: 2019-3-10 21:33
不点大师又在钻研新领域了啊。。。
文件系统么,没研究,只会用。反正gnux下首选ext2/3/4/5,  win下当然ntfs,优盘和移动硬盘用fat和exfat。。。

reactOS新版氏同时支持fat和btrfs的,或许以后btrfs也有可能成为win和lin之间都能较好工作的文件系统选择呢。。。

作者: 不点    时间: 2019-3-10 22:43
gnuxwy 发表于 2019-3-10 21:33
不点大师又在钻研新领域了啊。。。
文件系统么,没研究,只会用。反正gnux下首选ext2/3/4/5,  win下当然nt ...

没什么目的,谈不上钻研,闲着没事,碰上啥就想啥。btrfs 的体积比 ext4 大,翻倍还多。

在 linux kernel 源代码中,

squashfs   164K
fat           207K
ext2         265K
ntfs          967K
ext4       1.44M
btrfs       3.35M
xfs         3.64M


作者: 不点    时间: 2019-3-11 16:52
在百度上搜 “硬链接的用途”,大都在讲硬链接和软链接的差别,而提到具体应用场景的,却很少很少。根据搜到的结果,总结一下,硬链接大致有两个作用:

1、节省磁盘空间,省去一个复制的操作。
2、保护重要文件,以防误删(相当于多备份了一份)。

如果就只有这两个作用的话,那也太寒碜了吧?

自从使用 Linux 以来,20 多年了,我还真没用过硬链接,连一次都没用过。软链接倒是用过,也经常见到系统中有很多软链接。

猜测一下硬链接很少被人使用的原因:

1、习惯问题。人们习惯于拷贝,不习惯于使用硬链接。
2、海量磁盘空间用不完,没必要节省那么一点空间。
3、硬链接不能跨文件系统,用起来感到生疏。用软链接更自由。
4、不能对目录进行硬链接,使用范围狭窄,加剧了“生疏感”和 “不习惯”。软链接没这问题。
5、(继续上述第 4 条的讨论)由于硬链接在人们正想用它(对目录进行操作)的时候却不行,它也就失去关键的吸引力了。大家无奈去寻找别的替代方法,比如,mount --bind (或 mount -o bind)就是这样一种替代方法,这种方法用于软链接失效的场合。

作者: 2011os_defend    时间: 2019-3-11 20:51
不点 发表于 2019-3-9 01:08
一楼给出的那个 IBM 教程,比较了各个文件系统的代码量,发现 XFS 的代码量是最大的,达到 7 万行。ext3  ...

同意前辈的看法,xfs更新得算比较频繁,功能也越来越多。

另外ext3对手应该是ntfs吧?
作者: 不点    时间: 2019-3-11 22:00
前面谈到硬链接的使用频度不高。假如不支持硬链接的话,文件系统可以设计得更简单一些。

没有了硬链接,也就不需要记录 link-count 了,甚至 inode 也不需要了。不知我理解得是否正确:我觉得这个 inode 就是为硬链接准备的。如果不要硬链接了,也就不需要 inode 号码了。既然 inode 号码都不要了,那么 inode 也就不需要了。把 inode 结构里面的信息直接放在目录项中即可(正如微软的 FAT、exFAT 那样)。前面说了,目录项本来就不是固定长度的,因此,再添加一些 inode 成员信息,也不影响大局。

微软 exFAT 的目录项,光是 255 个 unicode 字符,都要消耗 17×32=544 字节,再加上其他信息,总共会超过 600 字节。现在在 ext4 的目录项中添加 inode 信息,最多也只有 263+256=519 字节而已。我们可以更灵活地处理,将目录项的最大长度尽量放宽一些,比如说,必要的时候,它可以达到 4K,甚至也可以完全不封顶(不封顶其实是说可以达到双字节整数的自然上限 64K,这不会带来什么问题,因为实际的目录项长度平均都会很小的,低于 100 字节)。

作者: gnuxwy    时间: 2019-3-11 22:38
真氏不懂这些底层文件系统的实现细节,看到不点大师的分析,真的有不明觉厉的感觉。。。

作者: 不点    时间: 2019-3-12 08:36
2011os_defend 发表于 2019-3-11 20:51
同意前辈的看法,xfs更新得算比较频繁,功能也越来越多。

另外ext3对手应该是ntfs吧?

ext2/3/4之类的,属于 Linux/Unix 阵营;FAT/NTFS 类的属于微软阵营。阵营不同,谈不上 “对手”。FAT/NTFS 类的文件系统,只能在 Linux 中作为辅助文件系统,不能作为主文件系统。而 ext2/3/4 在 Linux 中是“主”的地位,但在微软那里,需要下载一个第三方的文件系统驱动程序,才可以支持它,就是说,处于很“次”的地位。当然了,如果讨论纯技术,就某个侧重点来看,或许 ext3 是 NTFS 的对手,我对两者都没研究,不了解这方面的问题。
作者: 不点    时间: 2019-3-12 09:45
gnuxwy 发表于 2019-3-11 22:38
真氏不懂这些底层文件系统的实现细节,看到不点大师的分析,真的有不明觉厉的感觉。。。

真人不露相,您太客气了。文件系统是旧领域,不是新领域。万事万物,都有一个发展过程。每个发展的阶段,也都有其缺点或局限性,都有改进的余地,都可以加入新的思想在里面。在新思想渗透进去之后,或许也可看成是进入新领域了。

搞技术,就是要不断创新。创新是一个思想,一个思路。如果思想死了、思路断了,那就会说 “创新是找死”。有人说,创新是引领发展的动力,而也有人说,创新是找死。这两种都对。这两种反映的是不同的思想状况和不同的思路。创新是来解决事物发展中的矛盾的,是促进事物发展的。创新需要在一定程度上敢于打破教条,打破某些规范。创新也得保持现有的一些框框和规范,不能全盘否定,走极端。我们可以利用的资源总是有限的,我们在各种资源的利用上,就需要有取舍,有侧重点。需要在磁盘占用率以及访问效率等问题上,进行平衡。从某个角度来看,创新也不过就是权衡而已,通过权衡找到更有利的东西。再抽象一点,这就是哲学了。我们通过学习、研究、思考,来对比不同的文件系统的设计,合理抽取各自的优点,从而构造出一个新的文件系统,这大概也属于正常的思维模式吧,符合一般的科学研究或科学探索的规律(或特征)。还有一点非常重要的,就是,外行可做事。外行,就是门外汉的意思。外行不是不能做事,而是 “可做事”,有事可做。你想做事,就能做。你不想做事,整天到处游玩,那也一天天过去了。而且,有些事,还真得是只有外行才可能去做的,你信不信?他是内行,但由于某种原因,他不干那事。比如有可能是这样的情况:某些事做了白做、没好处,甚至做了反而对他(或他的公司)不利(有坏处),他就不可能去做。为什么各大公司都在免费让你下载他们的 APP 或“客户端”?甚至也有公司用金钱鼓励你下载安装的!那个 APP 客户端,肯定对他们公司有利。我以前在其他地方也经常说,这东西都是流氓,虽然流氓也是 “合理”的。你让这样有钱的公司去开发一个没有后门的 Linux 或者一个藏不住秘密的文件系统?凭啥啊?它怎么会去干呢?它钱多了,可以放火烧了,也不会去干这样的事情的。

作者: 不点    时间: 2019-3-12 21:06
接上文。

刚才谈到 APP 客户端。微软的系统,不限制任何软件的运行,至少以前是不限制。现在微软也在变化,也在设法限制用户。此处实在无法谈论好和坏。好的东西,如果没人生产它,怎么能好?坏的东西,也不会是绝对的坏,它也有好的一些方面。微软不限制软件的运行,这就让 Windows 成了跑马场,谁都可以上场踢腾。这就是说,微软的开放程度比较高。开放程度高,流氓软件、病毒也就更加泛滥,其中也就包括了 “客户端”。苹果是个封闭的系统,它就不让你随便运行软件。好处是,流氓软件也少。但话又说回来了,那就只剩下苹果自己当流氓了,它自己有完全的自由,想怎么耍你,就怎么耍你。你被完全锁在它的监狱里。失去自由的你,多年以后,显然后悔当初买了苹果。但是,死要面子,硬是说苹果的手机在水泥地上使劲摔也摔不坏,是非常优秀的。Android 比苹果开放,这才占领了苹果的江山。Android 像 Windows 那样,随便可以运行软件,因此,流氓软件也多。但 Android 和 Windows 不同的是,Android 采用权限控制,用户得不到 root 权限,不能更改系统,这样,系统永远可以恢复出厂设置,就不怕死掉了。但缺点是,这跟苹果类似,厂家耍流氓,预装流氓软件,控制用户,盗窃用户资料,泄漏用户秘密,用户只能忍受,毫无办法。 Android 有一半像微软的开放,另一半像苹果的封闭。Android 系统也有彻底死掉的,无法恢复出厂设置。这种情况有可能是用户私自 root 以后造成的,破坏了预装的软件,导致彻底无法恢复。也有可能是预装的流氓软件干的,它有着最高的权限,有能力搞破坏,让系统瘫痪。如果按照常规思维,肯定是微软的“全开放”,对用户更友好吧?可是,全开放以后,跑马场乱糟糟的,流氓病毒太猖狂,用户们通常没有驾驭能力,被耍得筋疲力尽。因此,用户们甘愿被人家 Android 预装软件控制住,反而觉得很省心。所以,后来微软也开始学习 Android 的这种封闭做法了。

作者: 易广白    时间: 2019-3-13 18:22
不点 发表于 2019-3-12 21:06
接上文。

刚才谈到 APP 客户端。微软的系统,不限制任何软件的运行,至少以前是不限制。现在微软也在变 ...

牛牛!不点大大!找到了“一般用户为什么傻”的根源,

本来一个菜市场,一些菜贩将它搅乱,导致没人来买菜,都去超市、专卖店了,菜市场的菜贩也只得转行。
作者: 不点    时间: 2019-3-13 19:20
易广白 发表于 2019-3-13 18:22
牛牛!不点大大!找到了“一般用户为什么傻”的根源,

本来一个菜市场,一些菜贩将它搅乱,导致没人来 ...

说的没错,有几次去自由市场买菜,本来也不经常去,只是偶然去了几次。结果你猜咋了?他们卖给我的价格,竟然比超市还贵。它这叫自毁市场啊!只要被骗一次,以后再去那里,就有心理障碍了:“一朝被蛇咬,十年怕井绳”。还是超市比较可信,俗话说,跑了和尚跑不了庙,它要为它的信誉负责。扯远点,美国讲求 “美国第一”,其实,美国一直都没把别国看得重要,它一直都是 “美国第一”。它现在再来提说 “美国第一”,那口味肯定很重。它现在的 “美国第一”,我理解为要从别国身上 “揩油”,或者说是要欺负别国了,这才是 “美国第一”的实在含义。这样的做法,杀鸡取卵,拿自己的国家信誉进行 “消费”,而且是 “透支”。其实是毁掉这个国家而已。看看以后的继任者会不会沿着这条不归路继续走下去。
作者: 易广白    时间: 2019-3-13 20:10
不点 发表于 2019-3-13 19:20
说的没错,有几次去自由市场买菜,本来也不经常去,只是偶然去了几次。结果你猜咋了?他们卖给我的价格, ...

去超市没有菜市场自由,而且不够丰富,人情味也少了许多,生活都少了乐趣,这又变成了“城市综合症”。
一些老人家坚持去菜市场,与奸商“斗智斗勇”,象俺们吗?
作者: 不点    时间: 2019-3-14 20:42
本帖最后由 不点 于 2019-3-16 16:44 编辑

为方便起见,新的文件系统,暂时就叫做 sefs 吧(意思是 simple and easy file system)。

文件系统的整体结构分两部分:引导区(含 super block 参数)+数据区。整个文件系统的空间,划分成很多簇,每簇的长度固定为 4K。就是说,无论物理扇区大小是 512 字节、2048 字节、还是 4096 字节,每簇都固定为 4096 字节(相当于 8 个 512 字节的小扇区)。第一簇的簇号是 0,作为引导区(含 super block 参数)。引导区也只占这一簇,剩下的都划归数据区。就是说,从簇号 1 开始,直到卷的结尾,就是数据区。FAT 表的位置是灵活的,它不是固定放在开头,而是可以放在任意一片连续的空间中。FAT 表的起始簇号和长度记录在 super block 参数中。根目录的起始簇号也记录在 super block 参数中。根目录的拥有者和权限等,以后再设计。根目录下有两个文件 /.bootblk 和 /.fattbl 分别用来访问引导区和 FAT 表(由 root 用户只读访问;root 用户也不能写)。今后如果需要的话,可以添加 Allocation bitmap,处理方式与 FAT 类似。

以下是 super block(引导扇区) 的初步设计(本帖将会不断修订完善)。

更动记录:2019-03-16 偏移 0E 处添加保留簇数(双字节整数)。保留簇也包括了引导簇在内,用于保存文件系统的一些关键的或辅助的信息。仍用 .bootblk 来表示它。

sefs Boot Sector(设计)
Offset
Size
Description
Comments
0x00
3
JumpBoot
EB ?? 90
0x03
8
FileSystemName
"SEFS"
0x0B
1
BytesPerSectorShift
Power of 2.
Minimum 9 (512 bytes per sector),
maximum 12 (4096 bytes per sector)
0x0C
1
SectorsPerClusterShift
Power of 2.
12 – BytesPerSectorShift, so cluster size is 4 KB
0x0D
1
DriveSelect
Extended INT 13h drive number; typically 0x80
0x0E
2
ReservedClusters
0x10
8
PartitionOffset
In sectors; if 0, shall be ignored
0x18
8
VolumeLength
Size of volume in sectors
0x20
4
FatCluster
FAT start cluster number. FAT must be contiguous
0x24
4
FatLength
In clusters.
0x28
4
Reserved? ClusterHeapOffset
0x2C
4
Reserved
? ClusterCount. 2^32-11 is the maximum number of clusters could be described
0x30
4
RootDirectoryCluster

0x34
4
Reserved? VolumeSerialNumber
0x38
2
Reserved
? FileSystemRevision, as MAJOR.minor, major revision is high byte, minor is low byte; currently 00.00
0x3A
2
Reserved? VolumeFlags * ↓
Offset
Size
Field
0
1
Reserved (no meaning)
1
1
VolumeDirty (0-clean, 1-dirty)
2
1
MediaFailure (0 – no failures reported or they already marked as BAD clusters) 1- some read/write operations failed)
3
1
ClearToZero (no meaning)
4
12
Reserved (no meaning)
0x3C
4
Reserved

0x40
446
BootCode

0x1FE
2
BootSignature
0xAA55
0x200
3584
Reserved



作者: 不点    时间: 2019-3-15 11:10
(sefs 设计,续上)FAT 就像一个普通文件那样,占据连续的簇号。Allocation bitmap 只是为了加快空闲空间的查找速度的,它处于辅助地位。Allocation bitmap 续尾在连续的 FAT 之后(续尾后,仍是连续的文件,它在根目录项中的文件名是 .fattbl)。Boot sector 中记录了 FAT length,因此,可以定位尾部的 Allocation bitmap 的位置。 在创建文件系统(格式化)时,首先要分配 FAT (连同 Allocation bitmap),通常放在数据区的最开头(就是紧接 boot 簇之后)。当文件系统(卷)需要动态调整其大小的时候,FAT(连同 Allocation bitmap)就可以调整到别的位置了(当然仍须保持连续)。接着要分配根目录。根目录项中的第一个有效条目,记录着根目录自己的拥有者、权限等信息(相应于 inode 结构里面的信息),当然,其中有一条信息是指示根目录自己的起始簇号(指向它现在的位置)。一般的目录文件的具体结构,以后再设计。但大致上可以确定,目录文件开头有个信息区域,指示该目录的一些属性。接着才是目录项的各个条目。安全起见,.bootblk 和 .fattbl 也可以放在一个子目录中(比如叫做 .fsstruct),子目录设置为不可进入,不可读写。
作者: 不点    时间: 2019-3-15 15:16
看看 kernel 里一般化的 inode 结构:
  1. /*
  2. * Keep mostly read-only and often accessed (especially for
  3. * the RCU path lookup and 'stat' data) fields at the beginning
  4. * of the 'struct inode'
  5. */
  6. struct inode {
  7.         umode_t                        i_mode;
  8.         unsigned short                i_opflags;
  9.         kuid_t                        i_uid;
  10.         kgid_t                        i_gid;
  11.         unsigned int                i_flags;

  12. #ifdef CONFIG_FS_POSIX_ACL
  13.         struct posix_acl        *i_acl;
  14.         struct posix_acl        *i_default_acl;
  15. #endif

  16.         const struct inode_operations        *i_op;
  17.         struct super_block        *i_sb;
  18.         struct address_space        *i_mapping;

  19. #ifdef CONFIG_SECURITY
  20.         void                        *i_security;
  21. #endif

  22.         /* Stat data, not accessed from path walking */
  23.         unsigned long                i_ino;
  24.         /*
  25.          * Filesystems may only read i_nlink directly.  They shall use the
  26.          * following functions for modification:
  27.          *
  28.          *    (set|clear|inc|drop)_nlink
  29.          *    inode_(inc|dec)_link_count
  30.          */
  31.         union {
  32.                 const unsigned int i_nlink;
  33.                 unsigned int __i_nlink;
  34.         };
  35.         dev_t                        i_rdev;
  36.         loff_t                        i_size;
  37.         struct timespec64        i_atime;
  38.         struct timespec64        i_mtime;
  39.         struct timespec64        i_ctime;
  40.         spinlock_t                i_lock;        /* i_blocks, i_bytes, maybe i_size */
  41.         unsigned short          i_bytes;
  42.         u8                        i_blkbits;
  43.         u8                        i_write_hint;
  44.         blkcnt_t                i_blocks;

  45. #ifdef __NEED_I_SIZE_ORDERED
  46.         seqcount_t                i_size_seqcount;
  47. #endif

  48.         /* Misc */
  49.         unsigned long                i_state;
  50.         struct rw_semaphore        i_rwsem;

  51.         unsigned long                dirtied_when;        /* jiffies of first dirtying */
  52.         unsigned long                dirtied_time_when;

  53.         struct hlist_node        i_hash;
  54.         struct list_head        i_io_list;        /* backing dev IO list */
  55. #ifdef CONFIG_CGROUP_WRITEBACK
  56.         struct bdi_writeback        *i_wb;                /* the associated cgroup wb */

  57.         /* foreign inode detection, see wbc_detach_inode() */
  58.         int                        i_wb_frn_winner;
  59.         u16                        i_wb_frn_avg_time;
  60.         u16                        i_wb_frn_history;
  61. #endif
  62.         struct list_head        i_lru;                /* inode LRU list */
  63.         struct list_head        i_sb_list;
  64.         struct list_head        i_wb_list;        /* backing dev writeback list */
  65.         union {
  66.                 struct hlist_head        i_dentry;
  67.                 struct rcu_head                i_rcu;
  68.         };
  69.         atomic64_t                i_version;
  70.         atomic_t                i_count;
  71.         atomic_t                i_dio_count;
  72.         atomic_t                i_writecount;
  73. #ifdef CONFIG_IMA
  74.         atomic_t                i_readcount; /* struct files open RO */
  75. #endif
  76.         const struct file_operations        *i_fop;        /* former ->i_op->default_file_ops */
  77.         struct file_lock_context        *i_flctx;
  78.         struct address_space        i_data;
  79.         struct list_head        i_devices;
  80.         union {
  81.                 struct pipe_inode_info        *i_pipe;
  82.                 struct block_device        *i_bdev;
  83.                 struct cdev                *i_cdev;
  84.                 char                        *i_link;
  85.                 unsigned                i_dir_seq;
  86.         };

  87.         __u32                        i_generation;

  88. #ifdef CONFIG_FSNOTIFY
  89.         __u32                        i_fsnotify_mask; /* all events this inode cares about */
  90.         struct fsnotify_mark_connector __rcu        *i_fsnotify_marks;
  91. #endif

  92. #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
  93.         struct fscrypt_info        *i_crypt_info;
  94. #endif

  95.         void                        *i_private; /* fs or device private pointer */
  96. } __randomize_layout;

复制代码

作者: 不点    时间: 2019-3-15 15:25
这是 ext4 的 inode:
  1. /*
  2. * Structure of an inode on the disk
  3. */
  4. struct ext4_inode {
  5.         __le16        i_mode;                /* File mode */
  6.         __le16        i_uid;                /* Low 16 bits of Owner Uid */
  7.         __le32        i_size_lo;        /* Size in bytes */
  8.         __le32        i_atime;        /* Access time */
  9.         __le32        i_ctime;        /* Inode Change time */
  10.         __le32        i_mtime;        /* Modification time */
  11.         __le32        i_dtime;        /* Deletion Time */
  12.         __le16        i_gid;                /* Low 16 bits of Group Id */
  13.         __le16        i_links_count;        /* Links count */
  14.         __le32        i_blocks_lo;        /* Blocks count */
  15.         __le32        i_flags;        /* File flags */
  16.         union {
  17.                 struct {
  18.                         __le32  l_i_version;
  19.                 } linux1;
  20.                 struct {
  21.                         __u32  h_i_translator;
  22.                 } hurd1;
  23.                 struct {
  24.                         __u32  m_i_reserved1;
  25.                 } masix1;
  26.         } osd1;                                /* OS dependent 1 */
  27.         __le32        i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
  28.         __le32        i_generation;        /* File version (for NFS) */
  29.         __le32        i_file_acl_lo;        /* File ACL */
  30.         __le32        i_size_high;
  31.         __le32        i_obso_faddr;        /* Obsoleted fragment address */
  32.         union {
  33.                 struct {
  34.                         __le16        l_i_blocks_high; /* were l_i_reserved1 */
  35.                         __le16        l_i_file_acl_high;
  36.                         __le16        l_i_uid_high;        /* these 2 fields */
  37.                         __le16        l_i_gid_high;        /* were reserved2[0] */
  38.                         __le16        l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */
  39.                         __le16        l_i_reserved;
  40.                 } linux2;
  41.                 struct {
  42.                         __le16        h_i_reserved1;        /* Obsoleted fragment number/size which are removed in ext4 */
  43.                         __u16        h_i_mode_high;
  44.                         __u16        h_i_uid_high;
  45.                         __u16        h_i_gid_high;
  46.                         __u32        h_i_author;
  47.                 } hurd2;
  48.                 struct {
  49.                         __le16        h_i_reserved1;        /* Obsoleted fragment number/size which are removed in ext4 */
  50.                         __le16        m_i_file_acl_high;
  51.                         __u32        m_i_reserved2[2];
  52.                 } masix2;
  53.         } osd2;                                /* OS dependent 2 */
  54.         __le16        i_extra_isize;
  55.         __le16        i_checksum_hi;        /* crc32c(uuid+inum+inode) BE */
  56.         __le32  i_ctime_extra;  /* extra Change time      (nsec << 2 | epoch) */
  57.         __le32  i_mtime_extra;  /* extra Modification time(nsec << 2 | epoch) */
  58.         __le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */
  59.         __le32  i_crtime;       /* File Creation time */
  60.         __le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
  61.         __le32  i_version_hi;        /* high 32 bits for 64-bit version */
  62.         __le32        i_projid;        /* Project ID */
  63. };
复制代码


作者: 不点    时间: 2019-3-15 17:58
先研究 ext4 的 inode 结构。

i_mode 是文件的权限模式,16 位。可是后面出现了 h_i_mode_high 也是 16 位。因此,把两者合并,就是 32 位的。Linux 中一般的 VFS 的 inode 中的 i_mode 是 umode_t 类型,即 unsigned short,它也是 16 位的。就是说,Linux 只用 16 位就够了。但别的操作系统(hurd)却使用了 32 位。所以,这里应该采用 32 位。

同理,i_uid 和 i_gid 都应该是 32 位值。而从 i_size_lo(32 位) 和 i_size_high (32 位)可知,文件长度应该是 64 位值。


  1.         __le32        i_atime;        /* Access time */
  2.         __le32        i_ctime;        /* Inode Change time */
  3.         __le32        i_mtime;        /* Modification time */
  4.         __le32        i_dtime;        /* Deletion Time */

  5.         __le32  i_ctime_extra;  /* extra Change time      (nsec << 2 | epoch) */
  6.         __le32  i_mtime_extra;  /* extra Modification time(nsec << 2 | epoch) */
  7.         __le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */
  8.         __le32  i_crtime;       /* File Creation time */
  9.         __le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
复制代码


上述这些“时间”,大部分都需要 64 位。只有 “删除时间”不重要,是 32 位的。

dtime 是删除时间。(<---- 它不重要,是 32 位值。其余几个是 64 位值。)
atime 是访问时间。
ctime 是 inode 发生变化的时间。
mtime 是修改时间。
crtime 是文件创建的时间。

在百度上搜,发现 crtime 是个较新的东西,以前只有 ctime,没有这个 crtime。它放在 ext4  inode 的结构的尾部,也说明它是后来才有的。有的地方把它叫做 birthtime(出生时间)。

那么,ctime 和 mtime 有什么差别呢?

mtime 是文件内容最后修改保存的时间。而 ctime 是文件的 inode 信息发生变化的时间,比如更改了 owner, group 或更改了权限位之类的,我理解,应该也包括更改了上述这些 time 吧。因此,只要内容更改了,ctime 也会更改(mtime 当然也变了)。但是,在文件内容未修改的情况下,mtime 就保持为旧的,而 ctime 有可能更新。

既然 “删除时间”不重要,那么,对等地,“创建时间”也不重要。就是说,只要粗略地知道它何时创建即可,没必要精确到毫秒级。创建和删除,就如一个人出生和死亡一样,都是一次性的。所以,这个时间属于常量,不会频繁变化,因此,没有必要精确到毫秒级。这样的话,就可节约 4 个字节。

i_links_count,是 16 位的,用于记录硬链接的个数。在 sefs 中不需要它,去掉它,可节约 2 个字节。

i_blocks_lo 是 32 位,l_i_blocks_high 是 16 位。合起来是 48 位,也就是 6 个字节。sefs 里面文件的块信息都记录在 FAT 表中,不需要知道有多少个块。所以,这 6 个字节可以节约出来。

i_flags 在 VFS 和 ext4 中都是 32 位值。不知道它够不够用。可以扩大到 64 位。

i_block 是 32 位整数数组,记录数据块信息。sefs 只需要一个 32 位的起始簇号即可,又节约了不少字节。

i_generation 是 32 位,在 VFS 中也有它。注释中写着 File version (for NFS),可能有用,就留着。

i_file_acl_lo;  是 32 位。l_i_file_acl_high 是 16 位。ACL 比较重要,但这个 48 位,有点变态。需要再看看相关资料。

i_extra_isize 是 16 位,与 inode 结构长度有关。在 sefs 中不需要它。
i_projid; /* Project ID */ 是个 32 位值,不知道有啥用。

作者: 不点    时间: 2019-3-16 14:21
https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html

The inode table entry is laid out in struct ext4_inode.

OffsetSizeNameDescription
0x0__le16i_modeFile mode. See the table i_mode below.
0x2__le16i_uidLower 16-bits of Owner UID.
0x4__le32i_size_loLower 32-bits of size in bytes.
0x8__le32i_atimeLast access time, in seconds since the epoch. However, if the EA_INODEinode flag is set, this inode stores an extended attribute value andthis field contains the checksum of the value.
0xC__le32i_ctimeLast inode change time, in seconds since the epoch. However, if theEA_INODE inode flag is set, this inode stores an extended attributevalue and this field contains the lower 32 bits of the attribute value’sreference count.
0x10__le32i_mtimeLast data modification time, in seconds since the epoch. However, if theEA_INODE inode flag is set, this inode stores an extended attributevalue and this field contains the number of the inode that owns theextended attribute.
0x14__le32i_dtimeDeletion Time, in seconds since the epoch.
0x18__le16i_gidLower 16-bits of GID.
0x1A__le16i_links_countHard link count. Normally, ext4 does not permit an inode to have more than 65,000 hard links. This applies to files as well as directories, which means that there cannot be more than 64,998 subdirectories in a directory (each subdirectory’s ‘..’ entry counts as a hard link, as does the ‘.’ entry in the directory itself). With the DIR_NLINK feature enabled, ext4 supports more than 64,998 subdirectories by setting this field to 1 to indicate that the number of hard links is not known.
0x1C__le32i_blocks_loLower 32-bits of “block” count. If the huge_file feature flag is not set on the filesystem, the file consumes i_blocks_lo 512-byte blocks on disk. If huge_file is set and EXT4_HUGE_FILE_FL is NOT set in inode.i_flags, then the file consumes i_blocks_lo + (i_blocks_hi<< 32) 512-byte blocks on disk. If huge_file is set and EXT4_HUGE_FILE_FL IS set in inode.i_flags, then this file consumes (i_blocks_lo + i_blocks_hi << 32) filesystem blocks on disk.
0x20__le32i_flagsInode flags. See the table i_flags below.
0x244 bytesi_osd1See the table i_osd1 for more details.
0x2860 bytesi_block[EXT4_N_BLOCKS=15]Block map or extent tree. See the section “The Contents of inode.i_block”.
0x64__le32i_generationFile version (for NFS).
0x68__le32i_file_acl_loLower 32-bits of extended attribute block. ACLs are of course one of many possible extended attributes; I think the name of this field is a result of the first use of extended attributes being for ACLs.
0x6C__le32i_size_high / i_dir_aclUpper 32-bits of file/directory size. In ext2/3 this field was named i_dir_acl, though it was usually set to zero and never used.
0x70__le32i_obso_faddr(Obsolete) fragment address.
0x7412 bytesi_osd2See the table i_osd2 for more details.
0x80__le16i_extra_isizeSize of this inode - 128. Alternately, the size of the extended inode fields beyond the original ext2 inode, including this field.
0x82__le16i_checksum_hiUpper 16-bits of the inode checksum.
0x84__le32i_ctime_extraExtra change time bits. This provides sub-second precision. See Inode Timestamps section.
0x88__le32i_mtime_extraExtra modification time bits. This provides sub-second precision.
0x8C__le32i_atime_extraExtra access time bits. This provides sub-second precision.
0x90__le32i_crtimeFile creation time, in seconds since the epoch.
0x94__le32i_crtime_extraExtra file creation time bits. This provides sub-second precision.
0x98__le32i_version_hiUpper 32-bits for version number.
0x9C__le32i_projidProject ID.

The i_mode value is a combination of the following flags:

ValueDescription
0x1S_IXOTH (Others may execute)
0x2S_IWOTH (Others may write)
0x4S_IROTH (Others may read)
0x8S_IXGRP (Group members may execute)
0x10S_IWGRP (Group members may write)
0x20S_IRGRP (Group members may read)
0x40S_IXUSR (Owner may execute)
0x80S_IWUSR (Owner may write)
0x100S_IRUSR (Owner may read)
0x200S_ISVTX (Sticky bit)
0x400S_ISGID (Set GID)
0x800S_ISUID (Set UID)
These are mutually-exclusive file types:
0x1000S_IFIFO (FIFO)
0x2000S_IFCHR (Character device)
0x4000S_IFDIR (Directory)
0x6000S_IFBLK (Block device)
0x8000S_IFREG (Regular file)
0xA000S_IFLNK (Symbolic link)
0xC000S_IFSOCK (Socket)

The i_flags field is a combination of these values:

ValueDescription
0x1This file requires secure deletion (EXT4_SECRM_FL). (not implemented)
0x2This file should be preserved, should undeletion be desired(EXT4_UNRM_FL). (not implemented)
0x4File is compressed (EXT4_COMPR_FL). (not really implemented)
0x8All writes to the file must be synchronous (EXT4_SYNC_FL).
0x10File is immutable (EXT4_IMMUTABLE_FL).
0x20File can only be appended (EXT4_APPEND_FL).
0x40The dump(1) utility should not dump this file (EXT4_NODUMP_FL).
0x80Do not update access time (EXT4_NOATIME_FL).
0x100Dirty compressed file (EXT4_DIRTY_FL). (not used)
0x200File has one or more compressed clusters (EXT4_COMPRBLK_FL). (not used)
0x400Do not compress file (EXT4_NOCOMPR_FL). (not used)
0x800Encrypted inode (EXT4_ENCRYPT_FL). This bit value previously was EXT4_ECOMPR_FL (compression error), which was never used.
0x1000Directory has hashed indexes (EXT4_INDEX_FL).
0x2000AFS magic directory (EXT4_IMAGIC_FL).
0x4000File data must always be written through the journal(EXT4_JOURNAL_DATA_FL).
0x8000File tail should not be merged (EXT4_NOTAIL_FL). (not used by ext4)
0x10000All directory entry data should be written synchronously (see dirsync) (EXT4_DIRSYNC_FL).
0x20000Top of directory hierarchy (EXT4_TOPDIR_FL).
0x40000This is a huge file (EXT4_HUGE_FILE_FL).
0x80000Inode uses extents (EXT4_EXTENTS_FL).
0x200000Inode stores a large extended attribute value in its data blocks(EXT4_EA_INODE_FL).
0x400000This file has blocks allocated past EOF (EXT4_EOFBLOCKS_FL).(deprecated)
0x01000000Inode is a snapshot (EXT4_SNAPFILE_FL). (not in mainline)
0x04000000Snapshot is being deleted (EXT4_SNAPFILE_DELETED_FL). (not inmainline)
0x08000000Snapshot shrink has completed (EXT4_SNAPFILE_SHRUNK_FL). (not inmainline)
0x10000000Inode has inline data (EXT4_INLINE_DATA_FL).
0x20000000Create children with the same project ID (EXT4_PROJINHERIT_FL).
0x80000000Reserved for ext4 library (EXT4_RESERVED_FL).
Aggregate flags:
0x4BDFFFUser-visible flags.
0x4B80FFUser-modifiable flags. Note that while EXT4_JOURNAL_DATA_FL andEXT4_EXTENTS_FL can be set with setattr, they are not in the kernel’s EXT4_FL_USER_MODIFIABLE mask, since it needs to handle the setting of these flags in a special manner and they are masked out of the set of flags that are saved directly to i_flags.

看到 i_flags 的全部 32 位被用光了。因此,用 64 位便于将来的扩展。在 sefs 中,应该有一个控制标志,用于强制文件连续存放(.fattbl),另有一个信息标志,表示文件已经是连续存放。还需要一个标志,强制文件占据的簇号不能更改(.bootblk)。同理,也有标志禁止改变文件长度,以及禁止读取、禁止写入(.bootblk,.fattbl),诸如此类,即使是 root 用户也无法操作。



另外,原网页对 64 位的时间戳印有详细解释,在附加的 32 位中,大部分的位都用于精确到纳秒级,只有少数被用于支持更多年份——最大只支持到 2446 年,可惜了。关于文件的时戳,几十年来一直使用的都是精确到秒,没有什么问题。感觉精确到纳秒级,没有什么意义。因此,sefs 把全部 64 位,都用于秒(像传统一样),不再对时间戳印进行复杂的格式设计。




作者: 不点    时间: 2019-3-18 10:22
本帖最后由 不点 于 2019-3-22 06:07 编辑

sefs 目录文件整体结构设计。

目录文件在其开头有一个信息区域,记录该目录下文件的统计信息。该目录下全部文件名的 hash 值也放在这里,hash 值取 32 位整数。信息区域中有一个 32 位变量指示本次所采用的 hash 算法。各种 hash 算法由驱动程序来定义。hash 值与文件的目录项的偏移相对应,找到了 hash 值就知道了目录项的位置。hash 值必须排序。但并非所有的文件名都有 hash 值。操作系统(或驱动程序)在空闲时为各目录下的文件名添加 hash 项。信息区域有一个 32 位变量,指示该目录下有多少个 hash 值。当然也有一个 32 位变量记录该目录下的文件总数。删除文件时,hash 项不一定删除,操作系统(或驱动程序)在空闲时会处理好。操作系统(或驱动程序)会尽量为该目录选用碰撞较少的 hash 算法。总碰撞数以及最大碰撞项的碰撞数也记录在信息区。初始时,可以为信息区域分配一簇。目录项从一个新的簇开始。驱动程序在更新信息区域时,顺便会保证该目录文件是连续存放的。

目录文件至少占用 2 个簇(一个信息簇和一个目录项簇)。在 FAT 表中,目录文件的最后一簇的指针指向该目录文件的起始簇(形成一个簇链循环)。

普通文件与此不同。普通文件的最后一簇,如果是个零头(即,不是刚好填满一个完整簇),它有可能被操作系统(或驱动程序)动态调整到目录项中。在 FAT 表中,普通文件的最后一簇的指针,指向该文件所在目录的目录文件起始簇或目录文件结束簇。当普通文件的最后一个不完整簇被调整到目录项中时,需要从目录项的数据结构中找到最后一簇的数据,此时 FAT 簇链的尾端,其实是最后一个完整簇,它所在位置的指针,指向目录文件的起始簇,需要从起始簇开始查找目录项,再由目录项查找零头数据。当普通文件的最后一簇(不管是否为完整簇)仍然保持在簇链尾端时,就不需要在目录项中保存数据了,此时 FAT 簇链的尾端指向目录文件结束簇。

在 FAT 表中,目录文件的簇链构成一个循环圈,可以想象成一个圆圈。普通文件是一个簇链在尾部又带上一个循环圈(即,该普通文件所在目录的循环圈),可以想象成一条线段连接一个圆圈。所以,仅从 FAT 链的拓扑结构,就可以区分普通文件和目录文件。

目录文件的循环链中,有个最小的簇号和最大的簇号。最小的簇号,一定是目录文件的起始簇,最大的簇号,一定是目录的结束簇。位于起始簇和结束簇之间的其它簇,也都是按顺序排列的,不可以出现逆转。也就是说,只有最后一簇才会发生折转(指向前面较小的簇号),其它簇都是指向较大的簇号。由于目录文件至少有 2 个簇,所以也不会出现指向自己的簇(即,圆圈上只有一个簇的情况)。普通文件的链条部分,也不可以出现折转。只在最后指向循环圈时才可能有折转的发生。指向循环圈的那个簇,就是普通文件本身的最后一个有效簇号,而循环圈是由其所在目录的全部簇构成的。

新创建的文件,或者新修改的文件,都会把文件内容全部放在簇链中(不会把尾部零头调整到目录项中),这便于在短期内频繁修改文件。操作系统(或驱动程序)会按照某种策略,在空闲时,把长期无修改而且有零头的文件进行调整。

以上这种拓扑结构,有利于从 FAT 表的链条找到文件所在的目录项。如果簇链的尾端用一个简单的 0xFFFFFFFF 来结束,那就不知道文件的其它信息了,比如就连文件的精确长度都无法知道。操作系统在读文件的时候,不会用到这最后一簇的指针,因为读到最后一簇就读完了,没有后续簇了。零头尾巴早都在读目录项的时候就已经读到内存里了。

作者: 不点    时间: 2019-3-19 18:09
本帖最后由 不点 于 2019-4-8 15:12 编辑

sefs 目录项结构设计(待完善)
OffsetSizeNameDescription
0x0__le32modeValue    Description
0x1       Owner may execute
0x2       Owner may read
0x4       Owner may append
0x8       Owner may erase
0x10      Reserved
0x20      Reserved
0x40      Reserved
0x80      Reserved
0x100     Group may execute
0x200     Group may read
0x400     Group may append
0x800     Group may erase
0x1000      Reserved
0x2000      Reserved
0x4000      Reserved
0x8000      Reserved
0x10000     Others may execute
0x20000     Others may read
0x40000     Others may append
0x80000     Others may erase
0x100000      Reserved
0x200000      Reserved
0x400000      Reserved
0x800000      Reserved
0x1000000   Reserved
0x2000000   Compatibility (Sticky bit)
0x4000000   Compatibility (Set GID)
0x8000000   Compatibility (Set UID)
  These are mutually-exclusive file types:
0x10000000    FIFO
0x20000000    Character device
0x40000000    Directory
0x60000000    Block device
0x80000000    Regular file
0xA0000000    Symbolic link
0xC0000000    Socket

0x4__le32uidOwner UID.
0x8__le64sizeFile size in bytes.
0x10__le32mtimeLast data modification time, in seconds since volume creation.
0x14__le32ctimeLast attribute change time, in seconds since volume creation.
0x18__le32atimeLast access time, in seconds since volume creation.
0x1C__le32reserved1
0x20__le32checksum
0x24__le32gidGID.
0x28__le32cluster_1st
Data chain starting cluster number
0x2C__le32reserved2
0x30__le64flags?控制位,更新 atime。
?控制位,文件 tail 在簇链中,不调整到目录项中。
?控制位,簇链必须连续。
?状态位,簇链已连续。
?状态位,文件被标记为已删除。新的进程不再处理该目录项,但文件的数据尚未被删除,可能有进程在使用该文件的数据。操作系统会在合适的时候删除该文件的内容以及该目录项。
0x38__le16rec_lenLength of this directory entry. Must be 16 byte aligned.
0x3A__le16ext_lenExtended attribute length. 0 if no extended attributes.
0x3C__le16tail_lenData tail is allocated inside the directory entry. If it is 0, then there is no tail or the tail is allocated normally in the cluster chain.
0x3E__le16name_lenLength of the file name, including the ending NULL.
0x40char[]nameFile name. ASCIIZ.

char[]
Data tail in Last block if tail_len != 0. Data tail immediately follows the name.

char[]
Extended attribute (ACL, SELinux, etc.) if exists. Extended attribute is always located at the end of the entry. So it starts at offset (rec_len - ext_len).


作者: 不点    时间: 2019-3-21 17:02
本帖最后由 不点 于 2019-3-21 17:14 编辑

搜到下面这个讨论,关于 selinux 的,感觉说到点子上了。感慨一下:安全只能靠自己。靠别人,年都过差(chà)了。一个简单的道理,装了一堆杀毒软件,以为安全了,殊不知这些全是流氓软件,不会有丝毫的安全,只会有后门。不用到处寻找木马,它们就是特洛伊木马。像 Linux 那样全是开源的,都无法保证安全,更不用说闭源的东西了。不装杀毒软件,只要自己平时小心一点,不下载恶意软件,系统反而还能活得久一些。在另一个地方看到有人说,主流 Linux 发行版全都有后门。想想也是这个理啊!世界这么大,开发人员又这么多,怎可能保证里面全都是干净的?看来以后也只能把 Linux 当成另一个 Windows 来用了,不要抱过高的期望。就是说,很无奈的。与其它开源操作系统相比,Linux 这么好用,肯定被各大流氓软件制造商盯上,他们肯定会渗透进去,把 Linux 变成像 Windows 一样的跑马场。由于 Linux 好用(跟用户摆脱不了 Windows 是一个道理,皆是因为好用),Linux 的用户们就无法摆脱 Linux,无法转移到别的“更安全的”系统上(即便存在的话)。



https://www.oschina.net/question/23734_93597
selinux真那么安全吗?
mallon 发布于 2013/03/17 22:55

什么selinux、polkit那套东西,且不说有美国国防部参与开发,算法上给你弄几个后门了,就算是没有后门,我也不信“越复杂越安全”这个道理,弄到root权限还不是一样完蛋?反之简单的linux权限模型没有root权限不也一样安全?

我一直信奉“简单”的原则,近些年来搞Linux的人脑子都有些秀逗了!

七液 2013/03/26 20:48
就和编码一样,写的越简单的代码查找bug和调试的难度越低,凡事一目了然,相同的原理挂在安全上,越是复杂,吃饱了撑的认为用户都是安全高手把安全规则都交给用户来处理的越容易出问题。先不说用户是否懂各种规则如何设定,复杂的系统查找漏洞和后门的难度也高。调试和找bug都不容易,寻找那些刻意留下来的就更难了,现在中国开始越来越重视商业间谍了(三一重工的破事就最好体现了,搞得人家都迁都北京了)但是法律还是个灰色区域,selinux这种专业人士玩起来都很麻烦,您指望一般公司内部的网管玩得起来不?再说我要是渗透的话,肯定先把网管贿赂了(一般网管都是比较不太重视的职业,公司肯定不高--以此延伸,机房的网管---哈哈我什么都没说)





作者: 不点    时间: 2019-3-22 05:30
本帖最后由 不点 于 2019-4-5 08:28 编辑

摘录 chattr 命令修改文件属性的一些说明片段:

这些属性共有以下8种:
A:即Atime,告诉系统不要修改对这个文件的最后访问时间。
S:即Sync,一旦应用程序对这个文件执行了写操作,使系统立刻把修改的结果写到磁盘。
a:即Append Only,系统只允许在这个文件之后追加数据,不允许任何进程覆盖或截断这个文件。如果目录具有这个属性,系统将只允许在这个目录下建立和修改文件,而不允许删除任何文件。
b:不更新文件或目录的最后存取时间。
c:将文件或目录压缩后存放。
d:当dump程序执行时,该文件或目录不会被dump备份。
D:检查压缩文件中的错误。
i:即Immutable,系统不允许对这个文件进行任何的修改。如果目录具有这个属性,那么任何的进程只能修改目录之下的文件,不允许建立和删除文件。
s:彻底删除文件,不可恢复,因为是从磁盘上删除,然后用0填充文件所在区域。
u:当一个应用程序请求删除这个文件,系统会保留其数据块以便以后能够恢复删除这个文件,用来防止意外删除文件或目录。
t:文件系统支持尾部合并(tail-merging)。
X:可以直接访问压缩文件的内容。

这些属性,本质上与文件的 chmod 属性是类似的,但却需要一条新的命令才能操作。这暴露出当初 rwx 权限的设计太过于粗糙,不够应用。于是没办法,只好打补丁。chattr 是一种补丁,ACL 是一种补丁,selinux 又是一种补丁,还有别的五花八门的补丁,可以说,补丁打不完了。目前 Linux 在应用层的软件已经很丰富了,这是非常不容易的。但在最擅长的安全领域却不断暴露出不安全的问题,似乎有些奇怪。我们常说,干任何事,安全第一。而在这里,安全被排在并不优先的位置了。需要明确的是,即便没有任何权限设置,也不会对应用层造成太大的问题。Windows 靠易用性打天下,并未依靠安全,至少当初是这样。那么,应用层做好之后,安全问题就摆上了桌面,最终还是得解决安全问题。该从底层彻底改造安全模型了。

补充:考察上述 immutable 参数的设计。它的描述是这样的:“系统不允许对文件进行任何修改,如果是目录,不允许增删文件。”——这不就相当于没有 “写”(w)权限吗?只不过连 root 用户也不允许写罢了。在 root 用户不会被攻陷的前提下,这个参数差不多应该算是多余的吧?只要 root 用户把文件设置为只有自己可以写而其他人不可以写,这就达到了同样的目的(当然不完全一样,因为 root 用户自己能写入)。况且,严格来说,仍然无法限制 root 用户写入,因为 root 用户可以首先去掉 immutable 属性,然后再写入文件。

另一个参数指示 dump 备份工具不备份此文件(或目录)——就这个小小的、完全是应用层的目的,都要浪费文件系统中的一个控制逻辑,感觉好无聊啊!怪不得文件系统和操作系统都搞得那么庞大和复杂——猜猜看——复杂了、混乱了,是不是就方便隐藏后门了?


作者: 不点    时间: 2019-3-22 18:17
搜到这样的问答:
Windows 7 中 Administrator 和 SYSTEM 账户权限有什么区别

最高权限账户应该是虚拟账户:TrustedInstaller,拥有最高磁盘访问权限。Administrator 和 SYSTEM 都没有这么高权限,那么这两个账户单从权限上来说,有什么区别?

你好朋友,这两个用户在权限上的区别就是,administrator 是管理员用户,一般你平时运行的程序都是以这个权限身份运行的,你平时安装软件什么什么的、修改系统设置都是以这个权限操作的,system 权限是系统自己的权限,任务管理器里面只要是以 system 这个用户名运行的程序都是系统本身的程序,比如任务管理器里面的 winlogon.exe、svchost.exe、alg.exe 这些进程等等,而不是你运行的程序,像什么 QQ.exe、thunder.exe 这些了,这些都是用户运行的程序,还有就是,注册表里面某些地方只有系统自己可以访问,你的用户不能访问,就是 system 比别的管理员用户权限大的关系,另外 win7 系统我不了解。

从上述问答中可以得到这样一些信息:TrustedInstaller 权限高于 system,而 system 又高于 administrator。但不知道上述问答的内容是否权威、是否准确。从另外一些地方可以知道,只要有 administrator 权限,就可以获得 system 以及 TrustedInstaller 权限。那么,是否可以理解为三个权限是相同的呢?


不管怎么说,Windows 采用不同的管理级别,还是有一定的参考价值的。


作者: gnuxwy    时间: 2019-3-24 22:45
大师的sefs文件系统设计好了,还要考虑源码实现,工作量不少。。。
linus本人也搞了几文件系统,比如他曾经为闪存设计过yafs文件系统。如果不点大师有兴趣,可以找源码参考下的。。。

作者: 不点    时间: 2019-3-24 23:20
gnuxwy 发表于 2019-3-24 22:45
大师的sefs文件系统设计好了,还要考虑源码实现,工作量不少。。。
linus本人也搞了几文件系统,比如他曾 ...

代码其实不难实现,抄抄改改就有了。

关键是(我发现)设计一个文件系统容易,但设计一个操作系统,比较麻烦。


我的意思是说,应该把 Linux 的权限处理部分进行大的改造,究竟如何进行,这个设计的工作量很大。操作系统的权限模型确定了以后,这里的文件系统的设计也就确定了。所以,这个文件系统的设计,暂时搁置起来。


简单说,Linux 的 root 用户权限太大,防范攻击的措施很脆弱,目前的
ACL 和 SELINUX 都不是合适的设计。


我是看到 ext4 的文档里面有 ACL 和 SELINUX 字样,就在百度里面搜,
这样才知道了相关知识。学完之后,觉得这些设计都有很大的问题。
我感觉设计者可能不想从头大搞,所以就采取了 “补丁、再补丁” 的办法。
但是,系统复杂了以后,更不可能安全了,因为可能的漏洞会更多,
且不说后门了。


即便作为桌面,安全性差,也是不行的。服务器当然就更必须保证安全了。
如果没有安全性的话,说实话,我也不需要 Linux 桌面(服务器就更不需要了)。
正是因为对 Windows、Android 跑马场的极度不满,才选择了 Linux。


Linux 这么多年发展出的桌面应用非常丰富,这是难度最高的事情。


其它开源系统要想发展出这么完善的应用,非常困难,不是一朝一夕的事。


相比之下,改造权限模型,工作量就不那么大了。但要把它设计好,
也没那么容易。这些天都在想这个问题。
目前还没有构思出一个完整的解决方案。







作者: 不点    时间: 2019-3-25 11:31
本帖最后由 不点 于 2019-3-25 16:18 编辑

前面提到过,无论创新也好,发展也好,都是权衡。创新和发展,都要有基础,要基于现有的一些东西。同时也要有否定,而不是完全被现有的东西捆住了手脚。就是说,既不全盘肯定,也不全盘否定。其实我也知道有些开源项目是连操作系统都从头做起的,并不以 Linux 为基础。我觉得,那可能动作太大了吧?底层系统的设计,对于懂的人来说,或许不难。但困难的是,如何让现有的应用层软件都搬过去?如果操作系统底层重新设计之后又能简单移植现有的应用软件,那当然是完全重新设计操作系统更好了。如果做不到,那么还是应该以现有的操作系统为基础,进行改良,而不是全部推倒重来。

接下来会有不少思维的片段。这些片段会反映对这一技术问题的构思过程,起初可能会有很多错误,但随着时间的推移,应该会逐步完善的。

首先考虑这样一个问题:root 权限太大。简单取缔 root 权限的话,管理起来就没有手段了。但 root 平时不参加管理的时候,躺在那里等待黑客用字典进行穷举式攻击(或者其它各类攻击),也不是一件好事。因此考虑,分散 root 的权力,把 root 的管理工作分给不同的管理员。普通管理员没有什么特权,就跟普通用户一样。所以,它们被攻陷以后,系统只会有部分损失,而不会全部瘫痪。root 权限仍然保留,但平时处于未激活的状态。激活 root 的过程非常严格,只有一个用户能够激活 root。这个用户是谁,别人不知道,只有安装系统的人知道。而且,这个用户除了能够激活 root 以外,别的权限几乎都没有,比如说,他不能添加删除用户,不能删除系统文件,也不能删除其它用户的文件。即使进入了这个用户,也不能轻易激活 root,需要用不对称密钥的反复测试,通过之后才激活 root。

系统设计成在平时无需 root 权限即可正常运行。大部分系统进程都是以非 root 用户的身份运行的。那些需要 root 权限的情况,是很罕见的。所以,平时可以把 root 权限屏蔽掉。系统中保存了 root 以及下属的其它管理员的不对称密钥(公钥)。对这些用户的登录验证很严格。登录者自己所用的客户端操作系统必须十分安全,保证不会泄漏自己的私钥。

激活 root 之前,要首先登入负责启动系统服务的管理员账户,停止一切不必要的服务,防止有其它用户也登入系统。登入进程管理的账户,把所有不太信任的进程都干掉。然后进入账户管理的账户,添加一个秘密账户,此账户就是唯一能够用来激活 root 权限的账户。系统中早已保存了 root 的密钥和秘密账户的密钥,两个身份都得认证成功,此时,内核才激活 root 权限。然后添加并登入 root 账户,进行维护操作。完成后,删除秘密账户和 root 账户,重新禁止内核里的 root 权限。

作者: gnuxwy    时间: 2019-3-25 22:47
近年新出现了一个用rust语言写的新操作系统redox,就氏打算从底层开始全部另搞一套的做法。
引导用coreboot,编译噐用llvm,c库自已重新写个relibc。。。

也氏用尛内核结构的,不知这货与gnu的内核hurd相比如何,再等十年再看能否成气侯吧。。。

google不满足安卓的成功,可能也有摆脱linux内核制约考虑,也在打算另起炉灶自已搞个新系统,多等等看吧。。。

作者: 不点    时间: 2019-3-26 18:10
gnuxwy 发表于 2019-3-25 22:47
近年新出现了一个用rust语言写的新操作系统redox,就氏打算从底层开始全部另搞一套的做法。
引导用coreboo ...

非常好,那都是了不起的。不过我在想另一个问题。开源的结果究竟会是怎样的?

开源里面可能也是参差不齐的,有特别优秀的,有一般的,有差的。倘若里面混有后门,恐怕也不容易把它揪出来。任何一个开源的实例都可能存在这样的问题。至于说究竟哪个 “好”,那是没办法说清楚的。只能说,看各人自己的水平以及缘分了。

当今世界正在发生变化,中国正处于变化的核心。人们开创出多个操作系统,更能体现多元化的发展理念。是的,我们的目光不能仅仅停留在某一片小小的天地(比如 Unix、Linux),应该有更加久远的透射。

有一次我偶尔去查看了一下 Unicode 字符在 65536 之外的部分,我很惊讶,那么多的汉字,我连一个都不认识。我们的祖先怎会有如此强大的造字能力?以至于当时造出的字,后人在几千年里都用不完!这就是跨时代的透射力!那些“扩展字符”都需要 4 个 UTF-8 的字节才能表示。我在 loongson 制作的 startOS 的终端命令行下,居然可以显示这些 “扩展汉字”(打印出对应的 4 个 UTF-8 字节,就打印出了一个扩展汉字),浏览器就更是可以显示了。一个人的生命是有限的,要在有限的生命中,实现无限的价值,这才是生命的意义。尤其是对于从万年古老文明走过来的中国人来说,更是如此。

作者: 不点    时间: 2019-3-26 18:29
嗯,谢谢提醒。我意识到了,操作系统可以千变万化,而文件系统并不因操作系统的变化而变化。所以,设计一个带有某种理念(比如 simple & easy)的文件系统,仍然是重要的。它可以超越具体的某个操作系统而成为一般性的存在。
作者: 不点    时间: 2019-3-26 18:57
继续探讨 Linux 权限相关问题。

suid —— 是个提权的途径。为什么不允许自己把文件的拥有者无偿赠送给别人?我想,那大概就是因为这个 suid 了。一个用户先设置 suid,然后把拥有者改成别人,这就突破别人的防盗门了。因此之故,才不允许自己把拥有者的权力(免费)赠送给别人。

然而设想一下,假如取缔 suid 之类的设计,这样一来,就完全可以把自己的拥有权让给别人,不再有麻烦了。

一个管理员,负责创建账户。他自己是普通账户,不是 root 账户。他有权在 /home 里面创建文件夹。

他创建的文件夹,拥有权是他自己。但是,他得把拥有权转交给目标用户,否则,他就没有完成 “创建账户”的任务。因此,一个合乎逻辑的权限模型就是,让任何用户都可以把自己对于文件或文件夹的拥有权转让给别人。显然,这样做的话,那就应该取缔 suid 之类的东西了。

提权的途径太多,是隐患的根源。倘若只有一个系统调用才能提权,那就可以堵住很多后门了。

作者: 不点    时间: 2019-3-27 18:37
sgid 与 suid 存在类似的问题,不再赘述。

sticky bit 也有问题。同一个文件夹底下,有删除权限的人,可不可以删除别人的文件?默认情况下,是允许删除别人的文件的。而在设置 sticky bit 后,才不允许删除别人的文件。

假如我们把这个 sticky bit 的动作当作默认的操作,是不是更合理一点?我们干脆节省这么一个逻辑电路,取消 sticky bit 的使用,让所有的文件夹都执行这一操作,即,任何人都不能删除别人的文件(除非对这个文件有写权限)。

是啊,这又引出另一个问题:普通用户自己的文件夹底下有别人的文件,比如有 root 账户的文件。按照目前的权限逻辑,不管三七二十一,咔嚓就干掉了 root 的文件。你对 root 属主的文件不可读写,却能删除,这样是不是也不怎么合理啊?这与人类生活的常识不相符,那么初学者学用这个奇葩逻辑就得费工夫,不自然。

合理一点的,可以这样设计:要想删除一个文件,需要满足两个条件。第一,你对该文件有写的权限。第二,你对该文件所在的目录有写权限。两者同时满足,才能删除文件。而且这是充分必要条件,只要满足这两条(不需要额外再增加其它限制,比如 sticky 啥的),就能删除文件。法律条文简单,没有例外情况,大家是平等的,都来执行,那就 OK。如果法律条文搞得复杂,那么可以钻空子的地方就多,维护起来难度就大。

作者: 2013olly    时间: 2019-3-28 15:33
不点 发表于 2019-3-26 18:57
继续探讨 Linux 权限相关问题。

suid —— 是个提权的途径。为什么不允许自己把文件的拥有者无偿赠送给 ...

就一个提权占用一个系统调用是不是太浪费了?

我觉得可以使用进程通信等手段解决,反正init进程肯定是在系统里而且以最高权限运行的,如果其他进程需要提权就直接发送给init,init判断权限合格后直接帮他做了,就不需要专门开个api来提权了
作者: 不点    时间: 2019-3-28 18:49
2013olly 发表于 2019-3-28 15:33
就一个提权占用一个系统调用是不是太浪费了?

我觉得可以使用进程通信等手段解决,反正init进程肯定是 ...

不错的思路。但是,那样的话,init 的压力就大了。感觉还是让内核承担这样的风险比较可靠。

提权这种操作,无论给谁都不放心——给 su 不放心,给 passwd 不放心。

只有给内核,让内核开发团队来维护,这才能放心。

作者: 不点    时间: 2019-3-28 21:18
回到文件系统的讨论。时间戳印。

计算了一下,64 位的秒数,可以达到几千亿年,到太阳系灭亡时,都还绰绰有余。32 位的秒数,可以表示 136 年。跨度 100 多年,也基本够用了。所以,平时用 32 位的时间,也就可以满足需要了。用一个 “基准时间” 来作为一切时间的基数,这个基准时间是 64 位的。基准时间放在哪里?它可以放在文件系统的 super block 里面(或者是 super block 之后的保留区里面)。就是说,文件系统格式化时的时间,就可以作为基准时间,它是 64 位的,可以用到太阳系毁灭时。而每个文件的时间戳印,都是相对于文件系统的基准时间的,采用 32 位,能持续使用 100 多年,足够我们大多数人一生享用了,甚至还没等 100 年过完,这存储介质早坏掉了,该换新了。

作者: 不点    时间: 2019-3-30 07:29
今天又对文件的 “写” 权限进行了 “权衡式” 思考。权衡的结果,是对目前的 “写” 权限 (w)进行 “一分为二” 的划分——分为 “擦除”(erase) 和 “增补” (append)两种。

对于普通文件来说,“擦除” 权的含义是,可以 “覆盖式” 地改动文件的现有字节数据,也可以删除文件的现有字节数据。如果一个人只有 “擦除” 权而无 “增补” 权,那么他就不能增加文件长度,只能保持或减小文件长度。而 “增补” 权的含义是,可以为文件追加字节,让文件变长。如果一个人只有 “增补” 权而无 “擦除” 权,那么他不能改写文件原有的字节数据(既不能删除,也不能覆盖)。如果一个人对某个文件既有 “擦除” 权,又有 “增补” 权,那么他就对该文件拥有了完整的 “写” (w)权限。如果一个人对某个文件既无 “擦除” 权,又无 “增补” 权,那么就相当于没有 “写” (w)权限。

对于目录来说,“擦除” 权的含义是,可以 “更名” 现有文件,也可以删除现有文件。如果一个人只有 “擦除” 权而无 “增补” 权,那么他就不能增加该目录下的文件个数,只能保持或减小文件个数。而 “增补” 权的含义是,可以在该目录下创建新文件,增加文件个数。如果一个人只有 “增补” 权而无 “擦除” 权,那么他就不能删除或改名该目录下原有的文件。如果一个人对某个目录既有 “擦除” 权,又有 “增补” 权,那么他就对该目录拥有了完整的 “写” (w)权限。如果一个人对某个目录既无 “擦除” 权,又无 “增补” 权,那么就相当于没有 “写” (w)权限。

你对某个目录拥有 “擦除” 权,并不能保证你一定可以删除或更名该目录下的某个文件,而仅仅是提供了删除或更名它的可能性。到底是否能够删除或更名,还要看你对那个文件是否拥有 “擦除” 权。


同理,你对某个文件拥有 “擦除” 权,并不能保证你一定可以删除该文件或覆盖该文件的字节数据,而仅仅是提供了删除或覆盖的可能性。到底是否能够删除或覆盖,还要看你对该文件所在的目录是否拥有 “擦除” 权。


作者: 不点    时间: 2019-3-30 13:12
本帖最后由 不点 于 2019-3-30 14:43 编辑

把 w 权限分拆以后,就要多占用一个 mode 位了。因此,需要设计新的模式。以下是初步设计,并与旧的 mode 进行对比:

【更新】把不太容易变动的 x(可执行) 和 r (可读)调整到低位。append 也不容易变动,因此也放在低位。erase 将来有可能被进一步分拆,因此,放在较高位,同时又保留了最高的 4 位,用于将来可能的扩展。每组权限占用一个字节。owner 一组的存在更稳定(不容易被取缔),因此调整到低端。group 一组放在中间,假如它将来被某个新的(简化式)操作系统所取缔,它的一些低位就可以被 owner 一组使用。


Old file mode
New file mode
  
Value    Description
0x1       Others may execute
0x2       Others may write
0x4       Others may read
0x8       Group may execute
0x10      Group may write
0x20      Group may read
0x40      Owner may execute
0x80      Owner may write
0x100     Owner may read
0x200     Sticky bit
0x400     Set GID
0x800     Set UID
  These are mutually-exclusive file types:
0x1000    FIFO
0x2000    Character device
0x4000    Directory
0x6000    Block device
0x8000    Regular file
0xA000    Symbolic link
0xC000    Socket
  Higher 16-bits - Reserved
  
Value    Description
0x1       Owner may execute
0x2       Owner may read
0x4       Owner may append
0x8       Owner may erase
0x10      Reserved
0x20      Reserved
0x40      Reserved
0x80      Reserved

0x100     Group may execute
0x200     Group may read
0x400     Group may append
0x800     Group may erase
0x1000      Reserved
0x2000      Reserved
0x4000      Reserved
0x8000      Reserved

0x10000     Others may execute
0x20000     Others may read
0x40000     Others may append
0x80000     Others may erase
0x100000      Reserved
0x200000      Reserved
0x400000      Reserved
0x800000      Reserved


0x1000000   Reserved
0x2000000   Compatibility
(Sticky bit)
0x4000000   Compatibility (Set GID)
0x8000000   Compatibility (Set UID)
  These are mutually-exclusive file types:
0x10000000    FIFO
0x20000000    Character device
0x40000000    Directory
0x60000000    Block device
0x80000000    Regular file
0xA0000000    Symbolic link
0xC0000000    Socket



作者: 不点    时间: 2019-3-30 19:29
回过头来再考察一下 ext4 的 inode 结构。原始的 ext2 的 inode 只有 128 字节,其中有很多是未使用的。到了 ext3,仍然是 128 字节,只不过使用了 ext2 并未使用的一些字段。

假如(仅仅是假如),从 ext3 到 ext4 是一个逐步复杂化的 “恶意” 过程的话,那么,原始的 ext2 的结构,可以认为是比较干净的。有人可能会说:累不累啊?这么疑神疑鬼的?——不累,而且也不是有病(那些胆怯的、不敢怀疑,才是有病)。要是给自己的思维事先划定 “禁区”,那你的思维就固化了。谁值得你绝对相信?哦,那是你的事,我当然不得而知。但我认为,没有一个人值得我绝对相信(就连我自己,我都不能绝对相信,因为我知道我犯错误的次数也是很多的)。即使是伟人,也不值得我 100% 信任他。好的,以上是为 “怀疑论” 做哲学铺垫,下面就可以肆无忌惮地尽情怀疑了。

先看 ext4 的位于 128 字节以后的扩展部分。它增添的内容如下:checksum 的高 16 位部分,若干个时间戳印的高位部分,inode 版本号的高 32 位部分,以及最后一个字段叫做 Project ID。看到这里,是不是觉得,这全是可有可无的东西?对呀!当然了!——128 字节本来就够用,ext2 和 ext3 都用了好多年,那么新增添的东西,自然就是可有可无的了!此处所欠缺的,无非就是一个花言巧语,为其行为进行辩护罢了。你要是去质问,人家是开发者,肯定有办法对付你,云里雾里讲一大堆,讲到你完全听不懂时,那就搞定你了。怪不得有那么多的开源操作系统项目不再以 Linux 为基础,而是另起炉灶——他们可能早都对 Linux 投 “不信任” 票了!

作者: 不点    时间: 2019-3-31 07:24
本帖最后由 不点 于 2019-3-31 07:25 编辑

在百度搜一下,知道微软、谷歌、腾讯、华为等,都是 Linux 基金会的白金会员。Linux 确实要普及了,然而,普及之后的结果,怕是仍然被这些有钱人控制。

是的,从 Windows 或 Android 跳到 Linux 这条船上是对的,但接下来可能还得再跳一次(或多次)。

目前我的预感和主观判断:Linux 里面肯定有恶意代码。后门应该是一堆一堆的,而不是一个一个的。指望 Linux 能安全?门都没有。

算了,一句话,等着跳吧。不过我这辈子恐怕跳不动了,那就等着下辈子了。

作者: 不点    时间: 2019-3-31 11:08
本帖最后由 不点 于 2019-3-31 11:51 编辑
gnuxwy 发表于 2019-3-25 22:47
近年新出现了一个用rust语言写的新操作系统redox,就氏打算从底层开始全部另搞一套的做法。
引导用coreboo ...

今天去了 redox 主页,发现它有自己的文件系统,叫做 RedoxFS。不知您能否再提供点信息?您能否谈谈 redox os 的使用经验?


https://github.com/redox-os/redoxfs 看到了一句话:

The Redox Filesystem. Compatible with Redox and Linux.

就这么一句简单的说明。

https://github.com/redox-os/redoxfs/blob/master/DESIGN.md 看到了文件系统的设计:

RedoxFS Design Document

Structures

Header

The header is the entry point for the filesystem. When mounting a disk or image, it should be scanned for a block starting with the 8-byte signature, within the first megabyte:

"RedoxFS\0"

The header stores the filesystem version, disk identifier, disk size, root block pointer, and free block pointer.

  1. #[repr(packed)]
  2. pub struct Header {
  3.     pub signature: [u8; 8],
  4.     pub version: u64,
  5.     pub uuid: [u8; 16],
  6.     pub size: u64,
  7.     pub root: u64,
  8.     pub free: u64,
  9. }
复制代码


The root and free block pointers point to a Node that identifies Node

  1. #[repr(packed)]
  2. pub struct Node {
  3.     pub name: [u8; 256],
  4.     pub mode: u64,
  5.     pub next: u64,
  6.     pub extents: [Extent; 15],
  7. }
复制代码

看这代码,似乎用固定长度的文件名(固定占据 256 字节)。mode 居然用 64 位(猜测它可能是把所有的字段都弄成 64 位的,即,8 字节对齐)。没见到 inode 号码,因此,有可能也不支持硬链接。

作者: 江南一根葱    时间: 2019-3-31 11:27
就像狮子王一样,人类的资源总被统治者控制
动物世界不分物种
作者: 不点    时间: 2019-3-31 16:55
本帖最后由 不点 于 2019-3-31 17:07 编辑

Redox 系统下目前没有火狐,只有一个叫做 NetSurf 的浏览器,不支持输入法,也不支持 JavaScript。

下载了 Windows 版的 NetSurf,测试速度很快,但不支持输入法,不支持 JavaScript,无法正常使用。

另外,Wiki 百科上说,Redox 只支持 AMD64,不支持别的平台。感觉路还远着。

Minix 操作系统目前不支持 x86-64,只支持 32 位的。对 ARM 有支持,但好像也不支持 ARM64。

RT-Thread 不知有没有桌面版,它是物联网操作系统。它也不支持 x86-64。

总体来看,操作系统的道路很曲折,很遥远。

作者: gnuxwy    时间: 2019-3-31 23:22
不点大师高看了,屮只氏一个老白而已。对redos系统只看开源资讯时偶尔看到,略有了解,根本没用过!
屮喜欢支持开源产品,不管氏软件和硬件,因为这符合屮个的利益和价值观。

开源可以降低用户使用成本,可以形成开放性竞争格局,减少垄断危害。别人无法左右,但自已可以选择。
开源不能消灭流氓恶意软件以及后门,但可以削弱它们,至少让它们不那么明目张胆。而在闭源软硬件的世界里,流氓后门软硬件则可以为所欲为。

呃,闭源,就氏可以为所为欲为当强盗;而开源,则也可能装傻充愣做窃贼。然而,抢一块钱比偷一百块钱更难以让人容忍。。。比烂的世界,开源至少比闭源稍好点,没那么烂,所以相对更值得选择。

不点大师对文件系统的思考很有意思。所思所想到底实践效果怎样,还氏得做出产品来试用后才知道好用不好用,思考的道理符不符合实际需求。。。



作者: 不点    时间: 2019-4-1 08:32
gnuxwy 发表于 2019-3-31 23:22
不点大师高看了,屮只氏一个老白而已。对redos系统只看开源资讯时偶尔看到,略有了解,根本没用过!
屮喜 ...

和论坛上众多引而不发的高人相比,我只是一个匹夫。只不过考虑到 “网络兴亡,匹夫有责”,所以也想负点责任,其实主要只是为自己负责而已;别人的事,倒是没必要去多虑。大凡做任何事,都要有利益的驱动才行。作为一个普通百姓,思考这些问题的出发点,那就不是挣钱,而是通过不断学习知识和参与实践从而增强保护自己的能力而已(这就是利益)。相比之下,一个来自某公司的开发者(假如他是为着公司利益来的),他就可能以 “渗透”为目的(为他的公司带来利益,也有可能是为他个人带来利益)。所以无论是谁,都有利益的驱动在其中,肯定跑不掉的。

刚才说了,我的利益在于保护自己。所以,那些与保护自己无关的东西,自然是不会放在心上的。另外,假如发现无论如何努力都不可能保护自己,那么按照常理,肯定是彻底放弃,不会继续做无用功。这两天很纠结,纠结就纠结在,要给出一个能否保护自己的判断,就是说,到底有没有可能来保护自己?如果有可能,那就继续努力,哪怕难,甚至难于上青天,也无所畏惧。如果根本不可能保护自己,那就拉倒吧,就此洗手,安度晚年得了。目前还没有头绪。谁有头绪的话,不妨说说,互相帮助嘛。

作者: 2013olly    时间: 2019-4-1 10:56
不点 发表于 2019-3-31 07:24
在百度搜一下,知道微软、谷歌、腾讯、华为等,都是 Linux 基金会的白金会员。Linux 确实要普及了,然而, ...

找人fork一个linux,把有后门的地方和难以看懂的地方全部重新写一遍,不知可能性如何?
作者: 不点    时间: 2019-4-1 11:19
嗯,有点眉目了。保护自己的前提,是有硬件生产权。如果自己不生产硬件,光是在软件上折腾,是不可能保护自己的。基本可以肯定,硬件生产者都会留有后门。它要是不留后门的话,那它还是正常的公司吗?有这么傻的公司吗?所以不管是 CPU 还是主板,都会留后门的。就连开源软件里面都会想尽一切办法塞入后门,更何况闭源的硬件了。可以说,后门无处不在。安全的钥匙,掌握在拥有硬件生产权的人手上。作为最终用户,都想着自己的安全,都想着尽量把后门干掉。但你要是把后门都干掉了,控制硬件生产权的人,绝对不会答应的。你让人家控制不住,那就伤害了人家的利益。你安全了,人家收拾不住你了,那么人家就不安全了。因此,从根本上来说,你连软件层面的后门(包括操作系统和其它应用程序的后门),都不可能干掉。你要是真能开发出没有后门的操作系统和应用软件,你这个操作系统和应用软件会被盯上,人家只要更新硬件,让你的系统和软件无法运行,你就死翘翘了。你 “劳苦” 了很多年,但不是 “功高”,而只是白费劲、瞎折腾、做无用功而已。
作者: 不点    时间: 2019-4-1 11:31
2013olly 发表于 2019-4-1 10:56
找人fork一个linux,把有后门的地方和难以看懂的地方全部重新写一遍,不知可能性如何?

刚才打字的时候,你发帖了。没看到你的帖子。你这个想法,原则上讲得通,但前提是,你得有硬件生产权才行(正如我刚才打字所说的那样)。然而,不管是谁,只要他屁股坐在有硬件生产权的位置上,他就不关心有没有后门了,说不定还想多弄几个后门出来。所以,这个问题是个死结,无解的。
作者: 不点    时间: 2019-4-1 22:20
当然,世界也并非僵死不变的,各种矛盾冲突,也会促使事物的发展。不必过分解读 Linux 内核中的问题,也可把它当成发展过程中的不完美。就算 Linux 有各种问题,它也是开源的,在前文中 gnuxwy 对此论述得很到位。如果彻底否定开源的成果,那么连同众多的贡献者们也一起否定了,那样也属于走极端了。

我们来到这里,都是想让自己的价值得到提升。有些东西也许看起来像是空中楼阁、太理想化,那也不妨碍我们讨论。过分追求理想,去实现那不可能实现的东西,不好。完全没有理想,那我们的日子过起来也太平淡、太没有趣味了。走中庸之道吧,看淡这一切。

作者: gnuxwy    时间: 2019-4-1 23:27
嗯,不点说到硬件生产权问题,的确对开源界很重要,没有开源硬件,单氏开源软件只氏一条腿,能站不能跑。。。
人和人氏有差别的,特别氏个体的行为,有时并不氏金钱化的。而且社会文明发展程度越高,个人整体上更注重精神需求,也就氏更愿意耗费时间、精力和各种资源用于自已的兴趣和信念性活动。比如科学史上的卡文迪许,就把他的聪明才智和金钱都投入物理学研究了。再比如自由软件的开创者rms先生,宁可清贫,也要把自已的时间、才智贯注于自由软件世界的信念之中。类似的道理,美欧社会文明发展程度高的地区,显然就会有更多爱好和支持开源理念的程序员和折腾用户。。。

未来极有可能,过几十年 oy 几百年,有想做开源硬件的有钱人,会投入资源把开源硬件平台搞成功,从而让开源运动成为真正的两足行人。。。
至于当前,普通的开源爱好者顺其自然,做自已感兴趣的事就行了。。。





作者: 不点    时间: 2019-4-2 11:41
gnuxwy 发表于 2019-4-1 23:27
嗯,不点说到硬件生产权问题,的确对开源界很重要,没有开源硬件,单氏开源软件只氏一条腿,能站不能跑。。 ...

嗯,扯远点(其实也不算远,技术从哪里来?没有理想,也就没有技术。所以,谈理想,实在不算远。),开国那一代人,我十分佩服,那一代的领袖级人物,名垂青史,跟科学上的牛顿、高斯、爱因斯坦等,在我看来是一样的地位。共同点是,都在推动世界文明向前发展。政治领袖和科学巨人的伟大之处,在于有理想,能高瞻远瞩。中国的文明史很长,文明需要理想。过分理想化,也会犯错误。文革就出了问题。但决不能因为理想出问题了,就全盘否定理想。
作者: 不点    时间: 2019-4-2 16:09
好的,现在再把先前 sefs 目录项设计中的一些有疑问的字段去除掉。哪些字段判定为有疑问的?那些相应于 ext4 的 128 字节之后的扩展字段,都判定为有疑问的。另外,那些与描述文件自身特性无关的字段,也去掉。比如,注释中带有 version 字样的字段,都去掉。保留一个 extended attribute 的可扩展性,可以用来支持所有这些乱七八糟的特性,算是能够与它们兼容(比如各种 version 字段,以及 ACL、selinux 等等)。

作者: 不点    时间: 2019-4-3 13:25
本帖最后由 不点 于 2019-4-3 14:24 编辑

再探讨一下时间戳印。微软的时间戳印有三种:创建时间,访问时间,修改时间。UNIX 也有三种,但与微软不完全相同。UNIX 的是 atime(访问时间)、ctime(inode 属性修改时间) 和 mtime(文件内容修改时间)。而 ext4 里面有五种,比 Unix 多出了两种,这多出的两种时间是:dtime(删除时间)和 crtime(创建时间)。

是不是有点 “莫衷一是”的感觉?大凡在不统一的、混乱的地方,正是可以权衡的地方,也就是可以有取舍的地方。先看看共同点,无论在哪种体系之下,访问时间(atime)和文件内容修改时间(mtime),都是有的。微软把 ctime 解释成 “创建时间”,而 Unix 却解释为 “文件属性变动时间”。ext4 后来增加的两个时间,就把 “创建时间”也给补上了,又添一个 “删除时间”。时间戳印自然是越多越好,记录得详细。但假如真要细分的话,恐怕这五种时间还远远不够用。因此,这就需要权衡了。

首先,访问时间(atime)和文件内容修改时间(mtime),应该保留。这俩的使用频度也比较高。比如 make 命令编译软件的时候,就是用 mtime 来比较文件的新旧的。

这些时间并不能等同于档案馆里面的历史纪事。这些时间是为操作系统和应用程序提供方便的,不要把它用作 “考古”的目的。在上述两个时间的基础上,如果我们要再增加一个时间的话,依旧让它是 ctime 吧。三个时间,已经够多了。倘若像考古那样,增加 20 个时间,恐怕都不算多。

接下来就是怎么解释这个 ctime 的问题。可以保持目前 Unix 对它的解释,即,属性变动的时间。另外,改名也算是属性变动吧?我们的 sefs 没有 inode 了,属性全都在目录项里面。而在目录项里面,文件名也是一个成员,因此也勉强算是一个属性吧。另外,从某种角度来看,改名就是一个删除和一个创建的动作,这么说来,改名也是一次创建了。既然创建文件要更新 ctime,那么 “改名就更新 ctime”这个逻辑,也说得过去,算是合情合理。就是说,如果要创建新文件,ctime 肯定是更新的。改名,ctime 也要更新。改其它属性,ctime 也更新。把三种 time 都合并到 ctime 上,节约空间占用。正如前面所说,如果多设计几个不常用的时间,满足极少数情况(比如将来成为出土文物,方便一万年之后的人类进行考古)的使用,不划算。因此,把它们 “权衡”掉。ext4 还有个 “删除时间”,它的用途就更狭窄了,仅仅在恢复被删除的文件时才有用——无非就是知道它是何时删除的罢了,芝麻小事,不该因此就占用一个 time 的位置,因此把它也 “优化”掉。

作者: sherylynn    时间: 2019-4-3 13:34
slore 发表于 2019-3-5 22:39
如果作为文件系统学习的话,越小越好。

Menuet OS 1.4MB,不过这货不是Linux。Linux体系的话4MB?

去了解了一下这个系统....太可怕了,叹为观止
作者: 不点    时间: 2019-4-5 09:23
本帖最后由 不点 于 2019-4-5 11:55 编辑

再一次地撕扯一下时间戳印。这次聚焦 atime(每次读文件它就更新了)。更新它,需要写盘动作,而写盘是对盘的寿命有影响的操作。所以,读文件就更新时间戳印的做法,不科学。ext4 的 inode 结构中有个标志,指示该文件或该目录的 atime 不更新。——这也间接说明了,更新 atime 是不那么好的一件事情。设计这个标志的原意是“减轻负担、提高效率”——对于频繁访问的文件,更新 atime 造成磁盘访问的负担过重(属于效率问题),所以,不让它更新。注意这还没有涉及到更新 atime 会影响磁盘寿命的问题。

因此,在 sefs 中,默认情况下,atime 不更新。需要更新时,再设置标志,让它更新。工作完成后,再清除标志,回到默认不更新的状态。

除了 find 命令以外,我还没有遇到哪个软件会利用 atime 设置的时间。感觉它用处不大,不如 mtime 的用处大。另外,ctime 与 atime 的处境差不多,都不太有用。

设置了那么多的时间种类,却只有一个时间(mtime)经常使用,其他的时间在平时都躺在那里睡大觉,这也是一种浪费。不过,既然历史上有这三个时间,那就还保留着吧,只要能注意别再胡乱增加其他的时间就行了。

既然 mtime 才是真正有用的 time,就把 mtime 调整到低位。其他两个放在高位,方便将来被某个简化版的操作系统取缔。

作者: 不点    时间: 2019-4-8 14:19
一个文件系统,牵扯到操作系统,一个操作系统又是用编程语言来写的。所以,编程语言也是个问题。假如都要 “简捷化”的话,那工作量确实不小。

Gnuxwy 提到的 redox 系统,也确实够 “劲”,连 bash 都不采用了。这要是在从前,我肯定要骂它。当我去年研究了 bash 的代码以后,就对 bash 彻底失望了。原因很简单:它的代码复杂得很,看不懂——这还是小事,而真正的大事是——我发现它是故意搞复杂的,于是我就能够肯定,其中一定有后门,跑不了。至于后门是啥,我当然没那能力去挖掘了,其实也没那兴趣。只要我认定它有后门即可,只要我以后生办法摆脱它即可,根本没有必要费劲去挖掘它的秘密。

作者: 不点    时间: 2019-4-8 14:45
关于文件系统的设计,目前也差不多算是设计完了,关键的问题都涉及到了。谁要是有兴趣,那就可以着手用代码来实现了。接下来,我的兴趣,又转移到编程语言上了。就是说,编程语言需要 “简捷化”。当然这同样是个权衡,所以,也并不容易实现 “简捷化”的目标。如果“太简捷”了,缺少功能,不行。如果复杂了,初学者学习难度增加、提高了门槛,也不行。初步设想,参照 C 语言的设计,比 C 语言再 “好”上那么一点点,可能就差不多了。
作者: gnuxwy    时间: 2019-4-15 21:33
不点大师想找一个比C语言可能稍好点的语言?
屮前不久见着有条开源资讯,说氏有人在开发一个zig语言,其设计目标就氏想达到不点大师的要求。

不过据说目前还很不成熟,bug很多。大师如果有兴趣,可以去下zig语言的开发网站,参与评论,也许能促进开发和解决bug呢。。。

屮个人觉得,如果能把gtk的作为cjj子集的设计重新用zig之类的原生语言重新实现一遍,就能比C好一些了。。。

作者: 不点    时间: 2019-4-16 07:27
gnuxwy 发表于 2019-4-15 21:33
不点大师想找一个比C语言可能稍好点的语言?
屮前不久见着有条开源资讯,说氏有人在开发一个zig语言,其设 ...

您看到了,我想在有限的生命中做点事,但个人力量实在有限,心有余而力不足。您提到的 zig,我会研究一下的。
作者: dsxmg1990    时间: 2020-4-5 01:27
微软为啥一直用ntfs,效益好?no有比它好的,相反linux各种文件系统,为啥,很简单,一个是生产系统,一个是研究折腾的系统!
作者: gs358906    时间: 2020-4-30 11:10
想分清楚就已经不简单了
作者: 不点    时间: 2021-9-27 09:52
今天搜 cpio 文件格式,找到如下结构:

struct header_old_cpio {
        unsigned short   c_magic;
        unsigned short   c_dev;
        unsigned short   c_ino;
        unsigned short   c_mode;
        unsigned short   c_uid;
        unsigned short   c_gid;
        unsigned short   c_nlink;
        unsigned short   c_rdev;
        unsigned short   c_mtime[2];
        unsigned short   c_namesize;
        unsigned short   c_filesize[2];
};

赫然可见,只有 mtime 在其中,而没有 atime 和 ctime!这再次印证了 mtime 和其他那些 time 的重要性是完全不同的。


tar 的格式也是如此:


Field width
Field Name
Meaning
100
name
Name of file
8
mode
File mode
8
uid
Owner user ID
8
gid
Owner group ID
12
size
Length of file in bytes
12
mtime
Modify time of file
8
chksum
Checksum for header
1
link
Indicator for links
100
linkname
Name of linked file


tar 和 cpio 共有的元素是:filename, filesize, mode, uid, gid, mtime。像这样抽取共性以后,就能发现哪些是主要的,哪些是次要的。


作者: 爱启动    时间: 2021-9-28 13:13
不是ext4这样的文件系统?
作者: 2012gzcs    时间: 2021-10-9 14:09
Minix 考古级,操作系统
作者: 不点    时间: 2021-10-16 11:25
搜到这个:

hash算法的讲解
https://www.cnblogs.com/austinspark-jessylu/p/9549260.html

讲得细致,门外汉能看懂,所以收藏到这里,说不定以后能用上。

作者: 爱启动    时间: 2021-11-10 10:09
支持楼主继续
作者: teamviewer    时间: 2022-3-14 21:48
IBM Linux 技术中心
作者: guyanqiu    时间: 2022-10-25 22:27
使用的频度是不同的
作者: 王少笑    时间: 2023-3-7 23:57
好像都不完美




欢迎光临 无忧启动论坛 (http://wuyou.net/) Powered by Discuz! X3.3