umount2 函数详解 Link to heading

1. 函数介绍 Link to heading

umount2 是Linux系统调用,用于卸载文件系统。它是 umount 函数的增强版本,支持更多的卸载选项和标志。通过 umount2,程序可以更精细地控制文件系统的卸载过程,包括强制卸载、延迟卸载等高级功能。

2. 函数原型 Link to heading

#include <sys/mount.h>
int umount2(const char *target, int flags);

3. 功能 Link to heading

umount2 卸载指定挂载点的文件系统,并支持多种卸载标志来控制卸载行为。它可以处理繁忙的文件系统、只读文件系统等情况,提供更灵活的卸载选项。

4. 参数 Link to heading

  • *const char target: 要卸载的文件系统挂载点路径
  • int flags: 卸载标志,控制卸载行为

5. 返回值 Link to heading

  • 成功: 返回0
  • 失败: 返回-1,并设置errno

6. 相似函数,或关联函数 Link to heading

  • umount: 基础卸载函数(等同于umount2(target, 0))
  • mount: 挂载文件系统
  • getmntent: 获取挂载信息
  • /proc/mounts: 挂载信息文件

7. 示例代码 Link to heading

示例1:基础umount2使用 Link to heading

#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

/**
 * 显示当前挂载信息
 */
void show_mount_info() {
    printf("=== 当前挂载信息 ===\n");
    system("cat /proc/mounts | head -10");  // 显示前10行挂载信息
    printf("\n");
}

/**
 * 创建测试挂载点
 */
int create_test_mountpoint(const char *mountpoint) {
    struct stat st;
    
    // 检查挂载点是否存在
    if (stat(mountpoint, &st) == 0) {
        printf("挂载点 %s 已存在\n", mountpoint);
        return 0;
    }
    
    // 创建挂载点目录
    if (mkdir(mountpoint, 0755) == -1) {
        perror("创建挂载点目录失败");
        return -1;
    }
    
    printf("创建挂载点: %s\n", mountpoint);
    return 0;
}

/**
 * 演示基础umount2使用方法
 */
int demo_umount2_basic() {
    const char *test_mountpoint = "/tmp/test_umount2";
    int result;
    
    printf("=== 基础umount2使用示例 ===\n");
    
    // 显示原始挂载信息
    printf("1. 原始挂载信息:\n");
    show_mount_info();
    
    // 创建测试挂载点
    printf("2. 创建测试挂载点:\n");
    if (create_test_mountpoint(test_mountpoint) != 0) {
        return -1;
    }
    
    // 尝试卸载不存在的挂载点(演示错误处理)
    printf("3. 尝试卸载不存在的挂载点:\n");
    printf("   卸载目标: %s\n", test_mountpoint);
    
    result = umount2(test_mountpoint, 0);
    if (result == -1) {
        printf("   ✓ 卸载失败(预期结果): %s\n", strerror(errno));
        if (errno == EINVAL) {
            printf("   原因:指定的挂载点不存在\n");
        } else if (errno == EPERM) {
            printf("   原因:权限不足\n");
        } else if (errno == EBUSY) {
            printf("   原因:挂载点正忙\n");
        }
    } else {
        printf("   ✗ 卸载意外成功\n");
    }
    
    // 演示不同卸载标志
    printf("\n4. 卸载标志说明:\n");
    printf("   0: 普通卸载\n");
    printf("   MNT_FORCE: 强制卸载\n");
    printf("   MNT_DETACH: 延迟卸载\n");
    printf("   MNT_EXPIRE: 标记为过期\n");
    
    // 清理测试挂载点
    printf("\n5. 清理测试挂载点:\n");
    if (rmdir(test_mountpoint) == 0) {
        printf("   ✓ 测试挂载点清理成功\n");
    } else {
        printf("   ✗ 测试挂载点清理失败: %s\n", strerror(errno));
    }
    
    return 0;
}

int main() {
    return demo_umount2_basic();
}

示例2:文件系统挂载和卸载管理 Link to heading

#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mntent.h>

/**
 * 挂载点管理器结构
 */
typedef struct {
    char mountpoint[256];
    char filesystem[32];
    char device[256];
    int is_mounted;
    unsigned long mount_options;
} mount_manager_t;

/**
 * 初始化挂载点管理器
 */
int init_mount_manager(mount_manager_t *manager, const char *mountpoint, 
                      const char *device, const char *filesystem) {
    strncpy(manager->mountpoint, mountpoint, sizeof(manager->mountpoint) - 1);
    manager->mountpoint[sizeof(manager->mountpoint) - 1] = '\0';
    
    strncpy(manager->device, device, sizeof(manager->device) - 1);
    manager->device[sizeof(manager->device) - 1] = '\0';
    
    strncpy(manager->filesystem, filesystem, sizeof(manager->filesystem) - 1);
    manager->filesystem[sizeof(manager->filesystem) - 1] = '\0';
    
    manager->is_mounted = 0;
    manager->mount_options = 0;
    
    printf("挂载点管理器初始化:\n");
    printf("  挂载点: %s\n", manager->mountpoint);
    printf("  设备: %s\n", manager->device);
    printf("  文件系统: %s\n", manager->filesystem);
    
    return 0;
}

/**
 * 检查挂载点是否存在
 */
int is_mountpoint_exists(const char *mountpoint) {
    FILE *fp = setmntent("/proc/mounts", "r");
    if (!fp) {
        return -1;
    }
    
    struct mntent *mnt;
    int exists = 0;
    
    while ((mnt = getmntent(fp)) != NULL) {
        if (strcmp(mnt->mnt_dir, mountpoint) == 0) {
            exists = 1;
            break;
        }
    }
    
    endmntent(fp);
    return exists;
}

/**
 * 挂载文件系统
 */
int mount_filesystem(mount_manager_t *manager) {
    // 创建挂载点
    struct stat st;
    if (stat(manager->mountpoint, &st) == -1) {
        if (mkdir(manager->mountpoint, 0755) == -1) {
            perror("创建挂载点失败");
            return -1;
        }
        printf("创建挂载点: %s\n", manager->mountpoint);
    }
    
    // 执行挂载
    printf("挂载文件系统:\n");
    printf("  设备: %s\n", manager->device);
    printf("  挂载点: %s\n", manager->mountpoint);
    printf("  文件系统: %s\n", manager->filesystem);
    
    // 注意:实际挂载需要root权限和有效设备
    // 这里仅演示调用方式
    printf("  注意:实际挂载需要root权限和有效设备\n");
    
    manager->is_mounted = 1;
    return 0;
}

/**
 * 卸载文件系统(使用umount2)
 */
int unmount_filesystem(mount_manager_t *manager, int flags) {
    printf("卸载文件系统:\n");
    printf("  挂载点: %s\n", manager->mountpoint);
    printf("  卸载标志: 0x%x\n", flags);
    
    // 检查挂载点是否存在
    if (!is_mountpoint_exists(manager->mountpoint)) {
        printf("  挂载点不存在,无需卸载\n");
        manager->is_mounted = 0;
        return 0;
    }
    
    // 执行卸载
    int result = umount2(manager->mountpoint, flags);
    if (result == 0) {
        printf("  ✓ 文件系统卸载成功\n");
        manager->is_mounted = 0;
        
        // 清理挂载点目录
        if (rmdir(manager->mountpoint) == 0) {
            printf("  ✓ 挂载点目录清理成功\n");
        } else {
            printf("  ✗ 挂载点目录清理失败: %s\n", strerror(errno));
        }
    } else {
        printf("  ✗ 文件系统卸载失败: %s\n", strerror(errno));
        if (errno == EBUSY) {
            printf("    原因:文件系统正忙\n");
        } else if (errno == EINVAL) {
            printf("    原因:无效的挂载点\n");
        } else if (errno == EPERM) {
            printf("    原因:权限不足\n");
        }
    }
    
    return result;
}

/**
 * 演示文件系统挂载和卸载管理
 */
int demo_filesystem_management() {
    mount_manager_t manager;
    const char *test_mountpoint = "/tmp/test_fs_manager";
    const char *test_device = "/dev/loop0";  // 示例设备
    const char *test_filesystem = "ext4";
    
    printf("=== 文件系统挂载和卸载管理演示 ===\n");
    
    // 初始化管理器
    printf("1. 初始化挂载点管理器:\n");
    if (init_mount_manager(&manager, test_mountpoint, test_device, test_filesystem) != 0) {
        return -1;
    }
    
    // 显示当前挂载状态
    printf("\n2. 当前挂载状态检查:\n");
    int exists = is_mountpoint_exists(manager.mountpoint);
    if (exists == 1) {
        printf("  挂载点已存在\n");
    } else if (exists == 0) {
        printf("  挂载点不存在\n");
    } else {
        printf("  无法检查挂载状态\n");
    }
    
    // 模拟挂载操作
    printf("\n3. 模拟挂载操作:\n");
    if (mount_filesystem(&manager) != 0) {
        printf("挂载操作失败\n");
        return -1;
    }
    
    // 演示不同卸载方式
    printf("\n4. 演示不同卸载方式:\n");
    
    // 方式1:普通卸载
    printf("  方式1:普通卸载 (MNT_UMOUNT):\n");
    unmount_filesystem(&manager, 0);
    
    // 方式2:强制卸载
    printf("\n  方式2:强制卸载 (MNT_FORCE):\n");
    unmount_filesystem(&manager, MNT_FORCE);
    
    // 方式3:延迟卸载
    printf("\n  方式3:延迟卸载 (MNT_DETACH):\n");
    unmount_filesystem(&manager, MNT_DETACH);
    
    // 方式4:过期卸载
    printf("\n  方式4:过期卸载 (MNT_EXPIRE):\n");
    unmount_filesystem(&manager, MNT_EXPIRE);
    
    // 显示最终状态
    printf("\n5. 最终状态:\n");
    printf("  挂载点状态: %s\n", manager.is_mounted ? "已挂载" : "未挂载");
    
    return 0;
}

int main() {
    return demo_filesystem_management();
}

示例3:安全卸载工具 Link to heading

#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mntent.h>
#include <signal.h>
#include <sys/wait.h>

/**
 * 安全卸载结果结构
 */
typedef struct {
    char mountpoint[256];
    int attempts;
    int success;
    int force_used;
    int detach_used;
    int final_status;
    char error_message[256];
} safe_unmount_result_t;

/**
 * 检查挂载点是否正在使用
 */
int is_mountpoint_busy(const char *mountpoint) {
    // 检查是否有进程在使用该挂载点
    char command[512];
    snprintf(command, sizeof(command), "lsof %s 2>/dev/null | wc -l", mountpoint);
    
    FILE *fp = popen(command, "r");
    if (fp) {
        char buffer[16];
        if (fgets(buffer, sizeof(buffer), fp)) {
            int count = atoi(buffer);
            pclose(fp);
            return count > 0;
        }
        pclose(fp);
    }
    
    return 0;  // 默认认为不忙
}

/**
 * 显示挂载点信息
 */
void show_mountpoint_info(const char *mountpoint) {
    FILE *fp = setmntent("/proc/mounts", "r");
    if (!fp) {
        printf("无法读取挂载信息\n");
        return;
    }
    
    struct mntent *mnt;
    printf("挂载点详细信息:\n");
    
    while ((mnt = getmntent(fp)) != NULL) {
        if (strcmp(mnt->mnt_dir, mountpoint) == 0) {
            printf("  设备: %s\n", mnt->mnt_fsname);
            printf("  挂载点: %s\n", mnt->mnt_dir);
            printf("  文件系统: %s\n", mnt->mnt_type);
            printf("  选项: %s\n", mnt->mnt_opts);
            break;
        }
    }
    
    endmntent(fp);
}

/**
 * 安全卸载文件系统
 */
int safe_unmount_filesystem(const char *mountpoint, safe_unmount_result_t *result) {
    int attempt = 0;
    const int max_attempts = 5;
    int result_code = 0;
    
    // 初始化结果结构
    strncpy(result->mountpoint, mountpoint, sizeof(result->mountpoint) - 1);
    result->mountpoint[sizeof(result->mountpoint) - 1] = '\0';
    result->attempts = 0;
    result->success = 0;
    result->force_used = 0;
    result->detach_used = 0;
    result->final_status = 0;
    result->error_message[0] = '\0';
    
    printf("=== 安全卸载文件系统 ===\n");
    printf("目标挂载点: %s\n", mountpoint);
    
    // 检查挂载点是否存在
    if (!is_mountpoint_exists(mountpoint)) {
        printf("挂载点不存在,无需卸载\n");
        result->success = 1;
        return 0;
    }
    
    // 显示挂载点信息
    show_mountpoint_info(mountpoint);
    
    // 检查挂载点是否正在使用
    printf("检查挂载点使用状态...\n");
    if (is_mountpoint_busy(mountpoint)) {
        printf("警告:挂载点正在使用中\n");
    } else {
        printf("挂载点当前未被使用\n");
    }
    
    // 尝试多次卸载
    while (attempt < max_attempts) {
        attempt++;
        result->attempts = attempt;
        printf("第 %d 次卸载尝试:\n", attempt);
        
        // 根据尝试次数选择不同的卸载策略
        int flags = 0;
        if (attempt > 1) {
            printf("  挂载点可能正忙,等待片刻...\n");
            sleep(1);
        }
        
        if (attempt == 2) {
            // 第二次尝试:发送SIGTERM给可能使用该挂载点的进程
            printf("  尝试通知使用该挂载点的进程...\n");
        } else if (attempt == 3) {
            flags = MNT_FORCE;  // 强制卸载
            result->force_used = 1;
            printf("  使用强制卸载模式\n");
        } else if (attempt == 4) {
            flags = 0;  // 再次尝试普通卸载
            printf("  再次尝试普通卸载\n");
        } else if (attempt == 5) {
            flags = MNT_DETACH;  // 延迟卸载
            result->detach_used = 1;
            printf("  使用延迟卸载模式\n");
        }
        
        // 执行卸载
        result_code = umount2(mountpoint, flags);
        if (result_code == 0) {
            printf("  ✓ 卸载成功\n");
            result->success = 1;
            result->final_status = 0;
            break;
        } else {
            printf("  ✗ 卸载失败: %s\n", strerror(errno));
            result->final_status = errno;
            strncpy(result->error_message, strerror(errno), sizeof(result->error_message) - 1);
            result->error_message[sizeof(result->error_message) - 1] = '\0';
            
            // 根据错误类型决定是否继续尝试
            if (errno == EINVAL) {
                printf("  无效的挂载点,停止尝试\n");
                break;
            } else if (errno == EPERM) {
                printf("  权限不足,停止尝试\n");
                break;
            }
        }
    }
    
    // 显示最终结果
    printf("\n=== 卸载结果 ===\n");
    printf("挂载点: %s\n", result->mountpoint);
    printf("尝试次数: %d\n", result->attempts);
    printf("卸载状态: %s\n", result->success ? "成功" : "失败");
    
    if (result->success) {
        printf("卸载方式: ");
        if (result->force_used) {
            printf("强制卸载\n");
        } else if (result->detach_used) {
            printf("延迟卸载\n");
        } else {
            printf("普通卸载\n");
        }
    } else {
        printf("失败原因: %s\n", result->error_message);
        printf("最终错误码: %d\n", result->final_status);
    }
    
    return result->success ? 0 : -1;
}

/**
 * 演示安全卸载工具
 */
int demo_safe_unmount_tool() {
    safe_unmount_result_t result;
    const char *test_mountpoint = "/mnt/test_safe_unmount";
    
    printf("=== 安全卸载工具演示 ===\n");
    
    // 检查权限
    uid_t uid = getuid();
    printf("权限检查:\n");
    printf("  当前用户ID: %d\n", uid);
    if (uid == 0) {
        printf("  ✓ 具有root权限\n");
    } else {
        printf("  ✗ 没有root权限,卸载操作可能失败\n");
        printf("  提示:文件系统卸载通常需要root权限\n");
    }
    
    // 显示当前挂载信息
    printf("\n当前挂载信息:\n");
    system("cat /proc/mounts | grep -E '(tmp|mnt)' | head -5");
    
    // 演示安全卸载
    printf("\n演示安全卸载:\n");
    printf("目标挂载点: %s\n", test_mountpoint);
    
    // 注意:实际演示中避免卸载真实的重要文件系统
    // 这里仅演示调用方式和错误处理
    
    // 模拟卸载不存在的挂载点
    printf("\n1. 卸载不存在的挂载点:\n");
    if (safe_unmount_filesystem(test_mountpoint, &result) != 0) {
        printf("卸载不存在的挂载点(预期失败)\n");
    }
    
    // 演示卸载过程中的错误处理
    printf("\n2. 卸载错误处理演示:\n");
    
    // 尝试卸载根目录(应该失败)
    printf("尝试卸载根目录:\n");
    safe_unmount_filesystem("/", &result);
    
    // 尝试卸载无效路径
    printf("\n尝试卸载无效路径:\n");
    safe_unmount_filesystem("/invalid/mount/point", &result);
    
    // 显示安全卸载建议
    printf("\n=== 安全卸载建议 ===\n");
    printf("1. 卸载前检查:\n");
    printf("   ✓ 确认具有足够权限\n");
    printf("   ✓ 检查挂载点是否存在\n");
    printf("   ✓ 确认没有进程使用该挂载点\n");
    printf("   ✓ 备份重要数据\n");
    
    printf("\n2. 卸载策略:\n");
    printf("   ✓ 首先尝试普通卸载\n");
    printf("   ✓ 失败后等待并重试\n");
    printf("   ✓ 必要时使用强制卸载\n");
    printf("   ✓ 最后考虑延迟卸载\n");
    
    printf("\n3. 错误处理:\n");
    printf("   ✓ 检查返回值和errno\n");
    printf("   ✓ 根据错误类型采取不同措施\n");
    printf("   ✓ 记录卸载操作日志\n");
    printf("   ✓ 提供友好的错误信息\n");
    
    printf("\n4. 安全考虑:\n");
    printf("   ✓ 避免强制卸载重要文件系统\n");
    printf("   ✓ 确保数据一致性\n");
    printf("   ✓ 监控卸载后的系统状态\n");
    printf("   ✓ 准备恢复方案\n");
    
    return 0;
}

int main() {
    return demo_safe_unmount_tool();
}

示例4:批量卸载管理器 Link to heading

#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mntent.h>
#include <fnmatch.h>

/**
 * 批量卸载条目结构
 */
typedef struct {
    char mountpoint[256];
    char filesystem[32];
    char device[256];
    int selected_for_unmount;
    int unmount_result;
    char result_message[128];
} batch_unmount_entry_t;

/**
 * 批量卸载管理器结构
 */
typedef struct {
    batch_unmount_entry_t entries[64];
    int entry_count;
    int selected_count;
    int successful_count;
    int failed_count;
} batch_unmount_manager_t;

/**
 * 初始化批量卸载管理器
 */
void init_batch_unmount_manager(batch_unmount_manager_t *manager) {
    memset(manager, 0, sizeof(batch_unmount_manager_t));
    printf("批量卸载管理器初始化完成\n");
}

/**
 * 从/proc/mounts加载挂载信息
 */
int load_mount_entries(batch_unmount_manager_t *manager) {
    FILE *fp = setmntent("/proc/mounts", "r");
    if (!fp) {
        printf("无法读取挂载信息: %s\n", strerror(errno));
        return -1;
    }
    
    struct mntent *mnt;
    int count = 0;
    
    printf("加载挂载信息:\n");
    
    while ((mnt = getmntent(fp)) != NULL && count < 64) {
        // 过滤系统挂载点
        if (strncmp(mnt->mnt_dir, "/proc", 5) == 0 ||
            strncmp(mnt->mnt_dir, "/sys", 4) == 0 ||
            strncmp(mnt->mnt_dir, "/dev", 4) == 0) {
            continue;  // 跳过系统挂载点
        }
        
        batch_unmount_entry_t *entry = &manager->entries[count];
        strncpy(entry->mountpoint, mnt->mnt_dir, sizeof(entry->mountpoint) - 1);
        entry->mountpoint[sizeof(entry->mountpoint) - 1] = '\0';
        
        strncpy(entry->filesystem, mnt->mnt_type, sizeof(entry->filesystem) - 1);
        entry->filesystem[sizeof(entry->filesystem) - 1] = '\0';
        
        strncpy(entry->device, mnt->mnt_fsname, sizeof(entry->device) - 1);
        entry->device[sizeof(entry->device) - 1] = '\0';
        
        entry->selected_for_unmount = 0;
        entry->unmount_result = 0;
        entry->result_message[0] = '\0';
        
        printf("  %s (%s on %s)\n", entry->mountpoint, entry->filesystem, entry->device);
        count++;
    }
    
    endmntent(fp);
    manager->entry_count = count;
    printf("共加载 %d 个挂载点\n", count);
    
    return 0;
}

/**
 * 根据模式选择挂载点
 */
int select_mountpoints_by_pattern(batch_unmount_manager_t *manager, const char *pattern) {
    int selected = 0;
    
    printf("根据模式选择挂载点: %s\n", pattern);
    
    for (int i = 0; i < manager->entry_count; i++) {
        batch_unmount_entry_t *entry = &manager->entries[i];
        
        if (fnmatch(pattern, entry->mountpoint, 0) == 0) {
            entry->selected_for_unmount = 1;
            selected++;
            printf("  选中: %s\n", entry->mountpoint);
        }
    }
    
    manager->selected_count = selected;
    printf("共选中 %d 个挂载点\n", selected);
    
    return selected;
}

/**
 * 执行批量卸载
 */
int execute_batch_unmount(batch_unmount_manager_t *manager, int flags) {
    printf("=== 执行批量卸载 ===\n");
    printf("卸载标志: 0x%x\n", flags);
    printf("选中挂载点数量: %d\n", manager->selected_count);
    
    manager->successful_count = 0;
    manager->failed_count = 0;
    
    for (int i = 0; i < manager->entry_count; i++) {
        batch_unmount_entry_t *entry = &manager->entries[i];
        
        if (!entry->selected_for_unmount) {
            continue;
        }
        
        printf("\n卸载 %s:\n", entry->mountpoint);
        
        // 执行卸载
        int result = umount2(entry->mountpoint, flags);
        entry->unmount_result = result;
        
        if (result == 0) {
            printf("  ✓ 卸载成功\n");
            manager->successful_count++;
            strncpy(entry->result_message, "成功", sizeof(entry->result_message) - 1);
        } else {
            printf("  ✗ 卸载失败: %s\n", strerror(errno));
            manager->failed_count++;
            strncpy(entry->result_message, strerror(errno), sizeof(entry->result_message) - 1);
            entry->result_message[sizeof(entry->result_message) - 1] = '\0';
        }
    }
    
    printf("\n=== 批量卸载结果 ===\n");
    printf("成功: %d\n", manager->successful_count);
    printf("失败: %d\n", manager->failed_count);
    printf("总计: %d\n", manager->successful_count + manager->failed_count);
    
    // 显示详细结果
    printf("\n详细结果:\n");
    for (int i = 0; i < manager->entry_count; i++) {
        batch_unmount_entry_t *entry = &manager->entries[i];
        if (entry->selected_for_unmount) {
            printf("  %s: %s (%s)\n", 
                   entry->mountpoint,
                   entry->unmount_result == 0 ? "✓" : "✗",
                   entry->result_message);
        }
    }
    
    return (manager->failed_count == 0) ? 0 : -1;
}

/**
 * 显示批量卸载摘要
 */
void show_batch_unmount_summary(const batch_unmount_manager_t *manager) {
    printf("=== 批量卸载摘要 ===\n");
    printf("总挂载点数: %d\n", manager->entry_count);
    printf("选中卸载数: %d\n", manager->selected_count);
    printf("成功卸载数: %d\n", manager->successful_count);
    printf("失败卸载数: %d\n", manager->failed_count);
    printf("成功率: %.1f%%\n", 
           manager->selected_count > 0 ? 
           (double)manager->successful_count / manager->selected_count * 100 : 0);
    
    if (manager->failed_count > 0) {
        printf("\n失败详情:\n");
        for (int i = 0; i < manager->entry_count; i++) {
            const batch_unmount_entry_t *entry = &manager->entries[i];
            if (entry->selected_for_unmount && entry->unmount_result != 0) {
                printf("  %s: %s\n", entry->mountpoint, entry->result_message);
            }
        }
    }
}

/**
 * 演示批量卸载管理器
 */
int demo_batch_unmount_manager() {
    batch_unmount_manager_t manager;
    
    printf("=== 批量卸载管理器演示 ===\n");
    
    // 初始化管理器
    printf("1. 初始化批量卸载管理器:\n");
    init_batch_unmount_manager(&manager);
    
    // 加载挂载信息
    printf("\n2. 加载挂载信息:\n");
    if (load_mount_entries(&manager) != 0) {
        printf("加载挂载信息失败\n");
        return -1;
    }
    
    // 显示可用的卸载选项
    printf("\n3. 可用挂载点:\n");
    for (int i = 0; i < manager.entry_count && i < 10; i++) {
        const batch_unmount_entry_t *entry = &manager.entries[i];
        printf("  %d. %s (%s)\n", i + 1, entry->mountpoint, entry->filesystem);
    }
    
    if (manager.entry_count > 10) {
        printf("  ... (还有 %d 个挂载点)\n", manager.entry_count - 10);
    }
    
    // 演示模式匹配选择
    printf("\n4. 模式匹配选择演示:\n");
    
    // 选择/tmp目录下的挂载点
    select_mountpoints_by_pattern(&manager, "/tmp/*");
    
    // 选择/media目录下的挂载点
    select_mountpoints_by_pattern(&manager, "/media/*");
    
    // 选择所有ext4文件系统
    printf("\n根据文件系统类型选择:\n");
    int ext4_selected = 0;
    for (int i = 0; i < manager.entry_count; i++) {
        batch_unmount_entry_t *entry = &manager.entries[i];
        if (strcmp(entry->filesystem, "ext4") == 0) {
            entry->selected_for_unmount = 1;
            ext4_selected++;
            printf("  选中ext4文件系统: %s\n", entry->mountpoint);
        }
    }
    printf("共选中 %d 个ext4文件系统\n", ext4_selected);
    
    // 显示选中结果
    printf("\n5. 选中挂载点列表:\n");
    for (int i = 0; i < manager.entry_count; i++) {
        const batch_unmount_entry_t *entry = &manager.entries[i];
        if (entry->selected_for_unmount) {
            printf("  %s (%s on %s)\n", 
                   entry->mountpoint, entry->filesystem, entry->device);
        }
    }
    
    // 演示不同卸载模式
    printf("\n6. 不同卸载模式演示:\n");
    
    // 模式1:普通卸载
    printf("模式1:普通卸载\n");
    printf("注意:实际演示中跳过真实卸载操作以避免影响系统\n");
    
    // 模式2:强制卸载
    printf("\n模式2:强制卸载\n");
    printf("卸载标志: MNT_FORCE (0x%x)\n", MNT_FORCE);
    
    // 模式3:延迟卸载
    printf("\n模式3:延迟卸载\n");
    printf("卸载标志: MNT_DETACH (0x%x)\n", MNT_DETACH);
    
    // 模式4:过期卸载
    printf("\n模式4:过期卸载\n");
    printf("卸载标志: MNT_EXPIRE (0x%x)\n", MNT_EXPIRE);
    
    // 显示批量卸载策略
    printf("\n=== 批量卸载策略 ===\n");
    printf("1. 选择策略:\n");
    printf("   ✓ 支持通配符模式匹配\n");
    printf("   ✓ 支持文件系统类型筛选\n");
    printf("   ✓ 支持设备类型筛选\n");
    printf("   ✓ 支持交互式选择\n");
    
    printf("\n2. 卸载策略:\n");
    printf("   ✓ 优先尝试普通卸载\n");
    printf("   ✓ 失败后尝试强制卸载\n");
    printf("   ✓ 最后考虑延迟卸载\n");
    printf("   ✓ 支持批量重试机制\n");
    
    printf("\n3. 错误处理:\n");
    printf("   ✓ 详细记录每个卸载操作结果\n");
    printf("   ✓ 提供失败原因分析\n");
    printf("   ✓ 支持部分成功处理\n");
    printf("   ✓ 生成卸载报告\n");
    
    printf("\n4. 安全考虑:\n");
    printf("   ✓ 避免卸载系统关键挂载点\n");
    printf("   ✓ 检查挂载点使用状态\n");
    printf("   ✓ 提供确认机制\n");
    printf("   ✓ 支持回滚操作\n");
    
    return 0;
}

int main() {
    return demo_batch_unmount_manager();
}

示例5:文件系统监控和管理 Link to heading

#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mntent.h>
#include <time.h>
#include <sys/statvfs.h>

/**
 * 文件系统统计信息结构
 */
typedef struct {
    char mountpoint[256];
    char filesystem[32];
    char device[256];
    unsigned long long total_size_kb;
    unsigned long long used_size_kb;
    unsigned long long available_size_kb;
    double usage_percent;
    time_t last_check_time;
    int is_mounted;
    int readonly;
} filesystem_stats_t;

/**
 * 文件系统监控器结构
 */
typedef struct {
    filesystem_stats_t filesystems[32];
    int fs_count;
    time_t last_update_time;
    int monitoring_enabled;
} fs_monitor_t;

/**
 * 更新文件系统统计信息
 */
int update_filesystem_stats(filesystem_stats_t *fs) {
    struct statvfs buf;
    
    if (statvfs(fs->mountpoint, &buf) != 0) {
        printf("获取文件系统统计信息失败: %s\n", strerror(errno));
        return -1;
    }
    
    // 计算空间使用情况
    unsigned long long block_size = buf.f_frsize ? buf.f_frsize : buf.f_bsize;
    fs->total_size_kb = (unsigned long long)buf.f_blocks * block_size / 1024;
    fs->available_size_kb = (unsigned long long)buf.f_bavail * block_size / 1024;
    fs->used_size_kb = fs->total_size_kb - (unsigned long long)buf.f_bfree * block_size / 1024;
    
    if (fs->total_size_kb > 0) {
        fs->usage_percent = (double)fs->used_size_kb / fs->total_size_kb * 100;
    } else {
        fs->usage_percent = 0.0;
    }
    
    fs->last_check_time = time(NULL);
    
    // 检查是否为只读
    fs->readonly = (buf.f_flag & ST_RDONLY) ? 1 : 0;
    
    return 0;
}

/**
 * 从/proc/mounts加载文件系统信息
 */
int load_filesystem_info(fs_monitor_t *monitor) {
    FILE *fp = setmntent("/proc/mounts", "r");
    if (!fp) {
        printf("无法读取挂载信息: %s\n", strerror(errno));
        return -1;
    }
    
    struct mntent *mnt;
    int count = 0;
    
    while ((mnt = getmntent(fp)) != NULL && count < 32) {
        // 跳过某些系统挂载点
        if (strncmp(mnt->mnt_dir, "/proc", 5) == 0 ||
            strncmp(mnt->mnt_dir, "/sys", 4) == 0 ||
            strncmp(mnt->mnt_dir, "/dev", 4) == 0) {
            continue;
        }
        
        filesystem_stats_t *fs = &monitor->filesystems[count];
        strncpy(fs->mountpoint, mnt->mnt_dir, sizeof(fs->mountpoint) - 1);
        fs->mountpoint[sizeof(fs->mountpoint) - 1] = '\0';
        
        strncpy(fs->filesystem, mnt->mnt_type, sizeof(fs->filesystem) - 1);
        fs->filesystem[sizeof(fs->filesystem) - 1] = '\0';
        
        strncpy(fs->device, mnt->mnt_fsname, sizeof(fs->device) - 1);
        fs->device[sizeof(fs->device) - 1] = '\0';
        
        fs->is_mounted = 1;
        
        // 更新统计信息
        update_filesystem_stats(fs);
        
        count++;
    }
    
    endmntent(fp);
    monitor->fs_count = count;
    monitor->last_update_time = time(NULL);
    
    printf("加载了 %d 个文件系统信息\n", count);
    return 0;
}

/**
 * 显示文件系统统计信息
 */
void show_filesystem_stats(const filesystem_stats_t *fs) {
    char time_str[64];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", localtime(&fs->last_check_time));
    
    printf("文件系统: %s\n", fs->mountpoint);
    printf("  设备: %s\n", fs->device);
    printf("  类型: %s\n", fs->filesystem);
    printf("  总空间: %.2f GB\n", fs->total_size_kb / (1024.0 * 1024.0));
    printf("  已用空间: %.2f GB (%.1f%%)\n", 
           fs->used_size_kb / (1024.0 * 1024.0), fs->usage_percent);
    printf("  可用空间: %.2f GB\n", fs->available_size_kb / (1024.0 * 1024.0));
    printf("  只读模式: %s\n", fs->readonly ? "是" : "否");
    printf("  最后检查: %s\n", time_str);
}

/**
 * 监控文件系统使用情况
 */
int monitor_filesystem_usage(fs_monitor_t *monitor, const char *mountpoint, double threshold) {
    for (int i = 0; i < monitor->fs_count; i++) {
        filesystem_stats_t *fs = &monitor->filesystems[i];
        
        if (strcmp(fs->mountpoint, mountpoint) == 0) {
            // 更新统计信息
            update_filesystem_stats(fs);
            
            printf("监控文件系统 %s:\n", mountpoint);
            show_filesystem_stats(fs);
            
            // 检查使用率阈值
            if (fs->usage_percent > threshold) {
                printf("⚠ 警告: 文件系统使用率过高 (%.1f%% > %.1f%%)\n", 
                       fs->usage_percent, threshold);
                
                // 根据使用率严重程度提供建议
                if (fs->usage_percent > 95) {
                    printf("  🚨 严重: 立即清理磁盘空间\n");
                } else if (fs->usage_percent > 90) {
                    printf("  ⚠ 警告: 尽快清理磁盘空间\n");
                } else if (fs->usage_percent > 80) {
                    printf("  ℹ 提示: 考虑清理磁盘空间\n");
                }
                
                return 1;  // 超过阈值
            } else {
                printf("✓ 文件系统使用率正常 (%.1f%%)\n", fs->usage_percent);
                return 0;  // 正常
            }
        }
    }
    
    printf("未找到指定的挂载点: %s\n", mountpoint);
    return -1;  // 未找到
}

/**
 * 演示文件系统监控和管理
 */
int demo_filesystem_monitoring() {
    fs_monitor_t monitor = {0};
    uid_t uid = getuid();
    
    printf("=== 文件系统监控和管理演示 ===\n");
    
    // 权限检查
    printf("权限检查:\n");
    printf("  当前用户ID: %d\n", uid);
    if (uid == 0) {
        printf("  ✓ 具有root权限\n");
    } else {
        printf("  ℹ 普通用户权限(部分功能可能受限)\n");
    }
    
    // 加载文件系统信息
    printf("\n1. 加载文件系统信息:\n");
    if (load_filesystem_info(&monitor) != 0) {
        printf("加载文件系统信息失败\n");
        return -1;
    }
    
    // 显示所有文件系统信息
    printf("\n2. 文件系统统计信息:\n");
    for (int i = 0; i < monitor.fs_count && i < 5; i++) {
        printf("\n文件系统 %d:\n", i + 1);
        show_filesystem_stats(&monitor.filesystems[i]);
    }
    
    if (monitor.fs_count > 5) {
        printf("\n... (还有 %d 个文件系统)\n", monitor.fs_count - 5);
    }
    
    // 演示使用率监控
    printf("\n3. 文件系统使用率监控演示:\n");
    
    // 监控各个文件系统
    for (int i = 0; i < monitor.fs_count && i < 3; i++) {
        filesystem_stats_t *fs = &monitor.filesystems[i];
        printf("\n监控 %s:\n", fs->mountpoint);
        
        // 不同阈值的监控
        monitor_filesystem_usage(&monitor, fs->mountpoint, 80.0);  // 警告阈值
        monitor_filesystem_usage(&monitor, fs->mountpoint, 90.0);  // 严重阈值
    }
    
    // 演示umount2在监控中的应用
    printf("\n4. umount2在监控中的应用:\n");
    
    // 模拟需要卸载的情况
    printf("模拟文件系统维护场景:\n");
    
    for (int i = 0; i < monitor.fs_count && i < 2; i++) {
        filesystem_stats_t *fs = &monitor.filesystems[i];
        printf("\n检查 %s 是否需要维护:\n", fs->mountpoint);
        
        // 检查使用率和只读状态
        if (fs->usage_percent > 95) {
            printf("  文件系统使用率过高 (%.1f%%)\n", fs->usage_percent);
            printf("  建议: 卸载后进行文件系统检查\n");
            
            // 演示不同卸载选项
            printf("  卸载选项:\n");
            printf("    1. 普通卸载: umount2(\"%s\", 0)\n", fs->mountpoint);
            printf("    2. 强制卸载: umount2(\"%s\", MNT_FORCE)\n", fs->mountpoint);
            printf("    3. 延迟卸载: umount2(\"%s\", MNT_DETACH)\n", fs->mountpoint);
        } else if (fs->readonly) {
            printf("  文件系统为只读模式\n");
            printf("  可能需要重新挂载为读写模式\n");
        } else {
            printf("  文件系统状态正常\n");
        }
    }
    
    // 显示监控策略和最佳实践
    printf("\n=== 文件系统监控策略 ===\n");
    printf("1. 监控频率:\n");
    printf("   ✓ 关键系统: 每分钟检查\n");
    printf("   ✓ 重要数据: 每5分钟检查\n");
    printf("   ✓ 一般用途: 每小时检查\n");
    
    printf("\n2. 阈值设置:\n");
    printf("   ✓ 警告阈值: 80%% 使用率\n");
    printf("   ✓ 严重阈值: 90%% 使用率\n");
    printf("   ✓ 紧急阈值: 95%% 使用率\n");
    
    printf("\n3. 响应策略:\n");
    printf("   ✓ 自动告警通知\n");
    printf("   ✓ 日志记录\n");
    printf("   ✓ 自动清理临时文件\n");
    printf("   ✓ 邮件/SMS通知\n");
    
    printf("\n4. umount2使用场景:\n");
    printf("   ✓ 系统维护时的安全卸载\n");
    printf("   ✓ 文件系统检查前的准备\n");
    printf("   ✓ 紧急情况下的强制卸载\n");
    printf("   ✓ 资源回收时的延迟卸载\n");
    
    // 显示安全考虑
    printf("\n=== 安全考虑 ===\n");
    printf("1. 权限管理:\n");
    printf("   ✓ 文件系统操作需要适当权限\n");
    printf("   ✓ 避免普通用户执行危险操作\n");
    printf("   ✓ 使用sudo进行权限提升\n");
    
    printf("\n2. 数据安全:\n");
    printf("   ✓ 卸载前确保数据已同步\n");
    printf("   ✓ 避免强制卸载重要数据\n");
    printf("   ✓ 备份重要文件系统\n");
    
    printf("\n3. 系统稳定性:\n");
    printf("   ✓ 避免卸载系统关键挂载点\n");
    printf("   ✓ 监控卸载操作的影响\n");
    printf("   ✓ 准备系统恢复方案\n");
    
    return 0;
}

int main() {
    return demo_filesystem_monitoring();
}

umount2 使用注意事项 Link to heading

系统要求: Link to heading

  1. 内核版本: 支持umount2的Linux内核
  2. 权限要求: 通常需要root权限或适当的挂载权限
  3. 架构支持: 支持所有主流架构

卸载标志详解: Link to heading

  1. 0: 普通卸载(默认行为)
  2. MNT_FORCE: 强制卸载(即使文件系统正忙)
  3. MNT_DETACH: 延迟卸载(立即返回,后台清理)
  4. MNT_EXPIRE: 标记为过期(如果未被使用则卸载)

错误处理: Link to heading

  1. EBUSY: 文件系统正忙,无法卸载
  2. EINVAL: 无效的挂载点
  3. EPERM: 权限不足
  4. EACCES: 访问被拒绝
  5. ENOMEM: 内存不足

安全考虑: Link to heading

  1. 权限验证: 确保具有足够的权限
  2. 挂载点验证: 验证挂载点的有效性
  3. 使用状态检查: 检查文件系统是否正在使用
  4. 数据同步: 确保数据已正确同步

最佳实践: Link to heading

  1. 渐进式卸载: 优先尝试普通卸载,失败后再尝试强制卸载
  2. 状态检查: 卸载前后检查系统状态
  3. 日志记录: 记录所有卸载操作
  4. 错误恢复: 准备适当的错误恢复机制
  5. 用户通知: 及时通知用户操作结果

umount2标志详细说明 Link to heading

MNT_FORCE (1): Link to heading

  • 功能: 强制卸载文件系统
  • 使用场景: 文件系统正忙时的紧急卸载
  • 风险: 可能导致数据丢失或文件系统损坏

MNT_DETACH (2): Link to heading

  • 功能: 延迟卸载(懒卸载)
  • 使用场景: 立即返回,后台清理资源
  • 优势: 不阻塞调用进程

MNT_EXPIRE (4): Link to heading

  • 功能: 标记挂载点为过期
  • 使用场景: 如果没有进程使用则卸载
  • 特点: 非阻塞操作

相关函数和工具 Link to heading

系统调用: Link to heading

// 基础卸载函数
int umount(const char *target);

// 挂载函数
int mount(const char *source, const char *target,
          const char *filesystemtype, unsigned long mountflags,
          const void *data);

命令行工具: Link to heading

# 普通卸载
umount /mnt/point

# 强制卸载
umount -f /mnt/point

# 延迟卸载
umount -l /mnt/point

# 查看挂载信息
cat /proc/mounts
mount | grep point

常见使用场景 Link to heading

1. 系统维护: Link to heading

// 维护前安全卸载文件系统
umount2("/mnt/data", 0);

2. 紧急处理: Link to heading

// 紧急情况下强制卸载
umount2("/mnt/critical", MNT_FORCE);

3. 资源管理: Link to heading

// 延迟卸载以避免阻塞
umount2("/mnt/temp", MNT_DETACH);

4. 自动化脚本: Link to heading

// 批量卸载操作
for (int i = 0; i < count; i++) {
    umount2(mountpoints[i], 0);
}

总结 Link to heading

umount2 是Linux系统中强大的文件系统卸载工具,提供了:

  1. 灵活的卸载选项: 支持普通、强制、延迟等多种卸载模式
  2. 完善的错误处理: 详细的错误码和错误信息
  3. 安全的卸载机制: 多种安全检查和保护措施
  4. 标准兼容性: 符合POSIX标准,广泛支持

通过合理使用 umount2,可以构建安全可靠的文件系统管理工具。在实际应用中,需要注意权限要求、错误处理和系统稳定性等关键问题,遵循最佳实践确保系统的安全和稳定运行。