stat
结构体中的成员 st_atime
、 st_mtime
、 st_ctime
字段表示文件时间戳,分别记录了对文件的上次访问时间、上次修改时间,以及文件状态上次发生变更的时间。三个字段类型都是 time_t
,对时间戳的记录形式为自1970年1月1日到当前系统时间经历的秒数,即标准的UNIX时间戳。
使用 utime()
函数或与之相关的函数接口,可改变存储于文件 i
节点中的文件上次访问时间戳和上次修改时间戳。
理解 i
节点,要从文件存储说起。文件存储在硬盘上,硬盘的最小单位叫作扇区( sector
)。每个扇区存储 512
字节(相当于 0.5KB
)。操作系统读硬盘的时候,不是一个个扇区地读,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个“块”( block
)。这种由多个扇区组成的“块”,是文件存取的最小单位。“块”的大小,最常见的是 4KB
,即连续八个扇区组成一个块。文件数据都存储在“块”中,那么显然,我们还必须找到一个地方存储文件的元信息,如文件的创建者、文件的创建日期、文件的大小等。这种存储文件元信息的区域叫作索引节点( inode
)。
#include <sys/types.h> #include <utime.h> int utime(const char *filename, const struct utimbuf *times);点击复制复制失败已复制
参数 filename
用来指定要修改时间的文件,若该参数为符号链接,则会进一步解引用。参数 times
既可为 NULL
,也可以为指向 utimbuf
结构的指针。
struct utimbuf { time_t actime; // access time time_t modtime; // modificatI/On time }点击复制复制失败已复制
utime()
函数的运作方式则视以下两种不同情况而定。
- 如果
buf
为NULL
,那么utime()
函数会将文件的上一次访问时间和修改时间同时设置为当前时间。 - 若将
buf
指定为指向utimbuf
结构体的指针,utime()
函数则会使用该结构的相应字段去更新文件的上次访问时间和修改时间。
为更改文件时间戳中的一项,可以先利用 stat()
函数来获取两个时间,并使用其中之一来初始化 utimbuf
结构体,然后再将另一个时间置为期望值,如下所示:
#include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <utime.h> int main(int argc, const char *argv[]) { struct stat buf; struct utimbuf utimbuf; if (stat(argv[1], &buf) == -1) { printf("stat error\n"); return -1; } utimbuf.actime = buf.st_atime; utimbuf.modtime = buf.st_atime; if (utime(argv[2], &utimbuf) == -1) { printf("utime error\n"); return -1; } return 0; }点击复制复制失败已复制
上述代码,只要 utime()
函数调用成功,就会将文件的上次状态更改时间置为当前时间。 argv[1]
和 argv[2]
为同一个命令行参数。
Linux
还提供了源于 BSD
( Berkeley Software Distribution
,伯克利软件套件)的 utimes()
函数的接口,其功能类似于 utime()
函数。
#include <sys/time.h> int utimes(const char *filename, const struct timeval times[2]);点击复制复制失败已复制
utime()
函数和 utimes()
函数之间最显著的差别在于后者可以以微秒级精度来指定时间值, timeval
结构体如下:
struct timeval { long tv_sec; // seconds秒 long tv_usec; // microseconds微秒 }点击复制复制失败已复制
futimes()
库函数和 lutimes()
库函数的功能与 utimes()
函数大同小异。前两者与后者之间的差异在于,用来指定更改时间戳文件的参数不同。
#include <sys/time.h> int futimes(int fd, const struct timeval tv[2]); int lutimes(const char *filename, const struct timeval tv[2]);点击复制复制失败已复制
调用 futimes()
库函数时,使用打开文件描述符fd
来指定文件。
调用 lutimes()
库函数时,使用路径名来指定文件。有别于调用 utimes()
函数的是:对于 lutimes()
库函数来说,若路径名指向一符号链接,则调用不会对该链接进行解引用,而是更改链接自身的时间戳。