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

精通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");

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(c,unix,struct,File,语言,磁盘)