3.5 软件时钟的应用

软件时钟的处理是在处理软中断时触发的,而软中断的处理又会紧接着硬件中断处理结束而进行,并且系统会周期地产生时钟中断硬件中断),这样,软件时钟的处理至少会在系统每一次时钟中断处理完成后触发如果软件时钟的到期时间大于系统当前的 jiffies ,表明时间未到期,则不会调用保存在软件时钟中的函数,但此时的确提供了处理软件时钟的时机)。从这点上看,软件时钟会有较快的相应——一旦时间到期,保存在软件时钟中的函数会将快地被调用在时钟软中断中被调用,参见3.3.2节)。所以内核中凡是需要隔一段时间间隔后作指定操作的过程都通过软件时钟完成。例如大部分设备驱动程序使用软件时钟探测异常条件、软盘驱动程序利用软件时钟关闭有一段时间没有被访问软盘的设备马达、进程的定时睡眠 schedule_timeout 函数)和网络超时重传等等。

本节主要通过介绍进程的定时睡眠 schedule_timeout 函数)和网络超时重传来说明软件时钟的应用。

3.5.1 进程的定时睡眠

函数 schedule_timeout 的代码如清单3-12

清单3-12 函数 schedule_timeout

signed long __sched schedule_timeout(signed long timeout)
{
struct timer_list timer;
unsigned long expire;

……
expire = timeout + jiffies;

setup_timer(&timer, process_timeout, (unsigned long)current);
__mod_timer(&timer, expire);
schedule();
del_singleshot_timer_sync(&timer);

timeout = expire - jiffies;

out:
return timeout < 0 ? 0 : timeout;
}

函数 schedule_timeout 定义了一个软件时钟变量 timer ,在计算到期时间后初始化这个软件时钟:设置软件时钟当时间到期时的处理函数为 process_timeout ,参数为当前进程描述符,设置软件时钟的到期时间为 expire 。之后调用 schedule() 函数。此时当前进程睡眠,交出执行权,内核调用其它进程运行。但内核在每一个时钟中断处理结束后都要检测这个软件时钟是否到期。如果到期,将调用 process_timeout 函数,参数为睡眠的那个进程描述符。 process_timeout 函数的代码如清单3-13。

清单3-13 函数 process_timeout

static void process_timeout(unsigned long __data)
{
wake_up_process((struct task_struct *)__data);
}

函数 process_timeout 直接调用 wake_up_process 将进程唤醒。当内核重新调用该进程执行时,该进程继续执行 schedule_timeout 函数,执行流则从 schedule 函数中返回,之后调用 del_singleshot_timer_sync 函数将软件时钟卸载,然后函数 schedule_timeout 结束。函数 del_singleshot_timer_sync 是实际上就是函数 del_timer_sync 参见3.3.2节),如清单3-14

清单3-14 函数del_singleshot_timer_sync
#define del_singleshot_timer_sync(t) del_timer_sync(t)

以上就是进程定时睡眠的实现过程。接下来介绍的是软件时钟在网络超时重传上的应用。


相关内容