纲要
1、linux进程管理的模块组织框架
2、相关数据结构。
3、进程调度原则,调度算法,。
4、进程的创建和运行管理。
5、进程间通讯。
6、更多的技术
进程调度和中断处理交接
进程管理涉及的内核机制:bottom-half处理,等待队列
Linux/SMP的进程管理和调度技术
7、概述2.4的新特点
==============================================================================================
(1) 进程调度模块的内外界面:
1、对用户进程提供了一组简单的系统调用接口;
2、对内核的其他模块提供了丰富的接口功能。
(2) 进程调度模块和其他模块的相互依赖关系:
内存管理模块:当一个进程被调度的时候,为它建立内存映射。
IPC子模块:bottom-half处理使用了其中的信号量队列。
文件系统模块:在装载module的时候为进程调度提供实际设备的访问途径。
所有的其他模块都依赖于进程调度模块,因为当要进行硬件访问的时候它们需要CPU挂起用户进程,切换到系统态进行处理。
.
==============================================================================================
task_struct 是进程管理中最重要的数据结构。详见src/linux/include/linux/sched.h中的定义。
(1)进程状态信息
volatile long state;
它的取值有(@sched.h)以下几种,分别表示相应状态信息:
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 4
#define TASK_STOPPED 8
#define TASK_SWAPPING 16
(2) 进程切换的依据:
- 进程优先级:表示下一次调度前进程可运行的时间长度(用tick计算)。
- 错误处理:如果上一次系统调用失败,切换到相应的错误处理程序。
(3)进程索引结构:
结构之一:双向链:
struct task_struct *next_task, *prev_task;
struct task_struct *next_run, *prev_run;
结构之二:树结构:
struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
==============================================================================================
调度是实现方式:周期性时间中断。
Linux的时钟中断每隔10ms发生一次。时钟中断处理例程就是进行进程的重新调度。因此至多每隔10ms的周期,进程管理器(函数schedule()就会被调用。
不采用其他方式的原因:如果使用堆栈式的进程管理机制,由前后两个进程协商交接,则一旦当前进程出错或者用不法手段破坏堆栈的数据,系统将无法返回。为了保证安全,必须引入比较复杂的错误处理机制。而周期性时间中断由硬件强制切换,实现起来比较简单。
调度优先级:
(1)中断(硬件支持)
(2)当前的核心态进程
(3)其他核心态进程
(4)用户进程(软件管理)
用户进程的优先级分类
(1)实时进程
(2)交互进程:视为IO bound进程
(3)批处理进程:视为CPU bound进程
具体描述:
※
中断可以抢占核心进程,但必须保证在中断处理结束后返回它。--
一个核心态进程可以禁用它所运行的处理器上的中断,从而保证不会被中断请求信号中断它的运行。
※ 核心态进程不可抢占中断处理进程。--中断处理期间,仅仅是在中断处理进程处理完成或其他被允许的中断发生时候才发生任务切换。
※ 核心态进程不可抢占其他核心态进程。--除非一个核心态进程自愿睡眠,否则不能切换到别的进程。这保证了核心代码块的对其他进程的整体性,大大的简化了核心保护机制。
特点:核心态进程是非抢占,用户态进程是抢占的。
优点:核心数据的同步和保护机制比较简单。
缺点:不能很好的支持响应速度要求高的实时应用。
系统优先级:
动态优先级:计算goodness值。
时间片(slice/jiffies/quantum):
时间片的选择原则:在响应速度满足要求的的情况下尽量选择较大的时间片,减少系统开销。
修改时间片必须直接修改源代码。
(1) 直接启动
发生在当前进程因等待资源而需要进入被阻塞状态时。调度程序执行的步骤如下:
1、把当前进程(全局变量current指向的task_struct变量)放到适当的等待队列里;
2、把当前进程的state设为TASK_INTERRUPTIBEL或者TASK_UNINTERRUPTIBEL;
3、调用schedule(),准备让新的进程掌握CPU;
4、检查当前进程所需的资源是否可用,如果是,则把当前进程从等待队列里删除,否则回到第2步。
相关内容:等待队列
这些步骤和sleep_on()
,interruptible_sleep_on()的操作类似。然而,这里schedule()还在唤醒进程后马上把它从等待队列里删除。
调度程序还会被许多执行长周期任务的设备驱动程序所调用。在每一个周期循环里,这些设备驱动程序检测need_resched的值,并且在必要的时候调用schedule()强行放弃CPU。
通过在当前进程的need_resched设为1,就可以实现另一种方式重新调度各个进程。因为每次调入一个用户态进程之前,这个变量的值都会被检查,因此schedule()又会很快被调用。
被动调用在以下情况下执行:
当当前进程用完了它的CPU时间片,update_process_times()重新进行计算。
当一个进程被唤醒,而且它的优先级比当前进程高。wake_up_process
()调用reschedule_idle(),设置当前进程的need_resched,使被唤醒的进程尽快掌握CPU。
当sched_setschedler()或sched_yield()系统调用被调用的时候。
==============================================================================================
Linux中,进程的创建是通过拷贝已存在进程来实现的。
在Linux内核启动的时候,首先由start_kernel()初始化各个系统数据结构,同时生成了和系统共存亡的后台进程:init。可以参考内核的初始化过程。
init进程通过拷贝自身,产生了若干内核子进程。然后这些进程就可以通过系统调用fork()生成它们的子进程,当然这些子进程的原始数据都是他们的父亲的副本。进程的终止是通过系统调用_exit()实现的。
==============================================================================================
- Semaphores: an implementation of a classical semaphore model. The model also allows for the creation of arrays of semaphores.
- Message queues: a connectionless data-transfer model. A message is a sequence of bytes, with an associated type. Messages are written to message queues, and messages can be obtained by reading from the message queue, possibly restricting which messages are read in by type.
- Shared memory: a mechanism by which several processes have access to the same region of physical memory.
==============================================================================================
进程调度和中断处理交接
进程管理涉及的内核机制:bottom-half处理,等待队列
Linux/SMP的进程管理和调度技术
◎ 源代码结构的变化
子功能优化;
可读性更强(schedule());
◎ task_struct的变化
数据类型的变化;
管理变量的增加;
◎ 通用调度算法的变化:
Linux 2.4 introduces a subtle optimization concerning TLB flushing
for kernel threads and zombie processes.
As a result, the active Page Global Directory is set by the schedule(
) function rather than by the switch_to macro.
◎ SMP调度算法的变化:
The Linux 2.4 scheduling algorithm for SMP machines has been improved and
simplified.
Whenever a new process becomes runnable,
(1)the kernel checks whether the preferred CPU of the process, that is, the
CPU on which it was last running, is idle; in this case, the kernel assigns the process to
that CPU.
(2)Otherwise, the kernel assigns the process to another idle CPU, if any.
(3)If all CPUs are busy,
(3.1)the kernel checks whether the process has enough priority to
preempt the process running on the preferred CPU.
(3.2)If not,
the kernel tries to preempt some other CPU only
(3.2.1)if the new runnable process is real-time or
(3.2.2)if it has short average time slices compared to the hardware
cache rewriting time.
(Roughly, preemption occurs if the new runnable process is interactive
and the preferred CPU will not reschedule shortly.)
◎ 对实时进程的更好支持:SVR4
◎ 理论上无限制的进程数量
==============================================================================================
附录: