作者:吴新武,华清远见嵌入式培训中心讲师。
Unix业界有句话叫“一切皆文件”,Linux作为一个优秀的类Unix操作系统,具有强大的文件管理能力, 其中“一切皆文件”就是很突出的特点!
文件系统就是负责文件的管理。每一个文件通常包含两部分的内容,一个是文件的信息包括文件的权限、文件的所有者、时间参数等,一个是文件数据。前者放在一个叫inode的结构体中,每个文件的inode的编号都是唯一的;后者放在block区,每个block都有唯一的编号,文件占用一个或多个block。inode译成中文就是索引节点,它用来存放档案及目录的基本信息,包含时间、档名、使用者及群组等,该结构体中有成员指出该文件内容放的block编号是多少,如果一个文件太大,会占用多个block。换句话说,只要找到一个文件的inode结点,就能找到该文件的内容。
Linux一个文件系统内部的每个文件的管理是通过inode和block,至于整个文件系统的管理,是通过superblock(超级块)。记录的信息主要有:
1、 block与inode的总量;
2、未使用与已使用的inode/block数量;
3、block与inode 大小(block为1,2,4K,inode为128bytes);
4、filesystem的挂载时间、最近一次写入数据的时间、最近一侧检验磁盘(fsck)的时间等文件系统的相关信息;
这个superblock非常重要,因为我们文件系统的基本信息都写在这里。一般来说,superblock的大小为1025字节。每个文件系统对应一个超级块,通过双向循环链表将超级块管理起来即可实现Linux对多个文件系统的管理。
那么对应单个的文件,Linux下是如何通过文件名来找到文件的呢?主要是两步骤:1、根据文件名,通过目录的对应关系找到文件对应的inode编号;2、根据文件编号找到inode表,再根据inode表中的block指针找到对应的文件内容。在Linux下,可以通过ls –i命令来查看每个文件的inode编号。inode该结构体的作为每个文件的标识,可通过stat函数将其内容读取到struct stat类型的结构体中。struct stat的结构如下。
struct stat {
dev_t st_dev; /* device */
ino_t st_ino; /* inode */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device type (if inode device) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
在stat结构体中st_dev成员为文件的设备号,可获得该设备的驱动类型及对应的file_operations 结构体即可以找到该文件的相关操作函数。
其中,st_mode的类型 mode_t.其实就是普通的unsigned int.
目前,st_mode使用了其低19bit. 0170000 => 1+ 3*5 = 16.
其中,最低的9位(0-8)是权限,9-11是id,12-15是类型。具体定义如下:
S_IFMT 0170000 bitmask for the file type bitfields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 fifo
S_ISUID 0004000 set UID bit
S_ISGID 0002000 set GID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permisson
S_IXOTH 00001 others have execute permission
当我们需要快速获得文件类型或访问权限时,最好的方法就是使用glibc定义的宏。如:S_ISDIR,S_IRWXU等。
例如要判断/home是目录还是文件可用:
struct stat buf;
memset(&buf, 0, sizeof(struct stat));
lstat(“/home”, &buf);
if( S_ISDIR(buf.st_mode)) printf(“is directory\n”);
if( S_ISREG(buf.st_mode)) printf(“is regular file\n”);
文件系统的管理作为Linux内核的重要部分,整体框架还是比较复杂的,本文只是在文件IO授课时的一个总结,欢迎批评指正。