90. ioprio_get - 获取进程或进程组的 I/O 优先级 Link to heading

1. 函数介绍 Link to heading

ioprio_get 是一个 Linux 系统调用,用于获取指定进程或进程组的 I/O 优先级。I/O 优先级是 Linux 内核 I/O 调度器使用的一种机制,用于控制进程对磁盘和其他块设备的访问优先级。

与传统的 CPU 优先级不同,I/O 优先级专门用于管理磁盘 I/O 操作的调度,确保高优先级的进程能够获得更好的磁盘访问性能。

2. 函数原型 Link to heading

#include <linux/ioprio.h>

int ioprio_get(int which, int who);

注意:这个函数不是标准 C 库的一部分,通常需要通过 syscall() 调用或者使用特定的库函数。

3. 功能 Link to heading

获取指定进程、进程组或用户的所有进程的 I/O 优先级。返回的优先级值包含了调度类和优先级等级信息。

4. 参数 Link to heading

  • int which: 指定查询的类型

    • IOPRIO_WHO_PROCESS: 查询单个进程的 I/O 优先级
    • IOPRIO_WHO_PGRP: 查询进程组中所有进程的 I/O 优先级
    • IOPRIO_WHO_USER: 查询指定用户的所有进程的 I/O 优先级
  • int who: 根据 which 参数指定的具体 ID

    • IOPRIO_WHO_PROCESS: 进程 ID(0 表示当前进程)
    • IOPRIO_WHO_PGRP: 进程组 ID(0 表示当前进程组)
    • IOPRIO_WHO_USER: 用户 ID(0 表示当前用户)

5. I/O 优先级编码 Link to heading

I/O 优先级值由两部分组成:

#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)

#define IOPRIO_PRIO_CLASS(mask) (((mask) >> IOPRIO_CLASS_SHIFT) & 0x7)
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)

6. I/O 调度类 Link to heading

enum {
    IOPRIO_CLASS_NONE,      // 无特定类(使用父进程或默认值)
    IOPRIO_CLASS_RT,        // 实时类(最高优先级)
    IOPRIO_CLASS_BE,        // Best-effort 类(默认类)
    IOPRIO_CLASS_IDLE,      // 空闲类(最低优先级)
};

7. 优先级等级 Link to heading

  • RT 和 BE 类: 0-7 级,0 为最高优先级,7 为最低优先级
  • IDLE 类: 无等级概念

8. 返回值 Link to heading

  • 成功时:返回 I/O 优先级值(包含类和等级信息)
  • 失败时:返回 -1,并设置 errno

9. 常见 errno 错误码 Link to heading

  • ESRCH: 指定的进程、进程组或用户不存在
  • EINVAL: which 参数无效
  • EPERM: 权限不足(无法访问指定进程的信息)
  • EFAULT: 指针参数指向无效内存地址

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

  • ioprio_set(): 设置进程的 I/O 优先级
  • ionice: 用户态命令行工具,用于查看和设置 I/O 优先级
  • sched_getparam(), sched_setparam(): CPU 调度参数管理
  • getpriority(), setpriority(): 进程优先级管理
  • /proc/[pid]/io: 查看进程 I/O 统计信息
  • /sys/block/[device]/queue/scheduler: 查看和设置块设备调度器

11. 示例代码 Link to heading

示例1:基本使用 - 获取 I/O 优先级 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/ioprio.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>

#ifndef SYS_ioprio_get
# define SYS_ioprio_get 252  // x86_64 架构下的系统调用号
#endif

#ifndef SYS_ioprio_set
# define SYS_ioprio_set 251
#endif

// I/O 优先级宏定义
#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(mask) (((mask) >> IOPRIO_CLASS_SHIFT) & 0x7)
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)

// I/O 调度类
enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE,
};

const char* ioprio_class_to_string(int class) {
    switch (class) {
        case IOPRIO_CLASS_NONE: return "NONE";
        case IOPRIO_CLASS_RT:   return "RT";
        case IOPRIO_CLASS_BE:   return "BE";
        case IOPRIO_CLASS_IDLE: return "IDLE";
        default: return "UNKNOWN";
    }
}

void print_ioprio_info(const char* label, int ioprio) {
    if (ioprio == -1) {
        printf("%-20s: 获取失败 (%s)\n", label, strerror(errno));
        return;
    }
    
    int class = IOPRIO_PRIO_CLASS(ioprio);
    int data = IOPRIO_PRIO_DATA(ioprio);
    
    printf("%-20s: %s", label, ioprio_class_to_string(class));
    
    if (class == IOPRIO_CLASS_RT || class == IOPRIO_CLASS_BE) {
        printf(" (等级 %d)", data);
    }
    
    printf(" [值: 0x%x]\n", ioprio);
}

int main() {
    int ioprio;
    
    printf("=== I/O 优先级获取演示 ===\n");
    
    // 获取当前进程的 I/O 优先级
    ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, 0);
    print_ioprio_info("当前进程", ioprio);
    
    // 获取当前进程组的 I/O 优先级
    ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PGRP, 0);
    print_ioprio_info("当前进程组", ioprio);
    
    // 获取当前用户的 I/O 优先级
    ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_USER, 0);
    print_ioprio_info("当前用户", ioprio);
    
    // 获取 init 进程的 I/O 优先级
    ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, 1);
    print_ioprio_info("init 进程 (PID 1)", ioprio);
    
    // 显示进程信息
    printf("\n进程信息:\n");
    printf("  当前 PID: %d\n", getpid());
    printf("  父进程 PID: %d\n", getppid());
    printf("  当前 UID: %d", getuid());
    
    struct passwd *pwd = getpwuid(getuid());
    if (pwd) {
        printf(" (%s)", pwd->pw_name);
    }
    printf("\n");
    
    return 0;
}

示例2:错误处理和特殊情况 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/ioprio.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>

#ifndef SYS_ioprio_get
# define SYS_ioprio_get 252
#endif

#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(mask) (((mask) >> IOPRIO_CLASS_SHIFT) & 0x7)
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)

enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE,
};

void test_ioprio_get(int which, int who, const char* description) {
    printf("\n测试 %s:\n", description);
    printf("  参数: which=%d, who=%d\n", which, who);
    
    int ioprio = syscall(SYS_ioprio_get, which, who);
    if (ioprio == -1) {
        printf("  结果: 失败 - %s\n", strerror(errno));
        switch (errno) {
            case ESRCH:
                printf("    原因: 指定的进程/组/用户不存在\n");
                break;
            case EINVAL:
                printf("    原因: 无效的 which 参数\n");
                break;
            case EPERM:
                printf("    原因: 权限不足\n");
                break;
            default:
                printf("    原因: 其他错误\n");
                break;
        }
    } else {
        int class = IOPRIO_PRIO_CLASS(ioprio);
        int data = IOPRIO_PRIO_DATA(ioprio);
        printf("  结果: 成功\n");
        printf("    I/O 优先级值: 0x%x\n", ioprio);
        printf("    调度类: %d ", class);
        switch (class) {
            case IOPRIO_CLASS_NONE: printf("(NONE)\n"); break;
            case IOPRIO_CLASS_RT:   printf("(RT)\n"); break;
            case IOPRIO_CLASS_BE:   printf("(BE)\n"); break;
            case IOPRIO_CLASS_IDLE: printf("(IDLE)\n"); break;
            default: printf("(UNKNOWN)\n"); break;
        }
        if (class == IOPRIO_CLASS_RT || class == IOPRIO_CLASS_BE) {
            printf("    优先级等级: %d\n", data);
        }
    }
}

int main() {
    printf("=== ioprio_get 错误处理测试 ===\n");
    
    // 测试正常情况
    test_ioprio_get(IOPRIO_WHO_PROCESS, 0, "当前进程");
    test_ioprio_get(IOPRIO_WHO_PGRP, 0, "当前进程组");
    test_ioprio_get(IOPRIO_WHO_USER, getuid(), "当前用户");
    
    // 测试无效参数
    test_ioprio_get(999, 0, "无效的 which 参数");
    test_ioprio_get(IOPRIO_WHO_PROCESS, -1, "负数进程 ID");
    
    // 测试不存在的进程
    test_ioprio_get(IOPRIO_WHO_PROCESS, 999999, "不存在的进程");
    
    // 测试不存在的进程组
    test_ioprio_get(IOPRIO_WHO_PGRP, 999999, "不存在的进程组");
    
    // 创建子进程进行测试
    pid_t child_pid = fork();
    if (child_pid == -1) {
        perror("fork 失败");
        exit(EXIT_FAILURE);
    }
    
    if (child_pid == 0) {
        // 子进程
        printf("\n=== 子进程信息 ===\n");
        printf("子进程 PID: %d\n", getpid());
        printf("父进程 PID: %d\n", getppid());
        
        // 子进程睡眠一段时间
        sleep(3);
        exit(0);
    } else {
        // 父进程
        printf("\n=== 父进程测试子进程 ===\n");
        printf("子进程 PID: %d\n", child_pid);
        
        // 父进程获取子进程 I/O 优先级
        test_ioprio_get(IOPRIO_WHO_PROCESS, child_pid, "子进程(运行中)");
        
        // 等待子进程结束
        int status;
        waitpid(child_pid, &status, 0);
        printf("子进程已结束\n");
        
        // 再次测试已结束的进程
        test_ioprio_get(IOPRIO_WHO_PROCESS, child_pid, "已结束的子进程");
    }
    
    return 0;
}

示例3:I/O 优先级管理工具 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/ioprio.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>

#ifndef SYS_ioprio_get
# define SYS_ioprio_get 252
#endif

#ifndef SYS_ioprio_set
# define SYS_ioprio_set 251
#endif

#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(mask) (((mask) >> IOPRIO_CLASS_SHIFT) & 0x7)
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)

enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE,
};

const char* ioprio_class_to_string(int class) {
    switch (class) {
        case IOPRIO_CLASS_NONE: return "NONE";
        case IOPRIO_CLASS_RT:   return "RT (实时)";
        case IOPRIO_CLASS_BE:   return "BE (尽力而为)";
        case IOPRIO_CLASS_IDLE: return "IDLE (空闲)";
        default: return "UNKNOWN";
    }
}

int get_ioprio(int which, int who) {
    return syscall(SYS_ioprio_get, which, who);
}

int set_ioprio(int which, int who, int ioprio) {
    return syscall(SYS_ioprio_set, which, who, ioprio);
}

void print_process_ioprio(pid_t pid, const char* label) {
    int ioprio = get_ioprio(IOPRIO_WHO_PROCESS, pid);
    if (ioprio != -1) {
        int class = IOPRIO_PRIO_CLASS(ioprio);
        int data = IOPRIO_PRIO_DATA(ioprio);
        
        printf("%-20s: PID %d, 类别 %s", label, pid, ioprio_class_to_string(class));
        if (class == IOPRIO_CLASS_RT || class == IOPRIO_CLASS_BE) {
            printf(" (等级 %d)", data);
        }
        printf("\n");
    } else {
        printf("%-20s: PID %d, 获取失败 (%s)\n", label, pid, strerror(errno));
    }
}

void analyze_system_ioprio() {
    printf("=== 系统关键进程 I/O 优先级分析 ===\n");
    
    // 分析当前进程
    print_process_ioprio(getpid(), "当前进程");
    
    // 分析父进程
    print_process_ioprio(getppid(), "父进程");
    
    // 分析 init 进程
    print_process_ioprio(1, "init 进程");
    
    // 分析 shell 进程
    print_process_ioprio(getppid(), "Shell 进程");
    
    // 分析当前用户的其他进程(简化实现)
    int user_ioprio = get_ioprio(IOPRIO_WHO_USER, getuid());
    if (user_ioprio != -1) {
        int class = IOPRIO_PRIO_CLASS(user_ioprio);
        printf("当前用户进程: 类别 %s", ioprio_class_to_string(class));
        if (class == IOPRIO_CLASS_RT || class == IOPRIO_CLASS_BE) {
            printf(" (等级 %d)", IOPRIO_PRIO_DATA(user_ioprio));
        }
        printf("\n");
    }
}

void interactive_ioprio_query() {
    char input[32];
    pid_t target_pid;
    
    printf("\n=== 交互式 I/O 优先级查询 ===\n");
    printf("输入进程 PID 查询 I/O 优先级 (输入 0 退出): ");
    
    while (fgets(input, sizeof(input), stdin)) {
        if (sscanf(input, "%d", &target_pid) == 1) {
            if (target_pid == 0) {
                break;
            }
            
            int ioprio = get_ioprio(IOPRIO_WHO_PROCESS, target_pid);
            if (ioprio != -1) {
                int class = IOPRIO_PRIO_CLASS(ioprio);
                int data = IOPRIO_PRIO_DATA(ioprio);
                
                printf("进程 %d 的 I/O 优先级:\n", target_pid);
                printf("  调度类: %s\n", ioprio_class_to_string(class));
                if (class == IOPRIO_CLASS_RT || class == IOPRIO_CLASS_BE) {
                    printf("  优先级等级: %d\n", data);
                }
                printf("  原始值: 0x%x\n", ioprio);
            } else {
                printf("查询进程 %d 的 I/O 优先级失败: %s\n", target_pid, strerror(errno));
            }
        }
        printf("继续输入进程 PID (输入 0 退出): ");
    }
}

void demonstrate_ioprio_classes() {
    printf("\n=== I/O 优先级类别说明 ===\n");
    printf("I/O 调度类:\n");
    printf("  %-8s: %s\n", "NONE", "无特定类,使用默认值");
    printf("  %-8s: %s\n", "RT", "实时类,最高优先级");
    printf("  %-8s: %s\n", "BE", "Best-effort 类,默认类");
    printf("  %-8s: %s\n", "IDLE", "空闲类,最低优先级");
    
    printf("\n优先级等级 (RT 和 BE 类):\n");
    printf("  %-8s: %s\n", "0", "最高优先级");
    printf("  %-8s: %s\n", "1-6", "中等优先级");
    printf("  %-8s: %s\n", "7", "最低优先级");
    
    printf("\n使用建议:\n");
    printf("  • 关键系统服务: RT 类,等级 0-2\n");
    printf("  • 用户交互程序: BE 类,等级 0-3\n");
    printf("  • 后台批处理: BE 类,等级 4-7 或 IDLE 类\n");
}

int main() {
    printf("=== I/O 优先级管理工具 ===\n");
    
    // 显示系统信息
    analyze_system_ioprio();
    
    // 显示类别说明
    demonstrate_ioprio_classes();
    
    // 交互式查询
    interactive_ioprio_query();
    
    return 0;
}

示例4:I/O 优先级设置和监控 Link to heading

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/ioprio.h>
#include <errno.h>
#include <string.h>
#include <time.h>

#ifndef SYS_ioprio_get
# define SYS_ioprio_get 252
#endif

#ifndef SYS_ioprio_set
# define SYS_ioprio_set 251
#endif

#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(mask) (((mask) >> IOPRIO_CLASS_SHIFT) & 0x7)
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)

enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE,
};

int get_ioprio(int which, int who) {
    return syscall(SYS_ioprio_get, which, who);
}

int set_ioprio(int which, int who, int ioprio) {
    return syscall(SYS_ioprio_set, which, who, ioprio);
}

void monitor_ioprio_changes(pid_t target_pid, int duration) {
    int last_ioprio = -2;  // -2 表示初始状态
    time_t start_time = time(NULL);
    time_t current_time;
    
    printf("开始监控进程 %d 的 I/O 优先级变化 (%d 秒)...\n", target_pid, duration);
    printf("%-8s %-15s %s\n", "时间", "I/O 优先级", "状态");
    printf("%-8s %-15s %s\n", "----", "----", "----");
    
    while ((current_time = time(NULL)) - start_time < duration) {
        int current_ioprio = get_ioprio(IOPRIO_WHO_PROCESS, target_pid);
        
        if (current_ioprio != -1) {
            int class = IOPRIO_PRIO_CLASS(current_ioprio);
            int data = IOPRIO_PRIO_DATA(current_ioprio);
            
            char status[32] = "稳定";
            if (last_ioprio == -2) {
                snprintf(status, sizeof(status), "初始");
            } else if (last_ioprio != current_ioprio) {
                snprintf(status, sizeof(status), "变化");
            }
            
            printf("%-8ld %-15s %s\n", 
                   current_time - start_time,
                   (class == IOPRIO_CLASS_RT || class == IOPRIO_CLASS_BE) ?
                   (class == IOPRIO_CLASS_RT ? 
                    (char*)("RT-" + data/10 + '0' + data%10) :
                    (char*)("BE-" + data/10 + '0' + data%10)) :
                   (class == IOPRIO_CLASS_IDLE ? "IDLE" : "NONE"),
                   status);
            
            last_ioprio = current_ioprio;
        } else {
            printf("%-8ld %-15s %s\n", 
                   current_time - start_time, 
                   "获取失败", 
                   strerror(errno));
        }
        
        sleep(1);
    }
    
    printf("监控结束\n");
}

void demonstrate_ioprio_adjustment() {
    printf("=== I/O 优先级调整演示 ===\n");
    
    pid_t current_pid = getpid();
    int original_ioprio = get_ioprio(IOPRIO_WHO_PROCESS, current_pid);
    
    printf("当前进程 PID: %d\n", current_pid);
    
    if (original_ioprio != -1) {
        int original_class = IOPRIO_PRIO_CLASS(original_ioprio);
        int original_data = IOPRIO_PRIO_DATA(original_ioprio);
        printf("原始 I/O 优先级: 类别 %d (等级 %d), 值 0x%x\n", 
               original_class, original_data, original_ioprio);
    } else {
        printf("获取原始 I/O 优先级失败: %s\n", strerror(errno));
        return;
    }
    
    // 尝试设置不同的 I/O 优先级
    printf("\n尝试设置不同的 I/O 优先级:\n");
    
    // 设置为 BE 类,等级 4
    int be_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
    if (set_ioprio(IOPRIO_WHO_PROCESS, current_pid, be_ioprio) == 0) {
        int new_ioprio = get_ioprio(IOPRIO_WHO_PROCESS, current_pid);
        printf("✓ 成功设置为 BE-4: 0x%x\n", new_ioprio);
    } else {
        printf("✗ 设置 BE-4 失败: %s\n", strerror(errno));
        if (errno == EPERM) {
            printf("  需要适当权限才能设置 I/O 优先级\n");
        }
    }
    
    // 设置为 IDLE 类
    int idle_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);
    if (set_ioprio(IOPRIO_WHO_PROCESS, current_pid, idle_ioprio) == 0) {
        int new_ioprio = get_ioprio(IOPRIO_WHO_PROCESS, current_pid);
        printf("✓ 成功设置为 IDLE: 0x%x\n", new_ioprio);
    } else {
        printf("✗ 设置 IDLE 失败: %s\n", strerror(errno));
    }
    
    // 恢复原始优先级
    if (set_ioprio(IOPRIO_WHO_PROCESS, current_pid, original_ioprio) == 0) {
        printf("✓ 已恢复原始 I/O 优先级\n");
    } else {
        printf("✗ 恢复原始优先级失败: %s\n", strerror(errno));
    }
}

void show_system_ioprio_info() {
    printf("\n=== 系统 I/O 调度信息 ===\n");
    
    // 显示当前支持的调度器(如果有权限)
    printf("当前块设备调度器信息:\n");
    system("ls /sys/block/ 2>/dev/null | head -5 | while read dev; do "
           "echo \"  $dev: $(cat /sys/block/$dev/queue/scheduler 2>/dev/null || echo '无法访问')\"; done");
    
    // 显示 ionice 命令的帮助信息
    printf("\n相关命令行工具:\n");
    printf("  ionice -p <pid>          # 查看进程 I/O 优先级\n");
    printf("  ionice -c <class> -n <level> -p <pid>  # 设置进程 I/O 优先级\n");
    printf("  ionice -c 3 -p $$        # 将当前进程设置为 IDLE 类\n");
}

int main() {
    printf("=== I/O 优先级监控和管理工具 ===\n");
    
    // 演示优先级调整
    demonstrate_ioprio_adjustment();
    
    // 显示系统信息
    show_system_ioprio_info();
    
    // 如果需要,可以监控优先级变化
    char choice;
    printf("\n是否监控当前进程 I/O 优先级变化? (y/N): ");
    if (scanf(" %c", &choice) == 1 && (choice == 'y' || choice == 'Y')) {
        monitor_ioprio_changes(getpid(), 10);
    }
    
    return 0;
}

12. I/O 优先级类别详细说明 Link to heading

// I/O 调度类详解

// IOPRIO_CLASS_NONE (0)
// • 无特定调度类
// • 继承父进程的调度类
// • 通常用于新创建的进程

// IOPRIO_CLASS_RT (1) - 实时类
// • 最高优先级
// • 等级 0-7,0 为最高
// • 适用于关键系统服务和实时应用

// IOPRIO_CLASS_BE (2) - Best-effort 类
// • 默认调度类
// • 等级 0-7,0 为最高
// • 适用于大多数用户进程

// IOPRIO_CLASS_IDLE (3) - 空闲类
// • 最低优先级
// • 仅在系统空闲时执行 I/O
// • 适用于后台批处理任务

13. 实际应用场景 Link to heading

场景1:数据库系统优化 Link to heading

void optimize_database_io_priority() {
    // 数据库主进程使用较高优先级
    int high_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 1);
    set_ioprio(IOPRIO_WHO_PROCESS, getpid(), high_ioprio);
    
    // 后台维护任务使用较低优先级
    int low_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);
    // 应用于维护进程
}

场景2:备份系统 Link to heading

void backup_system_priority() {
    // 备份进程使用 IDLE 类,避免影响正常业务
    int idle_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);
    set_ioprio(IOPRIO_WHO_PROCESS, getpid(), idle_ioprio);
}

场景3:系统监控 Link to heading

int is_high_io_priority_process(pid_t pid) {
    int ioprio = get_ioprio(IOPRIO_WHO_PROCESS, pid);
    if (ioprio != -1) {
        int class = IOPRIO_PRIO_CLASS(ioprio);
        return (class == IOPRIO_CLASS_RT || 
                (class == IOPRIO_CLASS_BE && IOPRIO_PRIO_DATA(ioprio) < 4));
    }
    return 0;
}

14. 注意事项 Link to heading

使用 ioprio_get 时需要注意:

  1. 权限要求: 通常需要适当权限才能查询其他进程的 I/O 优先级
  2. 系统调用: 需要通过 syscall() 调用,不是标准 C 库函数
  3. 架构相关: 系统调用号可能因架构而异
  4. 内核支持: 需要内核支持 I/O 优先级功能
  5. 调度器依赖: 实际效果取决于使用的 I/O 调度器

15. 与相关工具的配合使用 Link to heading

# 使用 ionice 命令行工具
ionice -p $$                    # 查看当前进程 I/O 优先级
ionice -c 3 -p $$              # 设置当前进程为 IDLE 类
ionice -c 1 -n 2 -p 1234       # 设置进程 1234 为 RT 类,等级 2

# 查看系统 I/O 调度信息
cat /sys/block/sda/queue/scheduler
cat /proc/[pid]/io

总结 Link to heading

ioprio_get 是管理 Linux 系统 I/O 优先级的重要系统调用:

关键特性:

  1. 精细控制: 支持进程、进程组、用户级别的查询
  2. 多类别支持: RT、BE、IDLE 三种调度类
  3. 等级划分: 每个类别支持 0-7 级优先级
  4. 系统调用: 直接访问内核调度信息

主要应用:

  1. 系统性能优化和资源管理
  2. 数据库和关键服务的 I/O 调度
  3. 备份和批处理任务的优先级控制
  4. 系统监控和诊断工具

使用要点:

  1. 需要通过 syscall() 调用
  2. 注意权限和错误处理
  3. 理解不同调度类的特点
  4. 配合 ioprio_set 实现完整功能

正确使用 I/O 优先级可以显著改善系统的 I/O 性能和响应性,是系统管理员和开发人员的重要工具。