目录
一、进程调度的时机
Linux系统中的进程调度是由调度器(scheduler)负责的,它的任务是按照一定的策略选择下一个要运行的进程。进程调度的时机主要包括以下几种情况:
-
时钟中断: 进程调度通常是由系统时钟中断触发的。Linux内核会使用时钟中断来维护系统时间,并在每次时钟中断时考虑是否进行进程切换。时钟中断的频率通常是固定的,比如每10毫秒触发一次。
-
进程主动让出CPU: 如果一个进程执行了系统调用或者发起了一个阻塞的操作,它会主动让出CPU,这时调度器有机会选择下一个要运行的进程。
-
进程结束或阻塞: 当一个进程执行完成或者由于某些原因(如等待I/O操作完成)而阻塞时,调度器会选择新的进程来执行。
-
高优先级任务就绪: 如果有一个高优先级的任务就绪并等待运行,调度器可能会中断当前进程的执行,切换到高优先级任务。
-
时间片用尽: 每个进程被分配一个时间片(quantum),当这个时间片用尽时,调度器会选择新的进程来执行。
-
抢占式调度: 如果系统支持抢占式调度,即内核允许更高优先级的进程中断当前运行的进程,那么在高优先级进程就绪时,调度器可能会触发抢占。
二、schedule()函数
在内核文件夹内,可以用如下命令去查找哪里调用了 schedule()函数:
grep -r "schedule" /path/to/kernel/source
大约可见:时钟中断处理函数、进程主动让出CPU、进程阻塞、定时器、中断上下文切换等进程函数会用到该函数
三、gdb 跟踪分析一个 schedule()函数
指令如下所示,可以跟踪分析该函数:
1、启动QEMU虚拟机,加载Linux内核镜像 bzImage
,并附加 rootfs.img
作为根文件系统。
2、在 GDB 中加载 Linux 内核符号表
3、在 GDB 中连接到之前启动的 QEMU GDB 服务器,端口号为 1234
4、在 schedule
函数、context_switch
函数、pick_next_task
函数处设置断点
5、执行并在断点位置处显示源代码以方便分析
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
gdb
file linux-3.18.6/vmlinux
target remote:1234
b schedule
b context_switch
b pick_next_task
c
list
c
list
综上可得:
1、schedule
函数是 Linux 内核调度器的核心。它负责选择下一个要执行的任务,并切换到该任务的上下文。调用 schedule
函数会触发一系列的调度决策,包括选择下一个任务、保存当前任务的上下文以及加载新任务的上下文。
2、context_switch
函数负责执行实际的任务切换。它在任务切换的时候保存当前任务的上下文,然后加载下一个任务的上下文。这个函数通常会在 schedule
函数内部被调用,用于完成任务切换的底层操作。
3、pick_next_task
函数用于选择下一个要执行的任务。在调度器的上下文中,它根据一定的调度算法从可运行任务队列中选择一个合适的任务。pick_next_task
函数返回所选择的任务的指针,该任务将成为下一个要执行的任务。
三个函数协同工作,构成了 Linux 调度器的核心部分。schedule
负责整个调度决策的逻辑,context_switch
则负责实际的任务切换过程,而 pick_next_task
用于选择下一个要执行的任务。这样的设计使得 Linux 内核能够高效地进行多任务处理,确保不同任务在适当的时候得到执行。这对于实现多任务操作系统的正常运行至关重要。
附、chatGPT辅助问答:
1、
2、
3、