Linux中,文件创建的时间是怎么保存的?

今天在微信群里有人提问,如果创建一个文件,创建这个文件的时间是保存在哪里的。

所以就查到了这篇文章。

===

在介绍inode结构体之前先做一个链接文件的实验:

  • 1.创建一个普通的文件test.txt,并写入内容查看,如下

  • 2.创建test.txt的硬链接文件,并测试如下:

  • 3.创建test.txt的软连接文件并测试,如下:

  • 4.ls命令查看文件相关信息,如下:

根据现象可以发现,test.txt文件的硬链接文件test_hardlink的inode号和原文件一样,而它的软链接文件tesrt_softlink的inode号就和原文件不一样,根据了解我们知道硬链接文件是原来文件的副本只是文件名不一样而已,软连接文件是一个新的文件(实际上硬链接文件在磁盘上和原文件使用的是同一个inode节点,软连接文件使用不同的inode节点来管理文件)。

那么inode究竟是什么,它在内核中处于什么的地位?

下面我们来介绍下内核中的inode结构(大部分做了注释):

struct inode {umode_t         i_mode;//文件的访问权限(eg:rwxrwxrwx)unsigned short      i_opflags;kuid_t          i_uid;//inode拥有者idkgid_t          i_gid;//inode拥有者组idunsigned int        i_flags;//inode标志,可以是S_SYNC,S_NOATIME,S_DIRSYNC等#ifdef CONFIG_FS_POSIX_ACLstruct posix_acl    *i_acl;struct posix_acl    *i_default_acl;
#endifconst struct inode_operations   *i_op;//inode操作struct super_block  *i_sb;//所属的超级快/*address_space并不代表某个地址空间,而是用于描述页高速缓存中的页面的一个文件对应一个address_space,一个address_space与一个偏移量能够确定一个一个也高速缓存中的页面。i_mapping通常指向i_data,不过两者是有区别的,i_mapping表示应该向谁请求页面,i_data表示被改inode读写的页面。*/struct address_space    *i_mapping;#ifdef CONFIG_SECURITYvoid            *i_security;
#endif/* Stat data, not accessed from path walking */unsigned long       i_ino;//inode号/** Filesystems may only read i_nlink directly.  They shall use the* following functions for modification:**    (set|clear|inc|drop)_nlink*    inode_(inc|dec)_link_count*/union {const unsigned int i_nlink;//硬链接个数unsigned int __i_nlink;};dev_t           i_rdev;//如果inode代表设备,i_rdev表示该设备的设备号loff_t          i_size;//文件大小struct timespec     i_atime;//最近一次访问文件的时间struct timespec     i_mtime;//最近一次修改文件的时间struct timespec     i_ctime;//最近一次修改inode的时间spinlock_t      i_lock; /* i_blocks, i_bytes, maybe i_size */unsigned short          i_bytes;//文件中位于最后一个块的字节数unsigned int        i_blkbits;//以bit为单位的块的大小blkcnt_t        i_blocks;//文件使用块的数目#ifdef __NEED_I_SIZE_ORDEREDseqcount_t      i_size_seqcount;//对i_size进行串行计数
#endif/* Misc */unsigned long       i_state;//inode状态,可以是I_NEW,I_LOCK,I_FREEING等struct mutex        i_mutex;//保护inode的互斥锁//inode第一次为脏的时间 以jiffies为单位unsigned long       dirtied_when;   /* jiffies of first dirtying */struct hlist_node   i_hash;//散列表struct list_head    i_wb_list;  /* backing dev IO list */struct list_head    i_lru;      /* inode LRU list */struct list_head    i_sb_list;//超级块链表union {struct hlist_head   i_dentry;//所有引用该inode的目录项形成的链表struct rcu_head     i_rcu;};u64         i_version;//版本号 inode每次修改后递增atomic_t        i_count;//引用计数atomic_t        i_dio_count;atomic_t        i_writecount;//记录有多少个进程以可写的方式打开此文件const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */struct file_lock    *i_flock;//文件锁链表struct address_space    i_data;
#ifdef CONFIG_QUOTAstruct dquot        *i_dquot[MAXQUOTAS];//inode磁盘限额
#endif/*公用同一个驱动的设备形成链表,比如字符设备,在open时,会根据i_rdev字段查找相应的驱动程序,并使i_cdev字段指向找到的cdev,然后inode添加到struct cdev中的list字段形成的链表中*/struct list_head    i_devices;,union {struct pipe_inode_info  *i_pipe;//如果文件是一个管道则使用i_pipestruct block_device *i_bdev;//如果文件是一个块设备则使用i_bdevstruct cdev     *i_cdev;//如果文件是一个字符设备这使用i_cdev};__u32           i_generation;#ifdef CONFIG_FSNOTIFY//目录通知事件掩码__u32           i_fsnotify_mask; /* all events this inode cares about */struct hlist_head   i_fsnotify_marks;
#endif#ifdef CONFIG_IMAatomic_t        i_readcount; /* struct files open RO */
#endif//存储文件系统或者设备的私有信息void            *i_private; /* fs or device private pointer */
};

实际上,inode是VFS使用的一个对象,用于存放内核在操作文件或目录时所需要的全部信息。索引节点有两种,一种是这里所说的VFS索引节点,存在内存中;另一种是具体文件系统的索引节点,存在于磁盘上,使用时将其读入内存填充VFS的索引节点,之后对VFS索引节点的任何修改都将写回磁盘更新磁盘的索引节点。

对于inod需要知道:

1)对于Unix风格的文件系统来说,这些信息可以从磁盘索引节点直接读入。如果一个文件 系统没有索引节点,那么不管这些相关信息在磁盘上市怎么存放的,文件系统都必须从中提取这些信息。没有索引的文件系统通常将文件的描述信息作为文件的一部分来存放。这些文件系统与Unix风格的文件系统不同,没有将数据与控制信息分开存放。而有些现代的文件系统使用数据库来存储文件的数据。但是不管哪种情况、采用哪种方式,索引节点对象必须在内存中创建,以便文件系统来使用。

2)一个索引节点代表了文件系统的一个文件,在文件创建时创建文件删除时销毁,但是索引节点仅在当文件被访问时,才在内存中创建,且无论有多少个副本访问这个文件,inode只存在一份。

3)inode只是用于描述文件的元数据信息,并不是文件的数据,文件的数据会根据inode的信息存放在一个数据块中(例如:test.txt文件ls -l看到的信息就是它的属性元信息,“hello”数据存放在另一个数据块中)。

4)可以简单理解为ls -l 看到的就是此文件的inode信息。

5)inode可以描述像普通文件、目录这样的磁盘文件,他也可以描述设备或者管道这样的文件,不过这些特殊的文件一般只存在inode块不分配数据块(因为索引节点中有一些特殊文件相关的项,比如i_pipe项就指向一个代表有名管道的数据结构,i_bdev块设备结构体,i_cdev指向字符设备结构体。这三个指针被放在一个共用体中,因为一个给定的索引节点每次只能表示三者之一(或者均不))。

6)有时,某些文件系统可能并不能完整地包含索引节点结构体所要求的所有信息。例如,有的文件系统可能并不记录文件的访问时间,这时,该文件系统可以在实现中选择合适的办法来解决和这个问题。它可以在i_atime中存储0,或者让i_atime等于i_mtime,或者只在内存中更新i_atime而不将其写回磁盘,或者由文件系统 的实现者来决定。

介绍完了inode,接下来看看inode的操作i_op:

struct inode_operations {struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);void * (*follow_link) (struct dentry *, struct nameidata *);int (*permission) (struct inode *, int);struct posix_acl * (*get_acl)(struct inode *, int);int (*readlink) (struct dentry *, char __user *,int);void (*put_link) (struct dentry *, struct nameidata *, void *);int (*create) (struct inode *,struct dentry *, umode_t, bool);int (*link) (struct dentry *,struct inode *,struct dentry *);int (*unlink) (struct inode *,struct dentry *);int (*symlink) (struct inode *,struct dentry *,const char *);int (*mkdir) (struct inode *,struct dentry *,umode_t);int (*rmdir) (struct inode *,struct dentry *);int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);int (*rename) (struct inode *, struct dentry *,struct inode *, struct dentry *);int (*setattr) (struct dentry *, struct iattr *);int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);ssize_t (*listxattr) (struct dentry *, char *, size_t);int (*removexattr) (struct dentry *, const char *);int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,u64 len);int (*update_time)(struct inode *, struct timespec *, int);int (*atomic_open)(struct inode *, struct dentry *,struct file *, unsigned open_flag,umode_t create_mode, int *opened);int (*tmpfile) (struct inode *, struct dentry *, umode_t);int (*set_acl)(struct inode *, struct posix_acl *, int);
} ____cacheline_aligned;

下面介绍常用的各种借口函数:

在给定的节点上,可能是由VFS执行这些函数,也可能由具体的文件系统执行:

该函数在在特定目录中寻找索引节点,改索引节点要对应于dentry中给出的文件名。

struct dentry * (*lookup) (struct inode *dir,struct dentry *dentry , unsigned int )

该函数在在特定目录中寻找索引节点,改索引节点要对应于dentry中给出的文件名。

int (*create) (struct inode *dir,struct dentry *dentry , umode_t mode, bool )

VFS通过系统调用create()和open()来调用改函数,从而为dentry对象创建一个新的索引节点。在创建时使用mode指定初始模式

int (link) (struct dentry *old_denrty,struct inode dir,struct dentry *dentry);

该函数被系统调用link()调用,用来创建硬链接。硬链接名称由dentry指定,连接对象是dir目录中old_denrty目录项所代表的文件。

int (unlink) (struct inode *dir,struct dentry dentry);

该函数被系统调用ulink()调用,从目录dir中删除由目录项dentry指定的索引节点对象。

int (*symlink) (struct inode *dir,struct dentry *dentry ,const char *symname);

该函数被系统调用symlink()调用,创建符号链接。改符号链接的名称由symname指定,连接对象是dir目录中的dentry目录项。

int (*mkdir) (struct inode *dir,struct dentry *dentry ,umode_t mode);

该函数被系统调用mkdir()调用,创建一个新的目录。创建时使用mode指定初始模式。

int (*rmdir) (struct inode *dir,struct dentry *dentry );

该函数被系统调用rmdir()调用,删除dir目录中的dentry 目录项代表的文件。

int (*mknod) (struct inode *dir,struct dentry *dentry ,umode_t mode,dev_t rdev);

该函数被系统调用mknod()调用,创建特殊文件(设备文件、命名管道或套接字)。要创建的文件在dir目录中,其目录项为dentry,关联的设备为rdev,初始权限有mode指定。

int (*rename) (struct inode *old_dir, struct dentry *old_dentry ,struct inode *new_dir ,struct dentry *new_dentry );

VFS调用该函数来移动文件。文件路径在old_dir目录中,源文件由old_dentry目录项指定,目标路径在new_dir中,目标文件由new_dentry指定。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神琪宝贝

团队名称:神琪宝贝团队人员: 姓名:温广琪(组长)学号:1600802130博客:http://www.cnblogs.com/wenwenwgq/技术:C,Java,python,网站兴趣&#xff1a…

汇顶科技2021秋招笔试

来源于读者投稿,作者Angel。笔试时间:2020.08.24,20:00-21:00提醒:很多大公司秋招在七八月份就要投递简历,九月已经晚了。题型:通用部分单选10道 不定项选择题2道 填空题2道 开放题目…

科大讯飞2021笔试题

来源于读者投稿,作者Angel笔试时间:2020.09.12,19:00——21:00岗位:嵌入式软件开发题型:四道编程题,4*1040分题目1、定义一个n*m矩阵,找到两个不在同一行同一列的数字,使…

跨交换机VLAN配置

CCNP实验之&#xff08;跨交换机VLAN&#xff09;<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />跨交换机设置原则:存在一台VLAN服务器&#xff0c;可以存在多台vlan客户端&#xff0c;那么需要配置VTP域。交换机的连接需干线&…

详细记录丨Realtek RTL8188FU WiFi 驱动移植

1 参考资料 1、芯片数据手册&#xff1a;TL8188FCA.pdf2、驱动移植手册&#xff1a;Quick_Start_Guide_for_Driver_Compilation_and_Installation.pdf3、【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.3.pdf4、Linux 添加 WiFi 驱动&#xff1a;https://blog.csdn.net/sbddbfm/…

拆解1968年的美国军用电脑,真的怀疑是“穿越”啊!

来源&#xff1a;数码之家文 | 禅哥这台机器在本人的eBay收藏夹里呆了很久&#xff0c;某日无意间扫了一眼收藏夹&#xff0c;突然发现卖家大降价&#xff0c;只要15刀&#xff0c;还有best offer选项。15刀你买不了吃亏&#xff0c;15刀你买不了上当。事不宜迟果断下手。根据非…

ZJOI2018 Round2 游记

day0 高铁上颓了一部电影,然后闭上眼睛就到了 醒来之后发现被绑了艹,袖子被打了个结,搞了 \(20\) 分钟才解开,真想把绑我的人吊起来 \(xxx\) 公交车上碰到一位长者,被教育了一顿 长者:"你们大学生呐,戴着一副眼镜,肯定不是读书读出来的,玩游戏玩多了吧?" 我:".…

使用PWM实现语音播放

本文转自ARM中文社区&#xff0c;作者&#xff1a;Xiaoya链接&#xff1a;https://community.arm.com/cn/b/blog/posts/nucleof429-2-pwm事实上大部分MCU都可以实现语音播放下面是一段音频数据的波形局部放大图&#xff1a;以一定的速度采样&#xff08;ADC&#xff09;这些波形…

C小项目 —— 学生选课系统

C小项目 —— 学生选课系统#include<stdio.h> #include<windows.h> #include<stdlib.h> #include<conio.h>typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t;#define CLASS_CLS system("cl…

为了杀蚊子,他用树莓派DIY了一把激光枪!

本文经AI新媒体量子位&#xff08;公众号ID&#xff1a;QbitAI&#xff09;授权转载&#xff0c;转载请联系出处。世人苦蚊子久矣。尤其在夏夜&#xff0c;耳边嗡嗡作响&#xff0c;甚至还得与其“挑灯夜战”个三百回合。为此&#xff0c;一个国外博士便DIY了一种高端的杀蚊方式…

java获取操作系统信息

Java代码 import java.util.Properties; Properties propsSystem.getProperties(); //获得系统属性集 String osName props.getProperty("os.name"); //操作系统名称 String osArch props.getProperty("os.arch"); //操作系统构架 String osVe…

scp和sftp常用操作

文件异地直接复制&#xff1a; scp SCP的全称是secure copy (remote file copy program)&#xff0c;此命令是openssh-clients附带的,它的作用就是在机器之间实现拷贝&#xff0c;且机器之间的传输完全是加密的。 最简单的 scp 用法如下&#xff1a; [rootwww ~]# scp [-pr] [-…

SM7250(高通5G)平台LCD bringup

写在前面的话高通平台显示这一块&#xff0c;自从去年开始&#xff0c;高通全面使用SMxxxx命名的芯片比如高端系列&#xff1a;SM8350(骁龙888)&#xff0c;SM8250(骁龙865)&#xff0c;SM8150(骁龙855)中端系列&#xff1a;SM7250&#xff08;骁龙765g&#xff09;&#xff0c…

网络管理人员的未来?

这是流传已久的一张带讽刺性的照片。一名网络专业的学生的未来难道真会如此&#xff1f;或者&#xff0c;是某些人理解错了这个专业的诸多特性&#xff1f;转载于:https://blog.51cto.com/zhangbikai/166694

python笔记-1(import导入、time/datetime/random/os/sys模块)

python笔记-6&#xff08;import导入、time/datetime/random/os/sys模块&#xff09; 一、了解模块导入的基本知识 此部分此处不展开细说import导入&#xff0c;仅写几个点目前的认知即可。其它内容待日后有深入理解了再来细说 1、import可以导入的两种不同的内容 1.1 *.py文件…

嵌入式里如何给内存做压力测试?不妨试试memtester

大家好&#xff0c;我是痞子衡&#xff0c;是正经搞技术的痞子。今天痞子衡给大家介绍的是内存读写正确性压力测试程序memtester。在嵌入式系统中&#xff0c;内存(RAM)的重要性不言而喻&#xff0c;系统性能及稳定性都与内存息息相关。关于内存性能有很多个不同指标&#xff0…

一位嵌入式工程师的成长之路

有些事并不是因为有希望才去坚持&#xff0c;而是因为坚持了才有希望。分享一位嵌入式工程师的成长之路&#xff0c;希望能给朋友一点勉励。刚毕业找不着工作2008年大专毕业后&#xff0c;意气风发南下深圳找工作&#xff0c;想找一份电子技术员的工作&#xff0c;白天上班&…

分享GitHub上一些嵌入式相关的高星开源项目

关于GitHub&#xff0c;可能很多人误以为这是互联网人的专属&#xff0c;其实并不是&#xff0c;那上面嵌入式相关的开源项目是有很多的。现分享一些高星开源项目&#xff08;像RT-Thread、AWTK等大家都熟知的就不介绍了&#xff09;&#xff1a;Avem项目链接&#xff1a;https…

安全四部曲之一---***工具简单使用

所需工具&#xff1a;ASP小旋风5.asp(黑防)鸽子2006ie_xpsp2网马生成器##############Michael分割线################先给大家几个外网路由的地址你们进去捣乱捣乱,没事的,因为没有日志记录用户名密码 全都是admin,别搞太破坏哦如果改动里面的设置,记得把登录密码改了,否则他们…

第 8 章 配置listener监听器

第 8 章 配置listener监听器注意 还记得我们之前讲过的在线列表吗&#xff1f;第 4.2 节 “例子&#xff1a;在线列表”。我们曾经说过那个在线列表无法判断用户非法退出&#xff0c;很可能造成在线列表无限增大&#xff0c;现在我们可以用listener来弥补这一问题了。如果你不满…