sched_info_arrive()

本文介绍了一个内核级的进程调度统计方法,通过跟踪进程在就绪队列中的等待时间来评估进程调度效率。具体实现包括记录进程加入就绪队列的时间、计算每次调度延迟以及更新相关计数器。
进程t即将获得CPU控制权
汇总进程t在可执行队列上所等候时间的综合;更新进程t获得CPU控制权的时间戳
static inline void sched_info_arrive(task_t *t)
{
    unsigned long now = jiffies, diff = 0;
    struct runqueue *rq = task_rq(t);

    if (t->sched_info.last_queued)
        diff = now - t->sched_info.last_queued;
    sched_info_dequeued(t);
    t->sched_info.run_delay += diff;
    t->sched_info.last_arrival = now;
    t->sched_info.pcnt++;

    if (!rq)
        return;

    rq->rq_sched_info.run_delay += diff;
    rq->rq_sched_info.pcnt++;
}
task_struct.sched_info.last_queued        
    when we were last queued to run(最近一次加入runqueue的时间)
task_struct.sched_info.run_delay        
    time spent waiting on a runqueue(每一次进入runqueue到得到CPU控制权的时间间隔的总和)
task_struct.sched_info.pcnt                
    # of timeslices run on this cpu







这个函数干了啥,它有因为while太久而触发软死锁判断的可能吗?/* * Generic idle loop implementation * * Called with polling cleared. */ static void cpu_idle_loop(void) { while (1) { /* * If the arch has a polling bit, we maintain an invariant: * * Our polling bit is clear if we're not scheduled (i.e. if * rq->curr != rq->idle). This means that, if rq->idle has * the polling bit set, then setting need_resched is * guaranteed to cause the cpu to reschedule. */ __current_set_polling(); #if defined CONFIG_BCM_KF_INTERACTIVE && defined CONFIG_CPU_FREQ_GOV_INTERACTIVE idle_notifier_call_chain(IDLE_START); #endif tick_nohz_idle_enter(); while (!need_resched()) { check_pgt_cache(); rmb(); if (cpu_is_offline(smp_processor_id())) { rcu_cpu_notify(NULL, CPU_DYING_IDLE, (void *)(long)smp_processor_id()); smp_mb(); /* all activity before dead. */ this_cpu_write(cpu_dead_idle, true); arch_cpu_idle_dead(); } local_irq_disable(); arch_cpu_idle_enter(); /* * In poll mode we reenable interrupts and spin. * * Also if we detected in the wakeup from idle * path that the tick broadcast device expired * for us, we don't want to go deep idle as we * know that the IPI is going to arrive right * away */ if (cpu_idle_force_poll || tick_check_broadcast_expired()) cpu_idle_poll(); else cpuidle_idle_call(); arch_cpu_idle_exit(); } /* * Since we fell out of the loop above, we know * TIF_NEED_RESCHED must be set, propagate it into * PREEMPT_NEED_RESCHED. * * This is required because for polling idle loops we will * not have had an IPI to fold the state for us. */ preempt_set_need_resched(); tick_nohz_idle_exit(); #if defined CONFIG_BCM_KF_INTERACTIVE && defined CONFIG_CPU_FREQ_GOV_INTERACTIVE idle_notifier_call_chain(IDLE_END); #endif __current_clr_polling(); /* * We promise to call sched_ttwu_pending and reschedule * if need_resched is set while polling is set. That * means that clearing polling needs to be visible * before doing these things. */ smp_mb__after_atomic(); sched_ttwu_pending(); schedule_preempt_disabled(); } }
最新发布
09-19
<think>我们正在处理一个关于设置Linux进程调度策略为SCHED_NORMAL的编程问题。根据提供的引用,我们可以知道: - SCHED_NORMAL是Linux中的普通调度策略,即CFS(完全公平调度器),用于普通进程。 - 引用[3]中展示了设置调度策略的系统调用sched_setscheduler的使用,其中需要指定策略(policy)和优先级参数(struct sched_param)。 - 对于实时策略(如SCHED_FIFO和SCHED_RR),优先级范围是1~99,而SCHED_NORMAL(以及SCHED_BATCH、SCHED_IDLE)的优先级必须为0。 因此,要设置进程为SCHED_NORMAL,我们需要: 1. 将policy参数设置为SCHED_NORMAL(在Linux中,SCHED_NORMAL也被定义为SCHED_OTHER,值为0)。 2. 将优先级参数(sched_param结构中的sched_priority)设置为0。 步骤: 1. 包含必要的头文件:<sched.h> 2. 定义一个sched_param结构,并将其sched_priority成员设置为0。 3. 调用sched_setscheduler函数,指定进程ID(0表示当前进程)、策略(SCHED_NORMAL)和参数。 注意:需要具有相应的权限(CAP_SYS_NICE)或者以root用户运行,或者进程的有效用户ID等于目标进程的实际用户ID或保存用户ID(如引用[3]中权限检查部分)。 示例代码: ```c #include <sched.h> #include <stdio.h> #include <unistd.h> int main() { struct sched_param param; param.sched_priority = 0; // 对于SCHED_NORMAL,优先级必须为0 // 设置当前进程的调度策略为SCHED_NORMAL if (sched_setscheduler(0, SCHED_NORMAL, &param) == -1) { perror("sched_setscheduler failed"); return 1; } printf("Scheduling policy set to SCHED_NORMAL successfully.\n"); return 0; } ``` 编译并运行: - 编译:gcc program.c -o program - 运行:./program (可能需要root权限,取决于系统配置) 注意:如果进程之前是实时进程(如SCHED_FIFO或SCHED_RR),将其改为SCHED_NORMAL会使其变为非实时进程,由CFS调度。 相关问题: 1. 如何检查一个进程当前的调度策略? 2. SCHED_NORMAL和SCHED_BATCH有什么区别? 3. 在Linux中,如何以编程方式设置进程的优先级(nice值)? 4. 设置调度策略时,权限不足怎么办?</think>### Linux 设置进程调度策略为 SCHED_NORMAL 的方法 在 Linux 中设置进程调度策略为 `SCHED_NORMAL`(即标准 CFS 调度器)的步骤如下: #### 1. **核心方法** 使用系统调用 `sched_setscheduler()`,将优先级设为 0: ```c #include <sched.h> struct sched_param param = { .sched_priority = 0 // SCHED_NORMAL 必须优先级为0 }; int ret = sched_setscheduler(0, SCHED_NORMAL, &param); ``` - **参数说明**: - `pid`:0 表示当前进程 - `policy`:`SCHED_NORMAL`(或 `SCHED_OTHER`,两者等价) - `param`:优先级结构体,**必须设置 `sched_priority=0`**[^3] #### 2. **完整示例代码** ```c #include <sched.h> #include <stdio.h> #include <unistd.h> int main() { // 设置调度参数 struct sched_param param = { .sched_priority = 0 }; // 修改调度策略 if (sched_setscheduler(0, SCHED_NORMAL, &param) == -1) { perror("sched_setscheduler failed"); return 1; } printf("当前调度策略: %d (SCHED_NORMAL)\n", sched_getscheduler(0)); return 0; } ``` #### 3. **关键注意事项** 1. **权限要求**: - 需要 `CAP_SYS_NICE` 能力(通常需 root 权限) - 或进程有效 UID 与目标进程 UID 匹配[^3] 2. **优先级强制规则**: - `SCHED_NORMAL` 的优先级必须为 0,否则会返回 `-EINVAL` 错误[^3] - 实时策略(`SCHED_FIFO/RR`)优先级范围为 1-99 3. **调度行为变化**: - 从实时策略切回 `SCHED_NORMAL` 后,进程由 CFS 调度器管理 - 可通过 `nice` 值调整 CPU 时间分配比例(范围 -20~19) #### 4. **验证方法** ```bash # 编译程序 gcc sched_normal.c -o sched_normal # 需要root权限执行 sudo ./sched_normal # 查看结果 (应在输出中看到 SCHED_NORMAL) 当前调度策略: 0 (SCHED_NORMAL) ``` #### 5. **与其他策略的区别** | 策略 | 优先级范围 | 调度器 | 适用场景 | |------|------------|--------|----------| | `SCHED_NORMAL` | 固定为 0 | CFS | 普通应用 | | `SCHED_FIFO` | 1-99 | 实时调度器 | 高优先级实时任务[^2] | | `SCHED_RR` | 1-99 | 实时调度器 | 带时间片的实时任务[^2] | > 注:`SCHED_NORMAL` 是 Linux 默认调度策略,适用于 95% 的普通应用场景。实时策略仅建议在严格时限要求的场景(如音视频处理、工业控制)中使用。 --- ### 相关问题 1. **如何将实时进程(`SCHED_FIFO/RR`)切换回普通调度策略?** *(参考本文的代码示例和优先级规则)* 2. **设置调度策略时出现 `Operation not permitted` 错误如何解决?** *(涉及权限配置和能力机制)* 3. `SCHED_NORMAL` 和 `SCHED_BATCH` 调度策略有何区别? *(针对 CPU 密集型任务的优化差异)* 4. **如何以编程方式查询进程当前的调度策略?** *(使用 `sched_getscheduler()` 系统调用)* 5. **在容器(Docker)中设置调度策略有哪些限制?** *(涉及 cgroup 和权能字隔离机制)* [^1]: 设置调度参数示例,包括优先级配置 [^2]: `SCHED_FIFO` 和 `SCHED_RR` 实时调度策略的区别 [^3]: 内核处理函数及权限验证逻辑,强调 `SCHED_NORMAL` 必须优先级为 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值