utimes函数详解 链接到标题

1. 函数介绍 链接到标题

utimes函数是Linux系统中用于修改文件访问时间和修改时间的函数。它是utime函数的增强版本,提供了微秒级的时间精度。可以把utimes想象成一个"高精度时间修改器",它能够精确地设置文件的时间戳到微秒级别。

与utime函数相比,utimes的主要优势在于它支持更高精度的时间设置,能够满足对时间精度要求较高的应用场景。这在需要精确控制文件时间戳的系统中特别有用。

使用场景:

  • 文件备份和恢复时保持精确时间戳
  • 软件构建系统中的依赖关系管理
  • 测试环境中的时间模拟
  • 文件系统维护和同步
  • 需要微秒级精度的时间控制应用

2. 函数原型 链接到标题

#include <sys/time.h>

int utimes(const char *filename, const struct timeval times[2]);

3. 功能 链接到标题

utimes函数的主要功能是修改指定文件的访问时间和修改时间,支持微秒级精度的时间设置。

4. 参数 链接到标题

  • filename: 文件路径名

    • 类型:const char*
    • 含义:要修改时间戳的文件路径名
  • times: 时间数组

    • 类型:const struct timeval[2]
    • 含义:包含新时间戳的数组
    • times[0]:访问时间(atime)
    • times[1]:修改时间(mtime)
    • 如果为NULL,则设置为当前时间
    • timeval结构体定义:
      struct timeval {
          time_t tv_sec;   // 秒数
          suseconds_t tv_usec;  // 微秒数
      };
      

5. 返回值 链接到标题

  • 成功: 返回0
  • 失败: 返回-1,并设置errno错误码
    • EACCES:权限不足
    • EFAULT:filename指向无效内存
    • EIO:I/O错误
    • ELOOP:符号链接循环
    • ENAMETOOLONG:路径名过长
    • ENOENT:文件不存在
    • ENOTDIR:路径前缀不是目录
    • EPERM:操作不被允许
    • EROFS:文件系统只读

6. 相似函数或关联函数 链接到标题

  • utime(): 基础时间修改函数(秒级精度)
  • futimes(): 通过文件描述符修改时间
  • lutimes(): 修改符号链接时间(不跟随链接)
  • futimens(): 通过文件描述符修改时间(纳秒级精度)
  • utimensat(): 相对于目录文件描述符修改时间
  • stat(): 获取文件状态信息
  • touch命令: 命令行下的时间修改工具

7. 示例代码 链接到标题

示例1:基础utimes使用 - 简单时间修改 链接到标题

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <errno.h>

// 创建测试文件
int create_test_file(const char* filename, const char* content) {
    int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("创建文件失败");
        return -1;
    }
    
    if (write(fd, content, strlen(content)) == -1) {
        perror("写入文件失败");
        close(fd);
        return -1;
    }
    
    close(fd);
    printf("创建文件: %s\n", filename);
    return 0;
}

// 显示文件详细时间信息
void show_detailed_file_times(const char* filename) {
    struct stat file_stat;
    
    if (stat(filename, &file_stat) == -1) {
        perror("获取文件状态失败");
        return;
    }
    
    printf("文件 %s 的详细时间信息:\n", filename);
    
    // 显示访问时间
    struct tm* atime_tm = localtime(&file_stat.st_atime);
    printf("  访问时间: %04d-%02d-%02d %02d:%02d:%02d", 
           atime_tm->tm_year + 1900, atime_tm->tm_mon + 1, atime_tm->tm_mday,
           atime_tm->tm_hour, atime_tm->tm_min, atime_tm->tm_sec);
    #ifdef st_atim
    printf(".%06ld", (long)file_stat.st_atim.tv_nsec / 1000);
    #endif
    printf("\n");
    
    // 显示修改时间
    struct tm* mtime_tm = localtime(&file_stat.st_mtime);
    printf("  修改时间: %04d-%02d-%02d %02d:%02d:%02d", 
           mtime_tm->tm_year + 1900, mtime_tm->tm_mon + 1, mtime_tm->tm_mday,
           mtime_tm->tm_hour, mtime_tm->tm_min, mtime_tm->tm_sec);
    #ifdef st_mtim
    printf(".%06ld", (long)file_stat.st_mtim.tv_nsec / 1000);
    #endif
    printf("\n");
    
    // 显示状态改变时间
    struct tm* ctime_tm = localtime(&file_stat.st_ctime);
    printf("  状态改变时间: %04d-%02d-%02d %02d:%02d:%02d\n", 
           ctime_tm->tm_year + 1900, ctime_tm->tm_mon + 1, ctime_tm->tm_mday,
           ctime_tm->tm_hour, ctime_tm->tm_min, ctime_tm->tm_sec);
}

// 将timeval转换为可读格式
void print_timeval(const char* label, const struct timeval* tv) {
    struct tm* tm_info = localtime(&tv->tv_sec);
    printf("%s: %04d-%02d-%02d %02d:%02d:%02d.%06ld\n",
           label,
           tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
           tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec,
           (long)tv->tv_usec);
}

int main() {
    printf("=== 基础utimes使用示例 ===\n");
    
    const char* test_file = "utimes_test.txt";
    
    // 创建测试文件
    if (create_test_file(test_file, "这是utimes测试文件的内容\n") == -1) {
        exit(EXIT_FAILURE);
    }
    
    // 显示初始时间
    printf("\n1. 初始文件时间:\n");
    show_detailed_file_times(test_file);
    
    // 获取当前时间
    struct timeval current_time;
    if (gettimeofday(&current_time, NULL) == -1) {
        perror("获取当前时间失败");
        unlink(test_file);
        exit(EXIT_FAILURE);
    }
    
    printf("\n当前系统时间: ");
    print_timeval("", &current_time);
    
    // 示例1: 使用utimes设置特定时间(微秒级精度)
    printf("\n2. 使用utimes设置特定时间(微秒级精度):\n");
    
    struct timeval new_times[2];
    // 设置访问时间为当前时间减去1小时,微秒设为123456
    new_times[0].tv_sec = current_time.tv_sec - 3600;  // 1小时前
    new_times[0].tv_usec = 123456;  // 微秒部分
    
    // 设置修改时间为当前时间减去2小时,微秒设为654321
    new_times[1].tv_sec = current_time.tv_sec - 7200;  // 2小时前
    new_times[1].tv_usec = 654321;  // 微秒部分
    
    printf("设置新的时间戳:\n");
    print_timeval("  访问时间", &new_times[0]);
    print_timeval("  修改时间", &new_times[1]);
    
    if (utimes(test_file, new_times) == 0) {
        printf("✓ 时间修改成功\n");
    } else {
        printf("✗ 时间修改失败: %s\n", strerror(errno));
    }
    
    // 显示修改后的时间
    printf("\n修改后的文件时间:\n");
    show_detailed_file_times(test_file);
    
    // 示例2: 使用utimes设置为当前时间
    printf("\n3. 使用utimes设置为当前时间:\n");
    
    if (utimes(test_file, NULL) == 0) {
        printf("✓ 时间设置为当前时间成功\n");
    } else {
        printf("✗ 时间设置失败: %s\n", strerror(errno));
    }
    
    // 显示当前时间的文件
    printf("\n设置为当前时间后的文件时间:\n");
    show_detailed_file_times(test_file);
    
    // 示例3: 设置未来时间(包含微秒)
    printf("\n4. 设置未来时间(包含微秒):\n");
    
    struct timeval future_times[2];
    // 设置为1天后的时间,使用特定的微秒值
    future_times[0].tv_sec = current_time.tv_sec + 86400;  // 1天后
    future_times[0].tv_usec = 987654;  // 特定微秒值
    
    future_times[1].tv_sec = current_time.tv_sec + 172800; // 2天后
    future_times[1].tv_usec = 456789;  // 特定微秒值
    
    printf("设置未来时间戳:\n");
    print_timeval("  访问时间", &future_times[0]);
    print_timeval("  修改时间", &future_times[1]);
    
    if (utimes(test_file, future_times) == 0) {
        printf("✓ 未来时间设置成功\n");
    } else {
        printf("✗ 未来时间设置失败: %s\n", strerror(errno));
    }
    
    show_detailed_file_times(test_file);
    
    // 验证微秒精度
    printf("\n5. 验证微秒精度:\n");
    
    struct stat verify_stat;
    if (stat(test_file, &verify_stat) == 0) {
        printf("验证微秒精度:\n");
        #ifdef st_atim
        printf("  访问时间微秒: %06ld (期望: 987654)\n", 
               (long)verify_stat.st_atim.tv_nsec / 1000);
        #endif
        #ifdef st_mtim
        printf("  修改时间微秒: %06ld (期望: 456789)\n", 
               (long)verify_stat.st_mtim.tv_nsec / 1000);
        #endif
    }
    
    // 清理测试文件
    unlink(test_file);
    
    printf("\n=== 基础utimes演示完成 ===\n");
    
    return 0;
}

示例2:utimes与文件操作的时间关系 链接到标题

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <errno.h>

// 显示完整的timeval信息
void show_complete_times(const char* filename) {
    struct stat file_stat;
    
    if (stat(filename, &file_stat) == -1) {
        perror("获取文件状态失败");
        return;
    }
    
    printf("文件 %s 的完整时间信息:\n", filename);
    
    // 访问时间
    struct tm* atime_tm = localtime(&file_stat.st_atime);
    printf("  访问时间 (atime): %ld.%06ld - %04d-%02d-%02d %02d:%02d:%02d", 
           (long)file_stat.st_atime,
           #ifdef st_atim
           (long)file_stat.st_atim.tv_nsec / 1000,
           #else
           0L,
           #endif
           atime_tm->tm_year + 1900, atime_tm->tm_mon + 1, atime_tm->tm_mday,
           atime_tm->tm_hour, atime_tm->tm_min, atime_tm->tm_sec);
    printf("\n");
    
    // 修改时间
    struct tm* mtime_tm = localtime(&file_stat.st_mtime);
    printf("  修改时间 (mtime): %ld.%06ld - %04d-%02d-%02d %02d:%02d:%02d", 
           (long)file_stat.st_mtime,
           #ifdef st_mtim
           (long)file_stat.st_mtim.tv_nsec / 1000,
           #else
           0L,
           #endif
           mtime_tm->tm_year + 1900, mtime_tm->tm_mon + 1, mtime_tm->tm_mday,
           mtime_tm->tm_hour, mtime_tm->tm_min, mtime_tm->tm_sec);
    printf("\n");
    
    // 状态改变时间
    struct tm* ctime_tm = localtime(&file_stat.st_ctime);
    printf("  状态改变时间 (ctime): %ld - %04d-%02d-%02d %02d:%02d:%02d\n", 
           (long)file_stat.st_ctime,
           ctime_tm->tm_year + 1900, ctime_tm->tm_mon + 1, ctime_tm->tm_mday,
           ctime_tm->tm_hour, ctime_tm->tm_min, ctime_tm->tm_sec);
}

// 读取文件内容
int read_file_content(const char* filename) {
    int fd = open(filename, O_RDONLY);
    if (fd == -1) {
        perror("打开文件失败");
        return -1;
    }
    
    char buffer[256];
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
    if (bytes_read > 0) {
        buffer[bytes_read] = '\0';
        printf("读取内容: %s", buffer);
    }
    
    close(fd);
    return 0;
}

// 写入文件内容
int write_file_content(const char* filename, const char* content) {
    int fd = open(filename, O_WRONLY | O_APPEND);
    if (fd == -1) {
        perror("打开文件失败");
        return -1;
    }
    
    if (write(fd, content, strlen(content)) == -1) {
        perror("写入文件失败");
        close(fd);
        return -1;
    }
    
    close(fd);
    return 0;
}

int main() {
    printf("=== utimes与文件操作时间关系示例 ===\n");
    
    const char* test_file = "time_relationship_test.txt";
    
    // 创建测试文件
    int fd = open(test_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("创建测试文件失败");
        exit(EXIT_FAILURE);
    }
    write(fd, "初始内容\n", 9);
    close(fd);
    
    printf("1. 文件创建后的初始时间:\n");
    show_complete_times(test_file);
    
    // 等待一段时间(确保时间有变化)
    printf("\n等待2秒...\n");
    sleep(2);
    
    // 读取文件(应该更新访问时间)
    printf("\n2. 读取文件后的时间:\n");
    read_file_content(test_file);
    show_complete_times(test_file);
    
    // 再等待一段时间
    printf("\n等待2秒...\n");
    sleep(2);
    
    // 写入文件(应该更新修改时间和状态改变时间)
    printf("\n3. 写入文件后的时间:\n");
    write_file_content(test_file, "追加内容\n");
    show_complete_times(test_file);
    
    // 使用utimes修改时间为历史时间(微秒级)
    printf("\n4. 使用utimes修改时间为历史时间(微秒级):\n");
    
    struct timeval historical_times[2];
    struct timeval current_time;
    gettimeofday(&current_time, NULL);
    
    // 设置为30天前的时间,包含特定微秒值
    historical_times[0].tv_sec = current_time.tv_sec - 86400 * 30;  // 30天前
    historical_times[0].tv_usec = 111111;  // 特定微秒值
    
    historical_times[1].tv_sec = historical_times[0].tv_sec;
    historical_times[1].tv_usec = 222222;  // 不同的微秒值
    
    printf("设置为30天前的时间:\n");
    printf("  目标访问时间: %ld.%06ld\n", 
           (long)historical_times[0].tv_sec, (long)historical_times[0].tv_usec);
    printf("  目标修改时间: %ld.%06ld\n", 
           (long)historical_times[1].tv_sec, (long)historical_times[1].tv_usec);
    
    if (utimes(test_file, historical_times) == 0) {
        printf("✓ 历史时间设置成功\n");
    } else {
        printf("✗ 历史时间设置失败: %s\n", strerror(errno));
    }
    
    show_complete_times(test_file);
    
    // 再次读取文件,观察时间变化
    printf("\n5. 再次读取文件后的时间:\n");
    read_file_content(test_file);
    show_complete_times(test_file);
    
    // 再次写入文件
    printf("\n6. 再次写入文件后的时间:\n");
    write_file_content(test_file, "再次追加内容\n");
    show_complete_times(test_file);
    
    // 演示utimes对ctime的影响
    printf("\n7. 演示utimes对ctime的影响:\n");
    
    // 保存当前ctime
    struct stat stat_before;
    stat(test_file, &stat_before);
    time_t ctime_before = stat_before.st_ctime;
    
    printf("utimes操作前的ctime: %ld\n", (long)ctime_before);
    
    // 执行utimes操作
    struct timeval new_times[2];
    new_times[0].tv_sec = current_time.tv_sec - 1000;
    new_times[0].tv_usec = 333333;
    new_times[1].tv_sec = current_time.tv_sec - 2000;
    new_times[1].tv_usec = 444444;
    
    if (utimes(test_file, new_times) == 0) {
        printf("执行utimes操作成功\n");
    }
    
    // 检查ctime是否改变
    struct stat stat_after;
    stat(test_file, &stat_after);
    time_t ctime_after = stat_after.st_ctime;
    
    printf("utimes操作后的ctime: %ld\n", (long)ctime_after);
    
    if (ctime_before == ctime_after) {
        printf("✓ utimes操作不会改变ctime(在某些系统上)\n");
    } else {
        printf("ℹ utimes操作改变了ctime(系统相关行为)\n");
    }
    
    // 演示微秒级时间控制
    printf("\n8. 微秒级时间控制演示:\n");
    
    // 设置一系列具有不同微秒值的时间
    struct {
        long usec_offset;
        const char* description;
    } microsecond_tests[] = {
        {0, "0微秒"},
        {1, "1微秒"},
        {999999, "999999微秒"},
        {500000, "500000微秒"},
        {123456, "123456微秒"}
    };
    
    int num_tests = sizeof(microsecond_tests) / sizeof(microsecond_tests[0]);
    
    for (int i = 0; i < num_tests; i++) {
        struct timeval test_times[2];
        gettimeofday(&current_time, NULL);
        
        test_times[0].tv_sec = current_time.tv_sec;
        test_times[0].tv_usec = microsecond_tests[i].usec_offset;
        test_times[1].tv_sec = current_time.tv_sec;
        test_times[1].tv_usec = microsecond_tests[i].usec_offset;
        
        if (utimes(test_file, test_times) == 0) {
            printf("  设置时间 %s: 成功\n", microsecond_tests[i].description);
            
            // 验证设置的时间
            struct stat verify_stat;
            if (stat(test_file, &verify_stat) == 0) {
                #ifdef st_atim
                long actual_usec = verify_stat.st_atim.tv_nsec / 1000;
                printf("    实际微秒值: %06ld\n", actual_usec);
                #endif
            }
        } else {
            printf("  设置时间 %s: 失败 (%s)\n", 
                   microsecond_tests[i].description, strerror(errno));
        }
    }
    
    // 清理
    unlink(test_file);
    
    printf("\n=== 时间关系演示完成 ===\n");
    
    return 0;
}

示例3:批量文件时间管理(utimes版本) 链接到标题

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <dirent.h>
#include <errno.h>

#define MAX_FILES 100

// 文件信息结构
typedef struct {
    char filename[256];
    struct timeval atime;
    struct timeval mtime;
    off_t size;
} file_info_t;

// 创建测试文件集合
int create_test_files(const char* directory) {
    // 创建目录
    if (mkdir(directory, 0755) == -1 && errno != EEXIST) {
        perror("创建目录失败");
        return -1;
    }
    
    // 创建测试文件
    const char* filenames[] = {
        "file1.txt", "file2.txt", "file3.txt", 
        "document.pdf", "image.jpg", "data.csv",
        "script.sh", "config.xml", "readme.md"
    };
    
    const char* contents[] = {
        "文件1的内容", "文件2的内容", "文件3的内容",
        "PDF文档内容", "图片文件内容", "CSV数据内容",
        "#!/bin/sh\necho '脚本文件'", "<?xml version='1.0'?><root>XML内容</root>", "# README\n说明文档"
    };
    
    int num_files = sizeof(filenames) / sizeof(filenames[0]);
    
    for (int i = 0; i < num_files; i++) {
        char full_path[512];
        snprintf(full_path, sizeof(full_path), "%s/%s", directory, filenames[i]);
        
        int fd = open(full_path, O_CREAT | O_WRONLY | O_TRUNC, 
                     (i == 6) ? 0755 : 0644);  // script.sh设置可执行权限
        if (fd != -1) {
            write(fd, contents[i], strlen(contents[i]));
            close(fd);
            printf("创建文件: %s\n", full_path);
        }
    }
    
    return 0;
}

// 获取目录中所有文件信息
int get_directory_files(const char* directory, file_info_t files[], int max_files) {
    DIR* dir = opendir(directory);
    if (dir == NULL) {
        perror("打开目录失败");
        return -1;
    }
    
    int count = 0;
    struct dirent* entry;
    
    while ((entry = readdir(dir)) != NULL && count < max_files) {
        // 跳过.和..
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        
        // 构造完整路径
        char full_path[512];
        snprintf(full_path, sizeof(full_path), "%s/%s", directory, entry->d_name);
        
        // 获取文件状态
        struct stat file_stat;
        if (stat(full_path, &file_stat) == 0) {
            strncpy(files[count].filename, full_path, sizeof(files[count].filename) - 1);
            
            // 转换时间格式
            files[count].atime.tv_sec = file_stat.st_atime;
            files[count].mtime.tv_sec = file_stat.st_mtime;
            #ifdef st_atim
            files[count].atime.tv_usec = file_stat.st_atim.tv_nsec / 1000;
            files[count].mtime.tv_usec = file_stat.st_mtim.tv_nsec / 1000;
            #else
            files[count].atime.tv_usec = 0;
            files[count].mtime.tv_usec = 0;
            #endif
            
            files[count].size = file_stat.st_size;
            count++;
        }
    }
    
    closedir(dir);
    return count;
}

// 显示文件列表(包含微秒信息)
void show_file_list_with_microseconds(file_info_t files[], int count) {
    printf("文件列表 (%d 个文件):\n", count);
    printf("%-30s %-25s %-25s %10s\n", "文件名", "修改时间", "访问时间", "大小");
    printf("%-30s %-25s %-25s %10s\n", "------", "--------", "--------", "----");
    
    for (int i = 0; i < count; i++) {
        struct tm* mtime_tm = localtime(&files[i].mtime.tv_sec);
        struct tm* atime_tm = localtime(&files[i].atime.tv_sec);
        
        char mtime_str[32], atime_str[32];
        snprintf(mtime_str, sizeof(mtime_str), "%02d-%02d %02d:%02d:%02d.%06ld",
                 mtime_tm->tm_mon + 1, mtime_tm->tm_mday,
                 mtime_tm->tm_hour, mtime_tm->tm_min, mtime_tm->tm_sec,
                 (long)files[i].mtime.tv_usec);
        
        snprintf(atime_str, sizeof(atime_str), "%02d-%02d %02d:%02d:%02d.%06ld",
                 atime_tm->tm_mon + 1, atime_tm->tm_mday,
                 atime_tm->tm_hour, atime_tm->tm_min, atime_tm->tm_sec,
                 (long)files[i].atime.tv_usec);
        
        // 提取文件名(去掉路径)
        char* filename = strrchr(files[i].filename, '/');
        if (filename) filename++;
        else filename = files[i].filename;
        
        printf("%-30s %-25s %-25s %10ld\n", 
               filename, mtime_str, atime_str, (long)files[i].size);
    }
    printf("\n");
}

// 批量更新文件时间(微秒级精度)
int batch_update_times_with_microseconds(const char* directory, struct timeval new_time) {
    DIR* dir = opendir(directory);
    if (dir == NULL) {
        perror("打开目录失败");
        return -1;
    }
    
    int updated_count = 0;
    struct dirent* entry;
    struct timeval new_times[2];
    new_times[0] = new_time;  // 访问时间
    new_times[1] = new_time;  // 修改时间
    
    while ((entry = readdir(dir)) != NULL) {
        // 跳过.和..
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        
        // 构造完整路径
        char full_path[512];
        snprintf(full_path, sizeof(full_path), "%s/%s", directory, entry->d_name);
        
        // 更新文件时间
        if (utimes(full_path, new_times) == 0) {
            printf("更新文件时间: %s\n", full_path);
            updated_count++;
        } else {
            printf("更新文件时间失败: %s (%s)\n", full_path, strerror(errno));
        }
    }
    
    closedir(dir);
    return updated_count;
}

// 根据文件扩展名设置不同时间(包含微秒)
int update_times_by_extension_with_microseconds(const char* directory) {
    DIR* dir = opendir(directory);
    if (dir == NULL) {
        perror("打开目录失败");
        return -1;
    }
    
    struct timeval now;
    gettimeofday(&now, NULL);
    int updated_count = 0;
    struct dirent* entry;
    
    while ((entry = readdir(dir)) != NULL) {
        // 跳过.和..
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        
        // 构造完整路径
        char full_path[512];
        snprintf(full_path, sizeof(full_path), "%s/%s", directory, entry->d_name);
        
        // 根据扩展名设置不同时间(包含微秒)
        struct timeval ext_times[2];
        char* dot = strrchr(entry->d_name, '.');
        
        if (dot) {
            if (strcmp(dot, ".txt") == 0) {
                ext_times[0].tv_sec = now.tv_sec - 3600;    // 1小时前
                ext_times[0].tv_usec = 111111;              // 特定微秒
                ext_times[1].tv_sec = now.tv_sec - 7200;    // 2小时前
                ext_times[1].tv_usec = 222222;              // 特定微秒
            } else if (strcmp(dot, ".pdf") == 0) {
                ext_times[0].tv_sec = now.tv_sec - 86400;   // 1天前
                ext_times[0].tv_usec = 333333;              // 特定微秒
                ext_times[1].tv_sec = now.tv_sec - 172800;  // 2天前
                ext_times[1].tv_usec = 444444;              // 特定微秒
            } else if (strcmp(dot, ".jpg") == 0) {
                ext_times[0].tv_sec = now.tv_sec - 604800;  // 1周前
                ext_times[0].tv_usec = 555555;              // 特定微秒
                ext_times[1].tv_sec = now.tv_sec - 1209600; // 2周前
                ext_times[1].tv_usec = 666666;              // 特定微秒
            } else if (strcmp(dot, ".sh") == 0) {
                ext_times[0].tv_sec = now.tv_sec - 1800;    // 30分钟前
                ext_times[0].tv_usec = 777777;              // 特定微秒
                ext_times[1].tv_sec = now.tv_sec - 3600;    // 1小时前
                ext_times[1].tv_usec = 888888;              // 特定微秒
            } else {
                ext_times[0] = now;
                ext_times[1] = now;
            }
        } else {
            ext_times[0] = now;
            ext_times[1] = now;
        }
        
        // 更新文件时间
        if (utimes(full_path, ext_times) == 0) {
            printf("根据扩展名更新时间: %s\n", full_path);
            updated_count++;
        }
    }
    
    closedir(dir);
    return updated_count;
}

// 高精度时间戳验证
void verify_microsecond_precision(file_info_t files[], int count) {
    printf("=== 微秒级精度验证 ===\n");
    
    for (int i = 0; i < count && i < 5; i++) {
        struct stat file_stat;
        if (stat(files[i].filename, &file_stat) == 0) {
            printf("文件: %s\n", strrchr(files[i].filename, '/') ? 
                   strrchr(files[i].filename, '/') + 1 : files[i].filename);
            
            #ifdef st_atim
            long expected_usec = files[i].atime.tv_usec;
            long actual_usec = file_stat.st_atim.tv_nsec / 1000;
            printf("  访问时间微秒 - 期望: %06ld, 实际: %06ld, %s\n",
                   expected_usec, actual_usec,
                   (expected_usec == actual_usec) ? "✓ 匹配" : "✗ 不匹配");
            #endif
            
            #ifdef st_mtim
            long expected_musec = files[i].mtime.tv_usec;
            long actual_musec = file_stat.st_mtim.tv_nsec / 1000;
            printf("  修改时间微秒 - 期望: %06ld, 实际: %06ld, %s\n",
                   expected_musec, actual_musec,
                   (expected_musec == actual_musec) ? "✓ 匹配" : "✗ 不匹配");
            #endif
            
            printf("\n");
        }
    }
}

int main() {
    printf("=== 批量文件时间管理(utimes版本)示例 ===\n");
    
    const char* test_dir = "batch_time_test_utimes";
    
    // 创建测试文件集合
    printf("1. 创建测试文件集合:\n");
    if (create_test_files(test_dir) == -1) {
        exit(EXIT_FAILURE);
    }
    
    // 获取并显示初始文件列表
    file_info_t files[MAX_FILES];
    int file_count = get_directory_files(test_dir, files, MAX_FILES);
    
    printf("\n2. 初始文件列表:\n");
    show_file_list_with_microseconds(files, file_count);
    
    // 批量更新所有文件时间为当前时间(微秒级)
    printf("3. 批量更新所有文件时间为当前时间(微秒级):\n");
    struct timeval current_time;
    gettimeofday(&current_time, NULL);
    
    // 设置特定的微秒值来验证精度
    current_time.tv_usec = 999999;  // 设置为最大微秒值
    
    int updated = batch_update_times_with_microseconds(test_dir, current_time);
    printf("成功更新 %d 个文件的时间\n", updated);
    
    // 显示更新后的文件列表
    file_count = get_directory_files(test_dir, files, MAX_FILES);
    printf("\n4. 更新后的文件列表:\n");
    show_file_list_with_microseconds(files, file_count);
    
    // 验证微秒级精度
    verify_microsecond_precision(files, file_count);
    
    // 等待一段时间
    printf("等待3秒...\n");
    sleep(3);
    
    // 根据文件扩展名设置不同时间(包含微秒)
    printf("\n5. 根据文件扩展名设置不同时间(包含微秒):\n");
    updated = update_times_by_extension_with_microseconds(test_dir);
    printf("成功更新 %d 个文件的时间\n", updated);
    
    // 显示最终文件列表
    file_count = get_directory_files(test_dir, files, MAX_FILES);
    printf("\n6. 最终文件列表:\n");
    show_file_list_with_microseconds(files, file_count);
    
    // 演示时间排序(按修改时间)
    printf("\n7. 按修改时间排序的文件列表:\n");
    
    // 简单冒泡排序
    for (int i = 0; i < file_count - 1; i++) {
        for (int j = 0; j < file_count - 1 - i; j++) {
            // 比较秒数
            if (files[j].mtime.tv_sec > files[j + 1].mtime.tv_sec) {
                file_info_t temp = files[j];
                files[j] = files[j + 1];
                files[j + 1] = temp;
            } else if (files[j].mtime.tv_sec == files[j + 1].mtime.tv_sec) {
                // 秒数相同时比较微秒数
                if (files[j].mtime.tv_usec > files[j + 1].mtime.tv_usec) {
                    file_info_t temp = files[j];
                    files[j] = files[j + 1];
                    files[j + 1] = temp;
                }
            }
        }
    }
    
    printf("按修改时间排序 (从旧到新):\n");
    show_file_list_with_microseconds(files, file_count);
    
    // 性能测试
    printf("\n8. 性能测试:\n");
    
    clock_t start_time = clock();
    
    // 快速连续设置时间1000次
    struct timeval test_time;
    gettimeofday(&test_time, NULL);
    
    for (int i = 0; i < 1000; i++) {
        test_time.tv_usec = i % 1000000;  // 变化微秒值
        utimes(files[0].filename, (i % 2 == 0) ? &test_time : NULL);
    }
    
    clock_t end_time = clock();
    double elapsed_time = ((double)(end_time - start_time)) / CLOCKS_PER_SEC;
    
    printf("1000次utimes调用耗时: %.6f 秒\n", elapsed_time);
    printf("平均每次调用: %.6f 毫秒\n", (elapsed_time * 1000) / 1000);
    
    // 清理测试文件
    DIR* dir = opendir(test_dir);
    if (dir) {
        struct dirent* entry;
        while ((entry = readdir(dir)) != NULL) {
            if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
                char full_path[512];
                snprintf(full_path, sizeof(full_path), "%s/%s", test_dir, entry->d_name);
                unlink(full_path);
            }
        }
        closedir(dir);
        rmdir(test_dir);
    }
    
    printf("\n=== 批量文件时间管理演示完成 ===\n");
    
    return 0;
}

示例4:高级时间管理与备份应用(utimes版本) 链接到标题

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <dirent.h>
#include <errno.h>
#include <utime.h>

// 备份记录结构(包含微秒级时间)
typedef struct {
    char original_path[512];
    char backup_path[512];
    struct timeval backup_time;
    struct timeval original_atime;
    struct timeval original_mtime;
} backup_record_t;

#define MAX_BACKUPS 1000

// 全局备份记录数组
static backup_record_t backup_records[MAX_BACKUPS];
static int backup_count = 0;

// 复制文件(保持时间戳,包括微秒)
int copy_file_with_timestamps_microseconds(const char* src, const char* dst) {
    // 获取源文件状态
    struct stat src_stat;
    if (stat(src, &src_stat) == -1) {
        perror("获取源文件状态失败");
        return -1;
    }
    
    // 打开源文件
    int src_fd = open(src, O_RDONLY);
    if (src_fd == -1) {
        perror("打开源文件失败");
        return -1;
    }
    
    // 创建目标文件
    int dst_fd = open(dst, O_CREAT | O_WRONLY | O_TRUNC, src_stat.st_mode);
    if (dst_fd == -1) {
        perror("创建目标文件失败");
        close(src_fd);
        return -1;
    }
    
    // 复制文件内容
    char buffer[8192];
    ssize_t bytes_read, bytes_written;
    
    while ((bytes_read = read(src_fd, buffer, sizeof(buffer))) > 0) {
        bytes_written = write(dst_fd, buffer, bytes_read);
        if (bytes_written != bytes_read) {
            perror("写入目标文件失败");
            close(src_fd);
            close(dst_fd);
            return -1;
        }
    }
    
    close(src_fd);
    close(dst_fd);
    
    // 设置目标文件的时间戳与源文件相同(包括微秒)
    struct timeval timestamps[2];
    
    // 访问时间
    timestamps[0].tv_sec = src_stat.st_atime;
    #ifdef st_atim
    timestamps[0].tv_usec = src_stat.st_atim.tv_nsec / 1000;
    #else
    timestamps[0].tv_usec = 0;
    #endif
    
    // 修改时间
    timestamps[1].tv_sec = src_stat.st_mtime;
    #ifdef st_mtim
    timestamps[1].tv_usec = src_stat.st_mtim.tv_nsec / 1000;
    #else
    timestamps[1].tv_usec = 0;
    #endif
    
    if (utimes(dst, timestamps) == -1) {
        perror("设置目标文件时间戳失败");
        return -1;
    }
    
    printf("复制文件: %s -> %s (保持时间戳,包括微秒)\n", src, dst);
    return 0;
}

// 创建备份(微秒级精度)
int create_backup_microseconds(const char* original_path, const char* backup_dir) {
    if (backup_count >= MAX_BACKUPS) {
        fprintf(stderr, "备份记录已满\n");
        return -1;
    }
    
    // 获取原始文件状态
    struct stat original_stat;
    if (stat(original_path, &original_stat) == -1) {
        perror("获取原始文件状态失败");
        return -1;
    }
    
    // 生成备份文件名(包含时间戳)
    struct timeval now;
    gettimeofday(&now, NULL);
    
    char backup_filename[512];
    char* filename = strrchr(original_path, '/');
    if (filename) filename++;
    else filename = (char*)original_path;
    
    snprintf(backup_filename, sizeof(backup_filename), 
             "%s/%s.%ld.%06ld", backup_dir, filename, 
             (long)now.tv_sec, (long)now.tv_usec);
    
    // 复制文件
    if (copy_file_with_timestamps_microseconds(original_path, backup_filename) == -1) {
        return -1;
    }
    
    // 记录备份信息
    strncpy(backup_records[backup_count].original_path, original_path, 
            sizeof(backup_records[backup_count].original_path) - 1);
    strncpy(backup_records[backup_count].backup_path, backup_filename, 
            sizeof(backup_records[backup_count].backup_path) - 1);
    
    backup_records[backup_count].backup_time = now;
    
    // 原始时间戳(包括微秒)
    backup_records[backup_count].original_atime.tv_sec = original_stat.st_atime;
    backup_records[backup_count].original_mtime.tv_sec = original_stat.st_mtime;
    
    #ifdef st_atim
    backup_records[backup_count].original_atime.tv_usec = original_stat.st_atim.tv_nsec / 1000;
    #else
    backup_records[backup_count].original_atime.tv_usec = 0;
    #endif
    
    #ifdef st_mtim
    backup_records[backup_count].original_mtime.tv_usec = original_stat.st_mtim.tv_nsec / 1000;
    #else
    backup_records[backup_count].original_mtime.tv_usec = 0;
    #endif
    
    backup_count++;
    printf("创建备份: %s -> %s\n", original_path, backup_filename);
    
    return 0;
}

// 恢复备份(保持微秒级精度)
int restore_backup_microseconds(int backup_index) {
    if (backup_index < 0 || backup_index >= backup_count) {
        fprintf(stderr, "无效的备份索引\n");
        return -1;
    }
    
    backup_record_t* record = &backup_records[backup_index];
    
    // 复制备份文件到原位置
    if (copy_file_with_timestamps_microseconds(record->backup_path, record->original_path) == -1) {
        return -1;
    }
    
    // 恢复原始时间戳(包括微秒)
    struct timeval original_times[2];
    original_times[0] = record->original_atime;
    original_times[1] = record->original_mtime;
    
    if (utimes(record->original_path, original_times) == -1) {
        perror("恢复原始时间戳失败");
        return -1;
    }
    
    printf("恢复备份: %s <- %s\n", record->original_path, record->backup_path);
    return 0;
}

// 显示备份列表(包含微秒信息)
void show_backup_list_with_microseconds() {
    if (backup_count == 0) {
        printf("没有备份记录\n");
        return;
    }
    
    printf("备份列表 (%d 个备份):\n", backup_count);
    printf("%-3s %-30s %-30s %-25s\n", "ID", "原始文件", "备份文件", "备份时间");
    printf("%-3s %-30s %-30s %-25s\n", "--", "--------", "--------", "--------");
    
    for (int i = 0; i < backup_count; i++) {
        char* orig_name = strrchr(backup_records[i].original_path, '/');
        if (orig_name) orig_name++;
        else orig_name = backup_records[i].original_path;
        
        char* backup_name = strrchr(backup_records[i].backup_path, '/');
        if (backup_name) backup_name++;
        else backup_name = backup_records[i].backup_path;
        
        struct tm* time_tm = localtime(&backup_records[i].backup_time.tv_sec);
        char time_str[32];
        snprintf(time_str, sizeof(time_str), "%02d-%02d %02d:%02d:%02d.%06ld",
                 time_tm->tm_mon + 1, time_tm->tm_mday,
                 time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec,
                 (long)backup_records[i].backup_time.tv_usec);
        
        printf("%-3d %-30s %-30s %-25s\n", i, orig_name, backup_name, time_str);
    }
    printf("\n");
}

// 创建测试文件(包含微秒级时间戳)
int create_test_file_with_microseconds(const char* filename, const char* content, struct timeval timestamp) {
    int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("创建测试文件失败");
        return -1;
    }
    
    if (write(fd, content, strlen(content)) == -1) {
        perror("写入测试文件失败");
        close(fd);
        return -1;
    }
    
    close(fd);
    
    // 设置特定时间戳(包括微秒)
    struct timeval file_times[2];
    file_times[0] = timestamp;  // 访问时间
    file_times[1] = timestamp;  // 修改时间
    
    if (utimes(filename, file_times) == -1) {
        perror("设置文件时间戳失败");
        return -1;
    }
    
    struct tm* time_tm = localtime(&timestamp.tv_sec);
    printf("创建测试文件: %s (时间戳: %04d-%02d-%02d %02d:%02d:%02d.%06ld)\n", 
           filename,
           time_tm->tm_year + 1900, time_tm->tm_mon + 1, time_tm->tm_mday,
           time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec,
           (long)timestamp.tv_usec);
    
    return 0;
}

// 模拟文件修改场景(微秒级)
void simulate_file_modifications_microseconds(const char* filename) {
    printf("\n模拟文件修改场景(微秒级精度):\n");
    
    // 读取文件(更新访问时间)
    int fd = open(filename, O_RDONLY);
    if (fd != -1) {
        char buffer[256];
        read(fd, buffer, sizeof(buffer));
        close(fd);
        printf("读取文件 %s (更新访问时间)\n", filename);
    }
    
    // 等待
    usleep(500000);  // 0.5秒
    
    // 写入文件(更新修改时间)
    fd = open(filename, O_WRONLY | O_APPEND);
    if (fd != -1) {
        write(fd, "追加内容\n", 9);
        close(fd);
        printf("写入文件 %s (更新修改时间)\n", filename);
    }
    
    // 显示修改后的时间(包括微秒)
    struct stat file_stat;
    if (stat(filename, &file_stat) == 0) {
        printf("修改后的时间:\n");
        struct tm* atime_tm = localtime(&file_stat.st_atime);
        struct tm* mtime_tm = localtime(&file_stat.st_mtime);
        
        printf("  访问时间: %04d-%02d-%02d %02d:%02d:%02d", 
               atime_tm->tm_year + 1900, atime_tm->tm_mon + 1, atime_tm->tm_mday,
               atime_tm->tm_hour, atime_tm->tm_min, atime_tm->tm_sec);
        #ifdef st_atim
        printf(".%06ld", (long)file_stat.st_atim.tv_nsec / 1000);
        #endif
        printf("\n");
        
        printf("  修改时间: %04d-%02d-%02d %02d:%02d:%02d", 
               mtime_tm->tm_year + 1900, mtime_tm->tm_mon + 1, mtime_tm->tm_mday,
               mtime_tm->tm_hour, mtime_tm->tm_min, mtime_tm->tm_sec);
        #ifdef st_mtim
        printf(".%06ld", (long)file_stat.st_mtim.tv_nsec / 1000);
        #endif
        printf("\n");
    }
}

// 时间精度对比测试
void time_precision_comparison_test() {
    printf("=== 时间精度对比测试 ===\n");
    
    const char* test_file = "precision_test.txt";
    
    // 创建测试文件
    int fd = open(test_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd != -1) {
        write(fd, "精度测试", 8);
        close(fd);
    }
    
    // 测试utimes的微秒精度
    printf("1. utimes微秒级精度测试:\n");
    
    for (int i = 0; i < 10; i++) {
        struct timeval test_times[2];
        struct timeval now;
        gettimeofday(&now, NULL);
        
        test_times[0].tv_sec = now.tv_sec;
        test_times[0].tv_usec = i * 100000;  // 0, 100000, 200000, ...
        test_times[1] = test_times[0];
        
        if (utimes(test_file, test_times) == 0) {
            struct stat verify_stat;
            if (stat(test_file, &verify_stat) == 0) {
                #ifdef st_atim
                long actual_usec = verify_stat.st_atim.tv_nsec / 1000;
                printf("  设置微秒: %06ld, 实际微秒: %06ld, %s\n",
                       (long)test_times[0].tv_usec, actual_usec,
                       (test_times[0].tv_usec == actual_usec) ? "✓ 精确" : "✗ 有偏差");
                #endif
            }
        }
    }
    
    // 测试不同时间函数的精度
    printf("\n2. 不同时间函数精度对比:\n");
    
    struct timeval start_time, end_time;
    
    // utimes测试
    gettimeofday(&start_time, NULL);
    struct timeval test_time = start_time;
    test_time.tv_usec = 123456;
    utimes(test_file, &test_time);
    gettimeofday(&end_time, NULL);
    
    double utimes_time = (end_time.tv_sec - start_time.tv_sec) * 1000000.0 +
                        (end_time.tv_usec - start_time.tv_usec);
    printf("  utimes耗时: %.2f 微秒\n", utimes_time);
    
    // utime测试
    struct utimbuf utime_buf;
    utime_buf.actime = start_time.tv_sec;
    utime_buf.modtime = start_time.tv_sec;
    
    gettimeofday(&start_time, NULL);
    utime(test_file, &utime_buf);
    gettimeofday(&end_time, NULL);
    
    double utime_time = (end_time.tv_sec - start_time.tv_sec) * 1000000.0 +
                       (end_time.tv_usec - start_time.tv_usec);
    printf("  utime耗时: %.2f 微秒\n", utime_time);
    
    printf("  精度提升: utimes支持微秒级,utime只支持秒级\n");
    
    unlink(test_file);
    printf("=== 精度对比测试完成 ===\n\n");
}

int main() {
    printf("=== 高级时间管理与备份应用(utimes版本)示例 ===\n");
    
    const char* backup_dir = "microsecond_backups";
    const char* test_file = "precise_file.txt";
    
    // 时间精度对比测试
    time_precision_comparison_test();
    
    // 创建备份目录
    if (mkdir(backup_dir, 0755) == -1 && errno != EEXIST) {
        perror("创建备份目录失败");
        exit(EXIT_FAILURE);
    }
    
    // 创建测试文件(设置为历史时间,包含微秒)
    struct timeval historical_time;
    gettimeofday(&historical_time, NULL);
    historical_time.tv_sec -= 86400 * 30;  // 30天前
    historical_time.tv_usec = 987654;      // 特定微秒值
    
    if (create_test_file_with_microseconds(test_file, "重要内容\n", historical_time) == -1) {
        exit(EXIT_FAILURE);
    }
    
    // 显示初始文件时间(包括微秒)
    struct stat initial_stat;
    stat(test_file, &initial_stat);
    printf("\n初始文件时间:\n");
    printf("  访问时间: %ld.%06ld\n", 
           (long)initial_stat.st_atime,
           #ifdef st_atim
           (long)initial_stat.st_atim.tv_nsec / 1000
           #else
           0L
           #endif
           );
    printf("  修改时间: %ld.%06ld\n", 
           (long)initial_stat.st_mtime,
           #ifdef st_mtim
           (long)initial_stat.st_mtim.tv_nsec / 1000
           #else
           0L
           #endif
           );
    
    // 创建第一次备份
    printf("\n1. 创建第一次备份:\n");
    if (create_backup_microseconds(test_file, backup_dir) == -1) {
        exit(EXIT_FAILURE);
    }
    
    show_backup_list_with_microseconds();
    
    // 模拟文件修改
    simulate_file_modifications_microseconds(test_file);
    
    // 等待一段时间
    usleep(500000);  // 0.5秒
    
    // 创建第二次备份
    printf("\n2. 创建第二次备份:\n");
    if (create_backup_microseconds(test_file, backup_dir) == -1) {
        exit(EXIT_FAILURE);
    }
    
    show_backup_list_with_microseconds();
    
    // 再次修改文件
    printf("\n3. 再次修改文件:\n");
    int fd = open(test_file, O_WRONLY | O_APPEND);
    if (fd != -1) {
        write(fd, "更多重要内容\n", 13);
        close(fd);
        printf("再次修改文件 %s\n", test_file);
    }
    
    // 显示当前文件状态
    struct stat current_stat;
    stat(test_file, &current_stat);
    printf("当前文件时间:\n");
    printf("  访问时间: %ld.%06ld\n", 
           (long)current_stat.st_atime,
           #ifdef st_atim
           (long)current_stat.st_atim.tv_nsec / 1000
           #else
           0L
           #endif
           );
    printf("  修改时间: %ld.%06ld\n", 
           (long)current_stat.st_mtime,
           #ifdef st_mtim
           (long)current_stat.st_mtim.tv_nsec / 1000
           #else
           0L
           #endif
           );
    
    // 创建第三次备份
    printf("\n4. 创建第三次备份:\n");
    if (create_backup_microseconds(test_file, backup_dir) == -1) {
        exit(EXIT_FAILURE);
    }
    
    show_backup_list_with_microseconds();
    
    // 演示备份恢复(保持微秒级精度)
    printf("\n5. 演示备份恢复(保持微秒级精度):\n");
    
    // 恢复到第一次备份
    printf("恢复到第一次备份:\n");
    if (restore_backup_microseconds(0) == 0) {
        struct stat restored_stat;
        stat(test_file, &restored_stat);
        printf("恢复后的文件时间:\n");
        printf("  访问时间: %ld.%06ld\n", 
               (long)restored_stat.st_atime,
               #ifdef st_atim
               (long)restored_stat.st_atim.tv_nsec / 1000
               #else
               0L
               #endif
               );
        printf("  修改时间: %ld.%06ld\n", 
               (long)restored_stat.st_mtime,
               #ifdef st_mtim
               (long)restored_stat.st_mtim.tv_nsec / 1000
               #else
               0L
               #endif
               );
    }
    
    // 恢复到第二次备份
    printf("\n恢复到第二次备份:\n");
    if (restore_backup_microseconds(1) == 0) {
        struct stat restored_stat;
        stat(test_file, &restored_stat);
        printf("恢复后的文件时间:\n");
        printf("  访问时间: %ld.%06ld\n", 
               (long)restored_stat.st_atime,
               #ifdef st_atim
               (long)restored_stat.st_atim.tv_nsec / 1000
               #else
               0L
               #endif
               );
        printf("  修改时间: %ld.%06ld\n", 
               (long)restored_stat.st_mtime,
               #ifdef st_mtim
               (long)restored_stat.st_mtim.tv_nsec / 1000
               #else
               0L
               #endif
               );
    }
    
    // 演示时间戳验证(微秒级)
    printf("\n6. 时间戳验证(微秒级):\n");
    for (int i = 0; i < backup_count; i++) {
        struct stat backup_stat;
        if (stat(backup_records[i].backup_path, &backup_stat) == 0) {
            printf("备份 %d:\n", i);
            printf("  备份文件修改时间: %ld.%06ld\n", 
                   (long)backup_stat.st_mtime,
                   #ifdef st_mtim
                   (long)backup_stat.st_mtim.tv_nsec / 1000
                   #else
                   0L
                   #endif
                   );
            printf("  原始文件修改时间: %ld.%06ld\n", 
                   (long)backup_records[i].original_mtime.tv_sec,
                   (long)backup_records[i].original_mtime.tv_usec);
            
            long backup_usec = 
                #ifdef st_mtim
                backup_stat.st_mtim.tv_nsec / 1000;
                #else
                0L;
                #endif
                
            if (backup_stat.st_mtime == backup_records[i].original_mtime.tv_sec &&
                backup_usec == backup_records[i].original_mtime.tv_usec) {
                printf("  ✓ 时间戳精确匹配(微秒级)\n");
            } else {
                printf("  ✗ 时间戳不匹配\n");
            }
        }
    }
    
    // 演示错误处理
    printf("\n7. 错误处理演示:\n");
    
    // 尝试恢复不存在的备份
    printf("尝试恢复不存在的备份:\n");
    if (restore_backup_microseconds(999) == -1) {
        printf("✓ 正确处理了无效备份索引\n");
    }
    
    // 尝试备份不存在的文件
    printf("尝试备份不存在的文件:\n");
    if (create_backup_microseconds("nonexistent.txt", backup_dir) == -1) {
        printf("✓ 正确处理了不存在的文件\n");
    }
    
    // 清理测试文件
    printf("\n8. 清理测试文件:\n");
    unlink(test_file);
    
    // 清理备份文件
    for (int i = 0; i < backup_count; i++) {
        unlink(backup_records[i].backup_path);
        printf("删除备份文件: %s\n", backup_records[i].backup_path);
    }
    rmdir(backup_dir);
    
    printf("\n=== 高级时间管理与备份应用演示完成 ===\n");
    
    return 0;
}

编译和运行 链接到标题

# 编译示例
gcc -o utimes_example1 utimes_example1.c
gcc -o utimes_example2 utimes_example2.c
gcc -o utimes_example3 utimes_example3.c
gcc -o utimes_example4 utimes_example4.c

# 运行示例
./utimes_example1
./utimes_example2
./utimes_example3
./utimes_example4

重要注意事项 链接到标题

  1. 时间精度: utimes支持微秒级精度,在支持的系统上可以精确到微秒
  2. 权限要求: 需要对文件有写权限或具有特殊权限(如CAP_FOWNER)
  3. ctime影响: utimes操作通常会更新文件的状态改变时间(ctime)
  4. 符号链接: utimes会跟随符号链接修改目标文件
  5. 目录时间: 可以修改目录的时间戳
  6. 原子性: utimes操作是原子的
  7. 错误处理: 必须检查返回值并适当处理错误
  8. 系统差异: 不同系统对微秒精度的支持可能有差异

最佳实践 链接到标题

  1. 使用安全包装函数: 对utimes进行封装以提供更好的错误处理
  2. 检查返回值: 始终检查函数返回值
  3. 权限检查: 在修改时间前检查必要的权限
  4. 时间验证: 验证设置的时间是否合理
  5. 批量操作: 在批量操作时考虑性能优化
  6. 错误日志: 记录时间修改操作的详细信息
  7. 备份策略: 在重要文件时间修改前考虑备份
  8. 精度要求: 根据应用需求选择合适的时间精度函数

通过这些示例,你可以理解utimes在文件时间管理方面的强大功能,它为Linux系统提供了微秒级精度的时间控制能力,特别适用于需要精确时间戳管理的备份、同步和测试等场景。