30分钟读懂Linux进程调度(图文并茂)

本文从滴答视角出发,详细解析Linux进程调度机制,涉及时钟中断、do_timer函数、进程调度及switch_to过程。同时,从数据结构角度探讨task_struct结构在进程管理中的作用,阐述了操作系统启动流程中与进程调度相关的初始化工作。
摘要由CSDN通过智能技术生成

滴答视角

滴答

计算机中有一个设备,叫定时器,准确说叫可编程定时/计数器。

这个定时器每隔一段时间就会向 CPU 发起一个中断信号。

在 linux-0.11 中,这个间隔时间被设置为 10 ms,也就是 100 Hz。

shedule.c

#define HZ 100

发起的中断叫时钟中断,其中断向量号被设置为了 0x20。

时钟中断

一切的源头,就源于这个每 10ms 产生的一次时钟中断。

当然如果没有操作系统的存在,这个 10ms 一次的时钟中断,就打了水漂,CPU 会收到这个时钟中断信号,但不会做出任何反应。

但很不幸,linux 提前设置好了中断向量表。

schedule.c

set_intr_gate(0x20, &timer_interrupt);

这样,当时钟中断,也就是 0x20 号中断来临时,CPU 会查找中断向量表中 0x20 处的函数地址,这个函数地址即中断处理函数,并跳转过去执行。

这个中断处理函数就是 timer_interrupt,是用汇编语言写的。

system_call.s

_timer_interrupt:
    ...
    // 增加系统滴答数
    incl _jiffies
    ...
    // 调用函数 do_timer
    call _do_timer
    ...

这个函数做了两件事,一个是将系统滴答数这个变量 jiffies 加一,一个是调用了另一个函数 do_timer。

sched.c

void do_timer(long cpl) {
    ...
    // 当前线程还有剩余时间片,直接返回
    if ((--current->counter)>0) return;
    // 若没有剩余时间片,调度
    schedule();
}

do_timer 最重要的部分就是上面这段代码,非常简单。

首先将当前进程的时间片 -1,然后判断:

如果时间片仍然大于零,则什么都不做直接返回。

如果时间片已经为零,则调用 schedule(),用脚去想也知道,这就是进行进程调度的主干。

进程的调度

void schedule(void) {
    int i, next, c;
    struct task_struct ** p;
    ...
    while (1) {
        c = -1;
        next = 0;
        i = NR_TASKS;
        p = &task[NR_TASKS];
        while (--i) {
            if (!*--p)
              
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值