手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网站运营>建站经验>列表

linux中的时间流

来源:互联网 作者:west263.com 时间:2008-04-16
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
void do_gettimeofday(struct timeval *tv); 源码中描述do_gettimeofday在许多体系结构上有“接近微秒级的分辨率”,然而实际精度是随不同的平台而变化的,在旧版本的内核中还会低些。当前时间也能够通过 xtime 变量(类型为struct timeval)获得(但精度差些),但是,并不鼓励直接使用该变量,因为除非关闭中断,否则无法原子性地访问 timeval 变量的两个成员 tv_sec 和 tv_usec。在2.2版的内核中,一个快捷安全的获得时间的办法(可能精度会差些)是使用 get_fast_time: void get_fast_time(struct timeval *tv); 获取当前时间的代码可见于jit(“Just In Time”)模块,源文档能够从 O'Reilly公司的 FTP站点获得。jit模块将创建 /proc/currentime 文档,读取该文档将以 ASCII 码的形式返回三项: 由 do_gettimeofday 返回的当前时间 从 xtime 钟获得的当前时间 jiffies 的当前值 我们选择用动态的 /proc 文档,是因为这样模块代码量会小些――不值得为返回三行文本而写一个完整的设备驱动程式。 If you use \*[PGN]cat\*[/PGN] to read the file multiple times in less than a timer tick, you'll see the difference between xtime and [ I ]do_gettimeofday[ R ], reflecting the fact that xtime is updated less frequently: 假如用 cat 命令在一个时钟滴答内多次读该文档,就会发现 xtime 和 do_gettimeofday 两者的差异了,xtime 更新的次数不那么频繁: morgana% cd /proc; cat currentime currentime currentime gettime: 846157215.937221 xtime: 846157215.931188 jiffies: 1308094 gettime: 846157215.939950 xtime: 846157215.931188 jiffies: 1308094 gettime: 846157215.942465 xtime: 846157215.941188 jiffies: 1308095 延迟执行 设备驱动程式经常需要将某些特定代码延迟一段时间后执行――通常是为了让硬件能完成某些任务。这一节将介绍许多实现延迟的不同技术,哪种技术最好取决于实际环境中的具体情况。我们将介绍任何的这些技术并指出各自的优缺点。 一件需要考虑的很重要的事情是所需的延迟长度是否多于一个时钟滴答。较长的延迟能够利用系统时钟;较短的延迟通常必须通过软件循环来获得。 长延迟 假如想把执行延迟若干个时钟滴答,或对延迟的精度需要不高(比如,想延迟整数数目的秒数),最简单的也是最笨的实现如下,也就是所谓的“忙等待”: unsigned long j = jiffies jit_delay * HZ; while (jiffies < j) /* nothing */; 这种实现当然要避免。我们在这里提到他,只是因为读者可能某时需要运行这段代码,以便更好地理解其他的延迟技术。 还是先看看这段代码是如何工作的。因为内核的头文档中jiffies被声明为volatile型变量,每次C代码访问他时都会重新读取他,因此该循环能够起到延迟的作用。尽管也是“正确”的实现,但这个忙等待循环在延迟期间会锁住处理器,因为调度器不会中断运行在内核空间的进程。更糟糕的是,假如在进入循环之前正好关闭了中断,jiffies值就不会得到更新,那么while循环的条件就永远为真,这时,您不得不按下那只大的红按钮(指电源按钮)。 这种延迟和下面的几种延迟方法都在jit模块中实现了。由该模块创建的任何 /proc/jit* 文档每次被读取时都延迟整整 1 秒。假如您想测试忙等待代码,能够读 /proc/jitbusy 文档,当该文档的 read 方法被调用时他将进入忙等待循环,延迟 1 秒;而象dd if=/proc/jitbusy bs=1这样的命令每次读一个字符就要延迟 1 秒。 能够想见,读 /proc/jitbusy 文档会大大影响系统性能,因为此时电脑要到1秒后才能运行其他进程。 更好的延迟方法如下,他允许其他进程在延迟的时间间隔内运行,尽管这种方法不能用于硬实时任务或其他对时间需要很严格的场合: while (jiffies < j) schedule(); 这个例子和下面各例中的变量j应是延迟到达时的jiffies值,计算方法和忙等待相同。 这种循环(能够通过读 /proc/jitsched 文档来测试他)延迟方法还不是最优的。系统能够调度其他任务;当前任务除了释放CPU之外不做任何工作,但是他仍在任务队列中。假如他是系统中唯一的可运行的进程,他还会被运行(系统调用调度器,调度器选择同一个进程运行,此进程又再调用调度器,然后...)。换句话说,机器的负载(系统中运行的进程平均数)至少为1,而idle进程(进程号为0,由于历史原因被称为“swapper”)绝不会被运行。尽管这个问题看来无所谓,当系统空闲时运行idle进程能够减轻处理器负载,降低处理器温度,延长处理器寿命,假如是手提电脑,还能延长电池的寿命。而且,延迟期间实际上进程是在执行的,因此延迟消耗的任何时间都是记在他的运行时间上的。运行命令 time cat /proc/jitsched 就能够发现这一点。 另一种情况下,假如系统很忙,驱动程式等待的时间可能会比预计多得多。一旦一个进程在调度时让出了处理器,无法确保以后的某个时间就能重新分配给他。假如可接受的延迟时间有上限的话,用这种方式调用schedule,对驱动程式来说并不是个安全的解决方案。 尽管有些毛病,这种循环延迟还是提供了一种有点“脏”但比较快的监控驱动程式工作的途径。假如模块中的某个 bug 会锁死整个系统,则可在每个用于调试的 printk 语句后添加一小段延迟,这样能够确保在处理器碰到令人厌恶的 bug 而被锁死之前,任何的打印消息都能进入系统日志。假如没有这样的延迟,这些消息只能进入内存缓冲区,但在 klogd 得到运行前系统可能已被锁住了。 获得延迟的最好方法,是请求内核为我们实现延迟。根据驱动程式是否在等待其他事件,有两种配置短期延迟的办法。 假如驱动程式使用等待队列等待某个事件,而您又想确保在一段时间后一定运行该驱动程式,能够使用 sleep 函数的超时版本,这在第5章“睡眠和唤醒”一节中已介绍过了: sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout); interruptible_sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout); 两种实现都能让进程在指定的等待队列上睡眠,而在超时期限(用jiffies表示)未到时的任何事件都会将其唤醒。由此他们就实现了一种有上限的不会永远持续下去的睡眠。注意超时值表示要等待的 jiffies 数量,而不是绝对的时间值。这种方式的延迟能够在 /proc/jitqueue 的实现中看到: wait_queue_head_t wait; init_waitqueue_head (&wait); interruptible_sleep_on_timeout(&wait, jit_delay*HZ); 在通常的驱动程式中,能够以下列两种方式重新获得执行:在等待队列上调用一个 wake_up,或 timout 超时。在这个特定实现中,没人会调用 wake_up(毕竟其他代码根本就不知道这件事),所以进程总是因 timeout 超时而被唤醒。这是个完美有效的实现,但是,假如驱动程式无须等待其他事件,能够用一种更直接的方式获取延迟,即使用schedule_timeout: set_current_state(TASK_INTERRUPTIBLE); schedule_timeout (jit_delay*HZ); 上述代码行(在 /proc/jitself 中实现)使进程进入睡眠直到指定时间。schedule_timeout也是处理一个时间增量而不是个 jiffies 的绝对值。和前面相同,在从超时到进程实际被调度执行之间,可能会消耗一些毫无价值的额外时间。 短延迟 有时驱动程式需要很短的延迟来和硬件同步。此时,使用jiffies值无法达到目的。 这时就要用内核函数udelay 和 mdelay*。 ============footnote begins=========== u表示希腊字母“mu”(μ),他代表“微”。 ============footnote ends=========== 他们的原型如下: #include

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!