一、进程
每一个进程都可以用task_struct结构体来描述
进程状态: TASK_RUNNING
TASK_INTERRUPTIABLE
TASK_UNINTERRUPTIABLE
TASK_KILLABLE
二、调度
调度就是从就绪状态的进程基于某种算法选择出最合适的进程去运行
调度策略
SCHED_NORMAL(SCHED_OTHER) 普通的分时进程
SCHED_FIFO 先入先出的实时进程
SCHED_RR 基于时间片轮转的实时进程
SCHED_BATCH 批处理进程
SCHED_IDEL 只有系统空闲时才会别调用的进程
调度时机
什么时候开始调度? 即是schedule()什么时候被调用?
1、主动式
当进程需要等待资源而暂时让出CPU,进程会被挂起(睡眠状态),这时可以在内核中调用schedule()主动请求调度。
例子:current->state = TASK_INTERRUPTIABLE;
schedule()
2、被动式(抢占)
支持内核抢的系统中,更高优先级的进程/线程可以抢占正在内核空间运行的低优先级进程/线程
在支持内核抢占的系统中,以下特例是不允许内核抢占的
1)内核正在进行中断处理,进程调度函数schedule()会对对此作出判断,如果是打印出错信息
2)内核正在进行中断上下文的中断的低半部处理
3)进程正在持有spinlock自旋锁、writelock()/readlock()读写锁,当持有这些锁时不应该被抢占,否则会导致其他cpu长期不能获得锁而产生死锁现象。
4)内核正在执行调度函数schedule,重复抢占没有意义。
调度标志
TIF_NEED_RESCHED
作用:内核提供了一个need_resched标志来表明是否需要重新执行一次调度
设置:当某个进程时间片耗尽时,会设置这个标志
当一个优先级更高的进程进行可执行状态时候,也会设置这个标志
调度步骤
1)清理当前运行中的进程
2)选择下一个要运行的进程(pick_next_task)
3)设置新进程运行的环境
4)进程上下文切换
三、系统调用
系统调用在内核中都有一个系统调用号
内核根据应用程序传递的系统调用号,从系统调用表sys_call_table中找到对应的系统调用处理函数
CALL(sys_call_exit)
如何向内核中添加自己的系统调用
1、添加新的内核函数
2、更新头文件unistd.h
3、针对这个新函数更新系统调用表calls.S