linux文件系统中i节点和stat函数/命令

一、概述

  • unix系统中,每打开一个文件,内核会使用三种数据结构来表示这个文件:进程表、v节点和i节点。
  • linux只保留了unix中的i节点来维护打开的文件;

二、i节点和struct stat结构体

linux的i节点信息存储在struct stat结构体中,可以通过man 2 stat来查看这个结构体的内容,如下:

           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */
               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 ID (if special file) */
               off_t     st_size;    /* total size, in bytes */
               blksize_t st_blksize; /* blocksize for filesystem I/O */
               blkcnt_t  st_blocks;  /* number of 512B 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 */
           };
  • st_dev 表示该文件所存在设备的id;
  • st_ino i节点编号,每一个文件都有唯一的i节点编号;
  • st_mode 文件的权限,如0777表示所有的用户具有可读可写和可执行权限,这个位还指明了文件的类型,可以和以下宏组合使用:
S_ISREG(m)  is it a regular file?
S_ISDIR(m)  directory?
S_ISCHR(m)  character device?
S_ISBLK(m)  block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)
S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)

S_IFMT     0170000   bit mask for the file type bit fields
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-user-ID bit
S_ISGID    0002000   set-group-ID 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 permission
S_IXOTH    00001     others have execute permission

  • st_nlink 硬链接的个数;
  • st_uid 拥有者组id;
  • st_gid 拥有者组id;
  • st_rdev 设备id;
  • st_size 设备的大小,以字节为单位,如果文件时一个符号链接,那么这个值的大小是它路径名的长度;
  • st_blksize
  • st_blocks
  • st_atime 最后访问时间
  • st_mtime 最后修改时间
  • st_ctime 上一次访问的时间

最后的三个时间可以使用localtime函数转换成标准的北京时间:

#include <time.h>
struct tm *localtime(const time_t *timep);
struct tm {
  int tm_sec;    /* Seconds (0-60) */
  int tm_min;    /* Minutes (0-59) */
  int tm_hour;   /* Hours (0-23) */
  int tm_mday;   /* Day of the month (1-31) */
  int tm_mon;    /* Month (0-11) */
  int tm_year;   /* Year - 1900 */
  int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
  int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
  int tm_isdst;  /* Daylight saving time */
};

三、stat函数和stat命令

3.1、stat函数

使用stat函数可以得到对应文件的struct stat结构体,函数原型如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);

这三个函数的区别在于,stat用来获取指定路径的文件信息,lstat函数和stat的作用完全相同,但是当lstat函数的pathname是一个符号链接时,lstat得到的信息是这个符号链接本身的信息,而不是这个符号链接指向的文件信息。fstat可以根据已经打开文件的描述符获取文件信息。

  1. 首先我们在当前目录下新建一个text文件,并在文件中随便写入一些内容::
touch text
vim text

2.使用stat函数读取text文件的内容

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
void check_file_type(mode_t mode)
{
	printf("File Type:");
	switch(mode & S_IFMT)
	{
      case S_IFSOCK:
          printf("socket\r\n");
          break;
      case S_IFLNK:
         printf("symbolic link\r\n");
         break;
      case S_IFREG:
          printf("regular file\r\n");
          break;
      case S_IFBLK:
          printf("block file\r\n");
          break;
      case S_IFDIR:
          printf("directory\r\n");
          break;
      case S_IFCHR:
          printf("character device\r\n");
          break;
      case S_IFIFO:
          printf("FIFO\r\n");
          break;
      default    :
          printf("unknown file type\r\n");
          break;
      }
}
 void check_file_permission(mode_t mode,char * perm)
 {
      perm[0]='?';//先获取类型
      switch(mode & S_IFMT){
      case S_IFSOCK:
          perm[0]='s';
          break;
      case S_IFLNK:
          perm[0]='l';
          break;
      case S_IFREG:
          perm[0]='-';
          break;
      case S_IFBLK:
          perm[0]='b';
         break;
     case S_IFDIR:
         perm[0]='d';
         break;
     case S_IFCHR:
         perm[0]='c';
         break;
     case S_IFIFO:
         perm[0]='p';
         break;
     }

     if(mode & S_IRUSR)
         perm[1]='r';
     if(mode & S_IWUSR)
         perm[2]='w';
     if(mode & S_IXUSR)
         perm[3]='x';
     if(mode & S_IRGRP)
         perm[4]='r';
     if(mode & S_IWGRP)
         perm[5]='w';
     if(mode & S_IXGRP)
         perm[6]='x';
     if(mode & S_IROTH)
         perm[7]='r';
     if(mode & S_IWOTH)
         perm[8]='w';
     if(mode & S_IXOTH)
         perm[9]='x';
     perm[10]='\0';
 }

int main()
{
	int ret = -1;
	struct tm *tim;
	char pem[] = "----------";
	struct stat stabuf;
	char pathname[] = "text";
	stat(pathname,&stabuf);
	printf("Inode Number:%d\r\n",stabuf.st_ino);
	printf("Hard Links:%d\r\n",stabuf.st_nlink);
	check_file_type(stabuf.st_mode);
	check_file_permission(stabuf.st_mode,pem);
	printf("File Permission:%s\r\n",pem);	
	printf("User ID:%u\r\n",stabuf.st_uid);
	printf("Group ID:%u\r\n",stabuf.st_gid);
	printf("Device ID:%u\r\n",stabuf.st_rdev);
	printf("File Size:%d\r\n",stabuf.st_size);
	printf("Block Size:%d\r\n",stabuf.st_blksize);
	printf("Block Nums:%d\r\n",stabuf.st_blocks);
	tim = localtime(&stabuf.st_atime);
	printf("Acess Time:%04d-%02d-%02d %02d:%02d:%02d %02d\r\n",tim->tm_year+1900,tim->tm_mon+1,tim->tm_mday,tim->tm_hour,tim->tm_min,tim->tm_sec,tim->tm_isdst);
	tim = localtime(&stabuf.st_mtime);
	printf("Modify Time:%04d-%02d-%02d %02d:%02d:%02d %02d\r\n",tim->tm_year+1900,tim->tm_mon+1,tim->tm_mday,tim->tm_hour,tim->tm_min,tim->tm_sec,tim->tm_isdst);
	tim = localtime(&stabuf.st_atime);
	printf("Change Time:%04d-%02d-%02d %02d:%02d:%02d %02d\r\n",tim->tm_year+1900,tim->tm_mon+1,tim->tm_mday,tim->tm_hour,tim->tm_min,tim->tm_sec,tim->tm_isdst);
	
}

3.编译上面的代码并执行后,紧接着使用stat命令查看文件的信息,得到如下结果,可以看出使用stat函数和stat命令得到的文件信息是一致的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KE4wCZ1F-1602384401529)(534ED7E486A5402398692D7F3EABD0C8)]

4.给text文件建立一个硬链接,在shell中执行ln text tex,然后查看文件信息,可以看到文件的硬链接变为了2。

ln text tex

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sZW7BYeD-1602384401533)(EB2FA78A9283470CAE13625615DD7736)]

图中文件的i节点编号和前面的不一致是因为我把text文件从共享文件夹中拷贝到了/home目录,使用vmtool共享文件夹是无法创建硬链接的,会提示如下错误:

ln: failed to create hard link ‘tex’ => ‘text’: Operation not permitted

3.2、stat命令

stat命令在shell中使用,它具有和stat函数大致相同的功能,但比stat函数的使用更加灵活和多样化,在shll终端中使用man stat可以查看比较详细的介绍。

stat命令我们通常不需要添加任何参数就可以查看文件的详细信息,在shell中执行如下指令:

stat text

其它选项

  • -f 查看文件系统信息而非文件信息;
  • -c 查看指定格式的文件信息,如stat -c %i text表示只查看文件的i节点信息;
  • -t 将文件信息以简略形式输出到shell终端
    (img-Cqu9Fm8D-1602384401535)(F4955B43FC1E4435ADC09BFBF0EAE2A8)]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值