http://book.51cto.com/art/200810/93784.htm
Linux 2.6内核标准教程》第6章时间度量,这一章围绕墙上时间xtims和相对时间jiffies两个主体进行阐述,从硬件支持到软件架构;从时间度量模块的初始化到如何使用时间度量的工作机制;从软件定时器的使用到软件定时器的工作原理。本节讲述的是如何对当前被中断的进程(用户进程或内核线程)进行记帐,以及记帐时完成了那些工作。
AD:
6.4.3 对当前进程记账
下面分析时钟中断处理过程如何对当前被中断的进程(用户进程或内核线程)进行记帐,以及记帐时完成了那些工作。下面是对负责进程记帐的函数update_process_times()的分析。
代码清单6.15--函数update_process_times
功能简介:该函数负责对当前进程进行记账,减小进程剩余可用的时间片。然后激活其他内核模块的处理函数,如同步机制RCU的处理函数、内核定时器的处理函数。
文件:src/kernel/timer.c
784 void update_process_times(int user_tick)
785 {
786 struct task_struct *p = current;
787 int cpu = smp_processor_id();
788
789 /* Note: this timer irq context must be accounted for as well. */
790 if (user_tick)
791 account_user_time(p, jiffies_to_cputime(1));
792 else
793 account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
794 run_local_timers();
795 if (rcu_pending(cpu))
796 rcu_check_callbacks(cpu, user_tick);
797 scheduler_tick();
798 run_posix_cpu_timers(p);
799 } |
static inline int user_mode(struct pt_regs *regs)
{
return (regs->xcs & 3) != 0;
} |
第786~787行代码通过宏定义current、smp_processor_id()获得当前进程描述符指针和当前处理器编号,并将其分别保存到指针变量p和整型cpu中。
第790~793行代码根据被中断进程运行于用户态还是系统态分别调用account_ user_time()、account_system_time()对被中断进程进行记账。它们分别将进程描述符中用户态时间字段utime、内核态时间字段stime的值加上jiffies_to_cputime(1),表示进程在用户态或者内核又运行了一个系统时钟滴答。然后更新处理器历史统计信息。其中jiffies_to_cputime()是一个宏定义,该宏定义用于将一个时钟中断转换为处理器时间。
第794行调用函数run_local_timers()设置时钟中断处理的下半部处理标记、激活时钟中断处理的下半部。该下半部负责维护、更新内核定时器链表,对于超时的内核定时器执行相应的超时处理函数,并将超时的定时器移出内核定时器链表。详情请参见6.5节。其中函数run_local_timers()在文件src/kernel/timer.c中的第867行定义如下。关于函数raise_softirq的功能请参见5.5.1小节。
void run_local_timers(void)
{
raise_softirq(TIMER_SOFTIRQ);
} |
第795~796行代码用于处理内核同步机制RCU所使用的数据,将老版本的数据删除。详情请参见8.4.2小节。
第797行调用函数scheduler_tick()判断被中断进程的时间片是否用完。如果用完设置该进程描述中的调度标记,在中断处理完毕、中断返回时系统会检查该标记;如果设置了该标记,系统会重新调度选择合适的进程运行。
第798行调用函数run_posix_cpu_timers()处理向用户进程提供的POSIX标准的时钟,这里不作更深入的介绍。
本文详细解析Linux2.6内核中时间度量机制,包括墙上时间xtims和相对时间jiffies,以及如何通过update_process_times()函数对当前被中断的进程进行记账。分析了在不同状态下对进程时间的记录方式,如用户态和内核态,并解释了记账过程中的关键步骤,如更新时间片、激活内核模块处理函数等。
3341

被折叠的 条评论
为什么被折叠?



