Linux CFS调度器之msleep

本文详细探讨Linux内核CFS调度器中的msleep函数,涉及进程睡眠过程、超时处理以及唤醒机制。通过msleep函数,进程进入不可中断的睡眠状态,直到超时或被唤醒。在唤醒过程中,调度器会调整睡眠进程的vruntime值以确保公平性。同时,文章阐述了进程在不同状态下的调度逻辑和负载均衡策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言


我们之前多次提到过睡眠的进程由于没有占用CPU资源,所以其vruntime会比较少,睡眠时间越长,vruntime越小。为了防止睡眠进程醒来后,独占CPU导致其他进程饿死,进程醒来后,会重新调整其vruntime值,使其既能够收到CPU的优待,又不至于导致其他进程饥饿。

另外,由于之前只分析了CFS调度器相关的代码,所以本文涉及到具体调度器的时候,全部以CFS调度器为例。

进程睡眠msleep函数


msleep
void msleep(unsigned int msecs)
{
	unsigned long timeout = msecs_to_jiffies(msecs) + 1;

	while (timeout)
		timeout = schedule_timeout_uninterruptible(timeout);
}
  • 以jiffies为单位计算超时时间
  • 调用schedule_timeout_uninterruptible进行下一步处理。
    因为这里是sleep,说睡眠多久就睡眠多久,不能被提前唤醒,所以这里的睡眠是无法中断的,因此调用schedule_timeout_uninterruptible接口。
sleep->schedule_timeout_uninterruptible
signed long __sched schedule_timeout_uninterruptible(signed long timeout)
{
	__set_current_state(TASK_UNINTERRUPTIBLE);
	return schedule_timeout(timeout);
}
  • 进程状态设置为TASK_UNINTERRUPTIBLE状态,也就是说不能被提前唤醒。
  • 调用 schedule_timeout接口进行下一步处理。

sleep->schedule_timeout_uninterruptible->schedule_timeout

signed long __sched schedule_timeout(signed long timeout)
{
	struct timer_list timer;
	unsigned long expire;

	switch (timeout)
	{
	case MAX_SCHEDULE_TIMEOUT:
		/*
		 * These two special cases are useful to be comfortable
		 * in the caller. Nothing more. We could take
		 * MAX_SCHEDULE_TIMEOUT from one of the negative value
		 * but I' d like to return a valid offset (>=0) to allow
		 * the caller to 
C++实现公平调度算法(CFS,Completely Fair Scheduler)通常用于操作系统的进程管理中,它是一种基于时间片轮转的调度策略,旨在确保每个进程都能获得相对均衡的时间资源。在Linux内核中,CFS是默认的进程调度器。 下面是一个简单的C++伪代码示例,展示了如何模拟基本的公平调度过程: ```cpp #include <vector> #include <chrono> class Process { public: int pid; int priority; std::chrono::time_point<std::chrono::high_resolution_clock> lastTurn; // 初始化函数 Process(int id, int p) : pid(id), priority(p), lastTurn(std::chrono::steady_clock::now()) {} void run() { if (std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - lastTurn).count() > currentTimeSlice) { lastTurn = std::chrono::steady_clock::now(); runActualTask(); // 这里替换为实际的任务执行逻辑 } else { std::this_thread::sleep_for(std::chrono::microseconds(currentTimeSlice - (std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - lastTurn).count()))); } } private: virtual void runActualTask() = 0; // 要子类覆盖的函数 }; class HighPriorityProcess : public Process { public: override void runActualTask() { // 高优先级任务处理 } }; class LowPriorityProcess : public Process { public: override void runActualTask() { // 低优先级任务处理 } }; // 调度管理 void fairScheduler(const std::vector<Process*>& processes, int currentTimeSlice) { for (auto& process : processes) { process->run(); } } int main() { std::vector<Process*> processes{new HighPriorityProcess(1, 5), new LowPriorityProcess(2, 2)}; fairScheduler(processes, 1000); // 每次循环时间片为1毫秒 //... return 0; } ``` 注意:这只是一个基础的演示,并未完全遵循真实的CFS算法,因为CFS会在内核级别实现,涉及到线程、锁和系统调用等复杂细节。上面的代码仅表示一个思想,实际应用需要结合操作系统知识进行编写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值