Linux 2.6.12 内核 进程 1 的创建(六)
现在进程 1 已经创建完成!但还没有执行,此时运行的仍然是进程 0
回到rest_init()函数:
static void noinline rest_init(void)
__releases(kernel_lock)
{
kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
此函数已执行完毕!
numa_default_policy();
空函数
unlock_kernel();
解锁大内核锁
preempt_enable_no_resched();
由于没有开启内核抢占,此函数为空!
cpu_idle();
}</pre>
<p></p>
好,下面进入cpu_idle() 函数的分析,分析这个有去无回的函数!
void cpu_idle (void)
{
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
首先检测当前进程,也就是进程0有没有设置 TIF_NEED_RESCHED 标志。表示当前进程需要立刻被调度!若设置则立刻调用下面的 schedule() 函数进行调度,否则进入循环!
在此时进程0已经设置了 TIF_NEED_RESCHED 标志!还记得在哪设置的吗?没错就在 init_idle() 函数中:set_tsk_need_resched(idle) 此函数设置的!在 init_idle() 函数中还设置了进程0的优先级(最小)等等……
注意进程0描述符不在 cpu 的运行队列中,所以进程0并不参与调度!
void (*idle)(void);
定义一个函数指针
if (__get_cpu_var(cpu_idle_state))
__get_cpu_var(cpu_idle_state) = 0;
声明了一个每处理器变量 per_cpu_cpu_idle_state ,类型为 unsigned int!负责记录每个 cpu 的 idle 进程的状态信息!
rmb();
内存屏障原语
idle = pm_idle;
idle应该为NULL
if (!idle)
idle = default_idle;
此时idle指向函数default_idle
__get_cpu_var(irq_stat).idle_timestamp = jiffies;
更新每 cpu 变量 per_cpu_irq_stat 中 idle_timestamp 字段值为系统时钟中断次数!此字段好像表示进程执行idle() 函数也就是 default_idle() 函数的时间?(不确定)
idle();
若当前进程一直没设置TIF_NEED_RESCHED 标志,则就一直循环调用idle()函数,直到设置了为止!
}
schedule();
进行进程调度,此时目的调度进程1的执行!
}
}</pre>
<p></p>
static inline int need_resched(void)
{
return unlikely(test_thread_flag(TIF_NEED_RESCHED));
}</pre>
<p></p>
static inline int test_thread_flag(int flag)
{
return test_bit(flag,¤t_thread_info()->flags);
}</pre>
<p>
检测当前进程描述符中 thread_info 字段指向的 thread_info 结构中 flags 字段是否设置 TIF_NEED_RESCHED 标志</p>
static DEFINE_PER_CPU(unsigned int, cpu_idle_state)
#define DEFINE_PER_CPU(type, name) \
__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name </pre>
<p></p>
void default_idle(void)
{
if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
local_irq_disable();
禁止中断!
if (!need_resched())
再次判断当前进程是否设置需要调度标志
safe_halt();
若还没设置此标志则执行开中断和 hlt 指令!
对于hlt指令本人并不是很清楚,也从来没用过。Google一下:
当 CPU 执行 HLT 指令时,CS 和 IP 指向 HLT 之后要执行的一条指令的地址,而CPU则处于“空操作”的暂停状态。此时,如果发生外部硬件中断,在CPU响应中断执行中断服务程序后,将返回到 HLT 后面的一条指令。所以,简要地说,HLT 指令的执行实际上是用软件方法使CPU处于暂停状态等待硬件中断,而硬件中断的发生又使CPU退出暂停状态。
除了外部硬件中断会使CPU退出暂停状态外,对系统进行复位操作,也会使CPU退出暂停状态。
else
local_irq_enable();
若此时终于设置了此标志则开中断,返回执行调度程序!
} else {
cpu_relax();
执行一些空操作
}
}</pre>
<p></p>
#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory")\
#define cpu_relax() rep_nop()
static inline void rep_nop(void)
{
__asm__ __volatile__("rep;nop": : :"memory");
}</pre>
<p></p>
接下来我们就应该分析schedule() 函数了,个人认为此函数非常难懂,我们下回分析吧!