• 调度器1—相关接口和命令行工具


    一、CPU调度策略设置

    1. 内核函数

    int sched_setscheduler(struct task_struct *p, int policy, const struct sched_param *param)
    衍生函数:
    sched_setscheduler_nocheck

    设置内核线程调度策略和优先级,优先级设置只对RT线程有效。

    2. 系统调用

    int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
    int sched_getscheduler(pid_t pid);

    若要设置为RT,需要root权限,此时RT优先级数值为99-param->sched_priority;若设置为CFS,param->sched_priority必须为0

    3. Native函数

    int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); 

    初始化attr,设置调度策略。设置为RT调度策略需要root权限,设置为CFS不需要。

    4. 上层函数

    native void setThreadScheduler(int tid, int policy, int priority) //Process.java

    通过 android_util_Process.cpp 这个JNI文件中调用 sched_setscheduler 函数实现。

    5. 命令行工具

    chrt -f -p <pid> 15

    将pid线程设置为RT(-f)线程,优先级比RT最低优先级提升15,为99-15=89

    二、CPU调度优先级设置

    1. 内核函数

    void set_user_nice(struct task_struct *p, long nice)

    和系统调用 nice 和 setpriority 对应。

    2. 系统调用

    int nice(int inc);

    当前cfs线程优先级数值加inc,inc可正可负,对rt线程无效。

    int getpriority(int which, id_t who);
    int setpriority(int which, id_t who, int prio);

    CFS线程在 nice=0(prio=120) 的基础上优先级数值加上 prio,对 RT 线程无效,RT线程使用 sched_setscheduler 设置优先级。优先级往低处设置不需要权限,优先级往高处设置需要相应的权限。参考《linux能力机制》

    3. Native函数

    int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);

    初始化attr,设置调度优先级,若是RT策略,param->sched_priority取值1-99,设置后对应优先级数值为99-param->sched_priority,若是CFS策略,param->sched_priority必须为0.

    int androidSetThreadPriority(pid_t tid, int pri) //android/system/core/libutils/Threads.cpp

    4. 上层函数

    native void setThreadPriority(int tid, int priority) //Process.java

    通过 android_util_Process.cpp 这个JNI文件中调用setpriority函数实现。

    5. 命令行工具

    renice -n 2 -p <pid>

    优先级数值加 2,也可以为负值。

    三、绑核设置

    1. 内核函数

    void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
    衍生函数:
    set_cpus_allowed_common
    set_cpus_allowed_ptr

    2. 系统调用

    int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
    int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);

    cpusetsize 为 sizeof(cpu_set_t),可以 "man sched_setaffinity" 和 "$ man CPU_ZERO" 查看使用方法。看 /proc/pid/status 的 Cpus_allowed 查看设置成功情况。设置后此任务只能跑在设定的CPU上,即使被设置的CPU上和忙其它CPU很空闲,也不能被 balance 到其它CPU核上。

    3. Native函数

    待补充,目前还没发现有,但是Native函数可以直接使用系统调用。

    4. 上层函数

    待补充,目前还没发现有,但是自己可以在 Process.java 中进行封装后使用。

    5. 命令行工具

    taskset -p 0f <pid>

    将线程pid绑定到 CPU0-CPU3,注意是 0f 而不是 0x0f.

    6. cgroup 设置

    cpuset分组,每个分组tasks文件里面的任务绑定到cpus文件指定的cpu上,可以通过下面方法查看

    # find ./ -name cpus
    # find ./ -name cpus | xargs cat

    四、Demo

    #include <sched.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/time.h>
    #include <sys/resource.h>
    #include <linux/capability.h>
    
    
    #if 0
    int main()
    {
            int ret;
    
            struct sched_param param = {.sched_priority = 10};
    
            ret = sched_setscheduler(0, SCHED_FIFO, &param);
            if (ret) {
                printf("sched_setscheduler error, ret=%d: %s
    ", ret, strerror(errno)); //need 权限
                return -1;
            }
    
            printf("my pid=%d
    ", getpid());
    
            ret = setpriority(PRIO_PROCESS, getpid(), 20);
            if (ret) {
                printf("setpriority error, ret=%d: %s
    ", ret, strerror(errno)); //need 权限
                return -1;
            }
    
            while(1);
    
            return 0;
    }
    
    /*
    policy                                       :                    1
    prio                                         :                   89
    */
    #endif
    
    
    int main()
    {
        int ret;
        __user_cap_header_struct hdr;
        __user_cap_data_struct data;
    
        #if 0
        struct sched_param param = {.sched_priority = 0};
    
        ret = sched_setscheduler(0, SCHED_OTHER, &param);
        if (ret) {
                printf("sched_setscheduler error, ret=%d: %s
    ", ret, strerror(errno)); //need root权限
                return -1;
        }
        #endif
    
        printf("my pid=%d
    ", getpid());
    
    
        nice(5);
    
        #if 1
        hdr.version = _LINUX_CAPABILITY_VERSION; //setcaps
        hdr.pid = getpid();
        data.effective = (1 << CAP_SYS_NICE);
        data.permitted = (1 << CAP_SYS_NICE);
        data.inheritable = 0xffffffff;
        if (-1 == capset(&hdr, &data)) {
            printf("capset %s",strerror(errno));
            return -1;
        }
        
        ret = setpriority(PRIO_PROCESS, getpid(), -10); //在nice=0(prio=120)的基础上加10,无论之前优先级是多少
        if (ret) {
            printf("setpriority error, ret=%d: %s
    ", ret, strerror(errno)); //need root权限
            return -1;
        }
        #endif
    
        #if 0
        ret = setpriority(PRIO_PROCESS, getpid(), 5); //重复设置报错没权限
        if (ret) {
            printf("setpriority 2 error, ret=%d: %s
    ", ret, strerror(errno)); //need root权限
            return -1;
        }
        #endif
    
        while(1);
    
        return 0;
    }
  • 相关阅读:
    Asp.Net 获取客户端真实IP方法总结
    C# 中英文符号互转(半角全角互转)
    执行git commit命令提示: “Please tell me who you are”的解决方案
    Tools
    VSC
    DevOps
    VSC
    DevOps
    DevOps
    K8S
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/15359075.html
Copyright © 2020-2023  润新知