stat()函数_stat函数返回值

stat()函数_stat函数返回值在linux中,经常需要获取文件的属性,比如修改时间,文件大小等等。stat函数将会帮助我们得到这些信息。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

在 linux 中,经常需要获取文件的属性,比如修改时间,文件大小等等。stat 函数将会帮助我们得到这些信息。

1 stat 函数

1.1 stat 函数的作用

linux 中,可以使用 stat 函数来获取文件相关的信息,就比如说文件的大小文件的类型等等。

1.2 struct stat 结构体

stat 函数将获取到的结果保存到一个名为 struct stat 的结构体中。它的样子如下:

 struct stat {
    dev_t     st_dev;         /* 包含这个文件的设备 ID */
    ino_t     st_ino;         /* inode 编号 */
    mode_t    st_mode;        /* 访问权限 */
    nlink_t   st_nlink;       /* 硬链接数量 */
    uid_t     st_uid;         /* 用户ID */
    gid_t     st_gid;         /* 组ID */
    dev_t     st_rdev;        /* 设备ID */
    off_t     st_size;        /* 文件占用的字节数 */
    blksize_t st_blksize;     /* 文件系统块大小 */
    blkcnt_t  st_blocks;      /* 文件占用了几个512字节 */
    time_t    st_atime;       /* 最后访问时间 */
    time_t    st_mtime;       /* 最后更改时间 */
    time_t    st_ctime;       /* 最后状态更改时间 */
};

1.3 stat 函数原型

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

stat 函数的第一个参数是目标文件的路径。第二个参数是输出参数,用来保存返回的文件信息的结果。

stat 函数的返回值如果是 0,表示函数执行成功,否则失败。失败后会改写 errno 这个全局变量。我们可以使用 perror 这个函数打印失败的原因。

2 实验

  • 代码
// filename: statdemo.c

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

int main() {
  struct stat st; 
  int r = stat("test.txt", &st);
  if (r) {
    perror("stat");
    return -1; 
  }

  printf("st_dev = %lld\n", st.st_dev);
  printf("st_ino = %ld\n", st.st_ino);
  printf("st_mode = %d\n", st.st_mode);
  printf("st_nlink = %d\n", st.st_nlink);
  printf("st_uid = %d\n", st.st_uid);
  printf("st_gid = %d\n", st.st_gid);
  printf("st_size = %ld\n", st.st_size);

  printf("st_atime = %ld\n", st.st_atime);
  printf("st_mtime = %ld\n", st.st_mtime);
  printf("st_ctime = %ld\n", st.st_ctime);
  return 0;
}
  • 编译
$ gcc statdemo.c -o st
  • 运行结果

如果 test.txt 文件不存在,打印如下结果:

stat: No such file or directory

如果 test.txt 文件存在,其内容只包含 hello 5 个字符,打印结果如下:

st_dev = 2049
st_ino = 831785
st_mode = 33204
st_nlink = 1
st_uid = 1000
st_gid = 1000
st_size = 6 // 这个结果是 6 是因为 vim 编辑器会自动在最后一个字符后面插入一个 '\n' 字符
st_atime = 1480252548
st_mtime = 1480252548
st_ctime = 1480252548

从以上结果可以看到文件信息各个字段的的内容。比如最近访问时间,最近更改时间,最近状态更改时间等等。还有访问权限位(st_mode)等等。另外需要注意的是,文件的类型也可以从 st_mode 中得出,这些我们将在后面介绍。

3 更加深入

掌握了 stat 函数的用法,相信你不应该止步于此。我们提出的问题是,stat 函数是从哪儿获取到文件信息的?

倘若你阅读了前面几篇有关文件系统的章节,相信你还回忆得起 目录项inode 节点 这些很重要的名词。

3.1 再理一遍文件查找过程

cur_inode = 2
for name in path: // 分析路径中的每一层次的名称
    if isLeaf(name): // 如果是最后一级目录,退出
        break
    for dir_entry in cur_inode.dir_entries: // 遍历当前 inode 节点中的每一个目录项
        if dir_entry.name == name: // 根据路径中某一层次的名称找到目录项
            if dir_entry.file_type == EXT2_FT_DIR: // 判断是是否是目录
                cur_inode = dir_entry.inode // 更新当前 inode 节点
                continue
        else:
            break
return cur_inode // 到这里就已经找到了 当前文件的 inode 编号,即 cur_inode。

3.2 相关结构体

  • dir_entry 结构体如下:
struct ext2_dir_entry_2 {
    __u32   inode;          /* Inode number */
    __u16   rec_len;        /* Directory entry length */
    __u8    name_len;       /* Name length */
    __u8    file_type;
    char    name[EXT2_NAME_LEN];    /* File name */
};
  • inode 节点结构体如下:
struct ext2_inode {
    __u16   i_mode;     /* File mode */
    __u16   i_uid;      /* Low 16 bits of Owner Uid */
    __u32   i_size;     /* Size in bytes */
    __u32   i_atime;    /* Access time */
    __u32   i_ctime;    /* Creation time */
    __u32   i_mtime;    /* Modification time */
    __u32   i_dtime;    /* Deletion Time */
    __u16   i_gid;      /* Low 16 bits of Group Id */
    __u16   i_links_count;  /* Links count */
    __u32   i_blocks;   /* Blocks count */
    __u32   i_flags;    /* File flags */
    union {
        struct {
            __u32  l_i_reserved1;
        } linux1;
        struct {
            __u32  h_i_translator;
        } hurd1;
        struct {
            __u32  m_i_reserved1;
        } masix1;
    } osd1;             /* OS dependent 1 */
    __u32   i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
    __u32   i_generation;   /* File version (for NFS) */
    __u32   i_file_acl; /* File ACL */
    __u32   i_dir_acl;  /* Directory ACL */
    __u32   i_faddr;    /* Fragment address */
    union {
        struct {
            __u8    l_i_frag;   /* Fragment number */
            __u8    l_i_fsize;  /* Fragment size */
            __u16   i_pad1;
            __u16   l_i_uid_high;   /* these 2 fields */
            __u16   l_i_gid_high;   /* were reserved2[0] */
            __u32   l_i_reserved2;
        } linux2;
        struct {
            __u8    h_i_frag;   /* Fragment number */
            __u8    h_i_fsize;  /* Fragment size */
            __u16   h_i_mode_high;
            __u16   h_i_uid_high;
            __u16   h_i_gid_high;
            __u32   h_i_author;
        } hurd2;
        struct {
            __u8    m_i_frag;   /* Fragment number */
            __u8    m_i_fsize;  /* Fragment size */
            __u16   m_pad1;
            __u32   m_i_reserved2[2];
        } masix2;
    } osd2;             /* OS dependent 2 */
};

3.3 stat 是如何找到文件信息的?

参考 3.1 中的文件查找流程,stat 可以很容易的从 inode 结构体中获取。比如 st_mode 字段来源于 inode 的 i_mode 字段等等。

需要注意的是,作为用户态程序,你是无法直接读取磁盘的,这也导致了我们没有办法自己去解析磁盘数据。这是出于操作系统安全角度考虑的,如果你不小心破坏了文件系统,这将直接导致操作系统无法启动。

linux 并不直接提供你操作磁盘的方法,除非你自己写 linux 驱动程序。但是为了让你获取一些必要的信息,linux 提供了一些接口给你使用,比如这里的 stat 函数。

4 小结

本节你需要掌握 stat 函数,并打印出这些整数值。关于这些整数如何转换成人类可读的,后面将一一介绍。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/171778.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 利用MATLAB演奏最炫民族风[通俗易懂]

    利用MATLAB演奏最炫民族风[通俗易懂]sp=actxserver(‘SAPI.SpVoice’);sp.Speak(‘最炫民族风’);sp.Speak(‘作曲者’);sp.Speak(‘二狗子’);sp.Speak(‘演奏者’);sp.Speak(‘Matlab’);%Mostshiningnationalwind//最炫民族风onMatlab%TheModificationisfrom”can

    2022年9月22日
    4
  • 进销存源码|ERP多仓库管理系统全开源php源码

    进销存源码|ERP多仓库管理系统全开源php源码  进销存(ERP)源码是用来管理企业数据的软件工具。进销存系统帮助不同的组织处理企业的不同部门。不同部门如收货、库存管理、客户订单管理、生产计划、发货、会计、人力资源管理等业务职能。基本上,它是将企业的计划、生产、销售和营销工作整合到一个管理系统中的实践。它将跨不同部门的所有数据库合并到一个单一的数据库中,该企业的所有员工都可以轻松访问该数据库。它有助于自动化执行业务流程所涉及的任务。    进销存源码演示及资源获取:e.csymzs.top    使用进销存前:    在使用进销存源码之前,

    2022年5月31日
    121
  • 拉格朗日乘数法求得的是最值还是极值_微观经济拉格朗日方程求极值

    拉格朗日乘数法求得的是最值还是极值_微观经济拉格朗日方程求极值一、拉格朗日乘数法简介在日常的生产生活中,当我们要要安排生产生活计划的时候,常常会在现实物理资源约束的条件下,计算得到收益最大或者损失最小的计划;像这种对自变量有附加条件的极值称为条件极值;拉格朗日乘数法是一种直接计算解决条件极值的方法;拉格朗日乘数法的定义如下:设有f(x,y),φ(x,y)f(x,y),\varphi(x,y)f(x,y),φ(x,y)两个函数,并且两者都有一阶连续偏导数,则做拉格朗日函数为F(x,y,λ)=f(x,y)+λφ(x,y)F(x,y,\lambda)

    2025年5月23日
    4
  • 程序员:为什么“基础不牢”成为我薪资被砍的理由?!

    程序员:为什么“基础不牢”成为我薪资被砍的理由?!

    2021年6月14日
    135
  • 数据库第一范式 第二范式 第三范式 BC 范式

    数据库第一范式 第二范式 第三范式 BC 范式国内绝大多数院校用的王珊的《数据库系统概论》这本教材,某些方面并没有给出很详细很明确的解释,与实际应用联系不那么紧密,你有这样的疑问也是挺正常的。我教《数据库原理》这门课有几年了,有很多学生提出了和你一样的问题,试着给你解释一下吧。(基本来自于我上课的内容,某些地方为了不过于啰嗦,放弃了一定的严谨,主要是在“关系”和“表”上)首先要明白”范式(NF)”是什么意思。按照教材中的定义,范式是“

    2022年5月20日
    30
  • java三大框架要学多久_新手学习SSH三大框架的几点建议[通俗易懂]

    java三大框架要学多久_新手学习SSH三大框架的几点建议[通俗易懂]说起三大框架,目前人们常用的是SSM,有人会认为SSH框架已经落后被淘汰了,其实这样说也不完全对。它毕竟实现了经典的MVC框架的基本功能,在有些项目还会用到。正因为用得不多,反而会出现很多问题。同时SSH在教学中也会被经常用到,笔者觉得SSH在教学中存在的意义在于能够帮助学习者理解经典MVC框架的原理。下面就简单谈一谈作为新手如何学习SSH。所谓SSH展开来讲包括了struts、spring、hi…

    2022年7月7日
    35

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号