调度器30—调度相关结构体—p->state

一、TASK_DEAD

1. 赋值调用路径

do_exit //的最后调用
    do_task_dead //sched/core.c
        set_special_state(TASK_DEAD);
            WRITE_ONCE(current->__state, state_value);

copy_process //fork.c 中 copy_creds() 执行失败调用,非主要路径
    WRITE_ONCE(p->__state, TASK_DEAD); //kernel/fork.c

看来是任务自己主动退出时将自己设置为 TASK_DEAD 状态。

 

二、TASK_NOLOAD

1. TASK_NOLOAD 或在 TASK_IDLE 上使用,主要使用位置:

#define TASK_IDLE    TASK_UNINTERRUPTIBLE | TASK_NOLOAD)

swait_event_idle_exclusive //这里面使用 TASK_IDLE 状态
schedule_timeout_idle(signed long timeout) //将当前进程设置为 TASK_IDLE,然后休眠timeout时间后被唤醒

schedule_timeout_uninterruptible(signed long timeout) //常用的是这类将当前进程设置为 TASK_UNINTERRUPTIBLE/TASK_INTERRUPTIBLE

2. TASK_NOLOAD 唯一使用位置:

__schedule
    if (!preempt && prev_state) { //若不是抢占,prev->state的状态也不是TASK_RUNNING才会发生deactive prev task。
        prev->sched_contributes_to_load =(prev_state & TASK_UNINTERRUPTIBLE) && 
            !(prev_state & TASK_NOLOAD) && !(prev->flags & PF_FROZEN); //主要影响 sched_contributes_to_load 的值
        
        if (prev->sched_contributes_to_load)
            rq->nr_uninterruptible++;
    }

3. prev->sched_contributes_to_load 的使用位置:

位置1:

ttwu_do_activate
    if (p->sched_contributes_to_load)
            rq->nr_uninterruptible--;

位置2:就是上面赋值和加加,没有其它使用位置了。

4. rq->nr_uninterruptible 使用位置:

print_cpu ///kernel/sched/debug.c
    P(nr_uninterruptible)  //# cat /proc/sched_debug | grep nr_uninterruptible 打印每个cpu的这个值

然后就是上面core.c中的++/--

        scheduler_tick //core.c
            calc_load_nohz_fold //loadavg.c 将delta加到全局变量 calc_load_tasks

    tick_nohz_stop_tick
        calc_load_nohz_start //loadavg.c
sched_tick_start
    sched_tick_remote //core.c INIT_DELAYED_WORK(&twork->work, sched_tick_remote); 异步调用的
        calc_load_nohz_remote //loadavg.c  
            calc_global_load_tick
                calc_load_fold_active
                    nr_active += (long)this_rq->nr_uninterruptible;

loadavg.c: 全局负载平均值是 nr_running + nr_uninterruptible 的指数衰减平均值。

5. 全局变量 calc_load_tasks:

在 loadavg.c 中主要用于初始化 avenrun[] 数组

avenrun[] 数组:
    SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info) //kernel/sys.c
    COMPAT_SYSCALL_DEFINE1(sysinfo, struct compat_sysinfo __user *, info) //kernel/sys.c
        do_sysinfo //kernel/sys.c
            get_avenrun //sched/loadavg.c

拷贝到用户空间,报告 1, 5, and 15 minute load averages。

/proc/loadavg 文件,cat如下
    loadavg_proc_show //proc/loadavg.c
        get_avenrun //sched/loadavg.c

//对应:
# cat /proc/loadavg
15.30 15.21 12.72 1/3499 8280

6. 结论:看来 TASK_NOLOAD 的影响对调度/调频没有关系,只与上层统计 1, 5, 15分钟的负载有关。

 

posted on 2023-01-31 22:37  Hello-World3  阅读(226)  评论(0编辑  收藏  举报

导航