您的位置:首页 > 编程语言 > C语言/C++

精通Unix下C语言之文件系统结构

2010-07-12 00:30 211 查看
精通Unix下C语言之文件系统结构

Unix文件的存储由“目录--i节点--数据块”三级组成,其中目录存储了文件的层次结构,数据块存储了文件的具体内容信息,i节点是连接文件层次结构与其数据内容的桥梁。

Unix下的文件包括了文件类型、文件访问权限、文件属主ID、文件属组ID、文件链接数、文件长度和文件时间等信息,这些信息存储在文件对应的i节点中。

1.1 文件系统的结构

磁盘包含着一个或多个分区,每个分区都有一个文件系统。Unix文件系统将磁盘空间分为一系列大小想通的块(block),全部块可分为引导块、超级块、i节点区(inode区)和数据区等四个部分。

1.引导块

引导块位于文件系统的第0块物理块,即文件卷的第一扇区,不属于文件系统管辖,存在文件系统的引导代码。

2.超级块

超级块位于文件系统的第1号物理块、紧跟引导块之后,描述文件系统本身的结构信息。超级块的数据结构一般定义在文件“filsys.h”中,/usr/include/sys/filsys.h

struct filsys

{

Ushort s_isize;/*磁盘索引节点区所占用的数据块数*/

daddr_t si_fsize;/*整个文件系统的数据块数*/

short s_nfree;/*在空闲块登录表中当前登记的空闲块数目*/

daddr_t s_free[NICFREE];/*空闲块登记表*/

short s_ninode;/*空闲索引节点数*/

ino_t s_inode[NICFREE];/*空闲节点登记表*/

chars_flock; /*加锁标志位*/

.

.

.

.

};

3.i节点区(inode区)

i节点区位于超级块之后,长度犹超级块中的s_isize中决定,它描述文件的属性,如长度、属主、属组、数据块表盒最近访问时间等。i节点的数据结构一般定义在"ino.h"/* /usr/include/sys/ino.h*/

struct dinode

{

ushort di_mode;/*文件类型与权限*/

short di_nlink;/*文件链接数*/

ushort di_uid;/*文件属主id*/

ushort di_gid;/*文件属组ID*/

off_t di_size;/*文件长度*/

char di_addr[NADDR_BYTES];/*文件磁盘块地址列表*/

char di_gen;/*file generation number*/

time_t di_atime;/*文件最近访问时间*/

time_t di_mtime;/*文件最近修改时间*/

time_t di_ctime;/*文件状态最近改变时间*/

};

文件系统通过i节点对文件进行控制和管理。其中,每个文件对应一个i节点,每个i节点具有唯一的节点号,记录了文件的属性和内容在磁盘上的存储位置。但文件名并不记录在i节点里,而是存储在目录文件中。

4.数据区

文件数据区中各数据块的空闲情况由超级块记录,文件系统利用超级块中的记录完成对数据块的分配和回收。

1.2 磁盘文件

磁盘文件读取工作原理

ex:命令cat T1.c的执行过程为例,总数一下unix文件的读取过程

1st step:在当前目录文件中查找文件"T1.c"机器对应的i节点编号,假设为1109;

2nd step:在i节点表中读取第1109号节点

3rd:读取i节点中文件属性、访问权限等信息

4th: 读取i节点中磁盘地址表,按照三级索引规则在数据区读取文件内容。

1.3文件属性

Unix的文件属性信息,都存储于i节点中,随着文件的操作而自动改变。一般情况下,我们能读取i节点的内容,但不能直接改变它。

1.文件属性函数族

#include<sys/types.h>

#include<sys/stat.h>

int stat(const char *path, struct stat *buf);

int fstat(int fildes,struct stat *buf);

int lstat(const char *path,struct stat *buf);

结构stat定义在文件"stat.h"如代码如下:/*/usr/include/sys/stat.h*/

strcut stat

{

...

dev_t st_dev;/*文件常驻设备ID*/

ino_t st_ino;/*i节点编号*/

mode_t st_mode;/*文件类型与权限*/

nlink_t st_mode;/*文件链接数*/

uid_t st_uid;/*文件属主ID*/

gid_t st_gid;/*文件属组ID*/

dev_t st_rdev;/*特别文件(字符文件或块文件)设备号*/

off_t st_size;/*文件长度*/

time_t st_atime;

time_t st_mtime;

time_t st_ctime;/*文件最近改变时间*/

};

2.文件类型

在Unix中,文件按类型可以分为普通文件(regular file)、目录文件(directory file)、管道文件(pipe file)、设备文件(dev file)、符号链接文件(char character file)和SOCKET文件。文件的类型属性在st_mode域中,占用4bit,各种文件类型的标志定义在文件"stat.h".

常数宏(S_IFMT)分别为S_IFREG、S_IFDIR、S_IFIFO、IF_BLK、S_IFCHR、S_IFSOCK.

在Unix中,已知结构stat的文件类型字段为st_mode,判断文件类型的方法有2种:

1) if((st_mode & _S_IFMT)==S_IFREG)是普通文件

else 不是

2) if(S_ISREG(st_mode))是普通文件

else不是

ex:设计函数GetFileType,功能是判断输入的文件类型,并转化为Unix文件标志,如下:

int GetFileType(mode_t st_mode,char *resp)

{

if(resp==null) return 0;

if(S_ISDIR(st_mode)) resp[0]='d';

else if(S_ISCHAR(st_mode)) resp[0]='c';

......

return 1;

}

3.文件访问权限

文件的全部访问权限可标志为三组共9个二进制数,其中第一组描述了用户权限,第二组内权限,第三组为其他用户权限。为了方便书写,通常也使用一个八进制数来代替一组权限。

在Unix中,已知结构stat的文件权限字段为st_mode,判断该文件访问权限的方法如下:

if(st_mode & S_IXUSR) 文件具有属主执行权限

else不具有

ex:设计函数GetFileMode,功能是判断输入的文件权限,并转化为Unix权限标志,如下:

int GetFileMode(mode_t st_mode,char *resp)

{

if(resp==null) return 0;

memset(resp,'-',9);

if(st_mode & S_IRUSR) resp[0]='r';

if(st_mode & S_IWUSR) resp[1]='w';

....

return 1;

}

4.文件其它属性

在i节点记录的文件属性还包括文件属主ID,文件属组ID、文件链接数、文件长度和文件时间等信息。

int GetFileOtheAttr(struct stat info,char * resp)

{

struct tm *mtime;

if(resp==null)return 0;

mtime=localtime(&info.st_mtime);

return (sprintf(resp,"%3d %6d %11d %04d %02d %02d",

info,st_nlink,infor.st_uid,info.st_gid,info.st_size,

mtime->tm_year +1900,mtime->tm_mon+1,mtime->tm_mday));

}

设计类似于Unix命令中的“ls -l”的程序lsl,显示指定文件的属性信息,如下:

#include<stdio.h>

#include<sys/type.h>

#include<sys/stat.h>

#include<time.h>

int GetFileType(mode_t st_mode,char *resp);

int GetFileMode(mode_t st_mode,char *resp);

int GetFileOtherAttr(mode_t st_mode,char *resp);

void main()

{

struct stat info;

char buf[100];

if(arg!=2)

{

fprintf(stderr,"lsl filename/n");

return ;

}

memset(buf,0,sizeof(buf));

if(lstat(argv[1],&info)==0)

{

p+=GetFileType(info.st_mode,p);

p+=GetFileMode(info.st_mode,p);

p+=GetFileOtherAttr(info,p);

printf("%s %s/n",buf,arg[1]);

}

else fprintf(sterr,"open file failed./n");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: