ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:125.77KB ,
资源ID:2200133      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/2200133.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(linux定时器.docx)为本站会员(b****2)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

linux定时器.docx

1、linux定时器目录一、设计题目与要求 1二、实验思想 12.1 Linux内核对定时器的描述 12.2 Linux 内核定时器 32.3 Linux 信号signal处理机制 6三、内核定时器机制的实现 63.1动态定时器机制的初始化 63.2 将定时器插入到链表中 7四、数据结构与模块说明 94.1 定时器使用 94.2 程序流程图 104.3 源程序 104.4 运行结果与运行情况 11五、实验心得 13六、参考文献 14Linux定时器实验一、设计题目与要求11设计题目:Linux定时器12设计要求:通过研究Linux内核的时间函数,学习内核源代码;然后应用这些知识并且使用“信号”机制

2、建立一种定时器实验,每隔多长时间打印出当前系统的时间,并且计算出每次调度的时间。二、实验思想2.1 Linux内核对定时器的描述Linux在include/linux/timer.h头文件中定义了数据结构timer_list来描述一个内核定时器: struct timer_list struct list_head list; unsigned long expires; unsigned long data; void (*function)(unsigned long); ; 各数据成员的含义如下: (1)双向链表元素list:用来将多个定时器连接成一条双向循环队列。 (2)expires

3、:指定定时器到期的时间,这个时间被表示成自系统启动以来的时钟滴答计数(也即时钟节拍数)。当一个定时器的expires值小于或等于jiffies变量时,我们就说这个定时器已经超时或到期了。在初始化一个定时器后,通常把它的expires域设置成当前expires变量的当前值加上某个时间间隔值(以时钟滴答次数计)。 (3)函数指针function:指向一个可执行函数。当定时器到期时,内核就执行function所指定的函数。而data域则被内核用作function函数的调用参数。内核函数init_timer()用来初始化一个定时器。实际上,这个初始化函数仅仅将结构中的list成员初始化为空。如下所示(

4、include/linux/timer.h): static inline void init_timer(struct timer_list * timer) timer-list.next = timer-list.prev = NULL; 由于定时器通常被连接在一个双向循环队列中等待执行(此时我们说定时器处于pending状态)。因此函数time_pending()就可以用list成员是否为空来判断一个定时器是否处于pending状态。如下所示(include/linux/timer.h): static inline int timer_pending (const struct ti

5、mer_list * timer) return timer-list.next != NULL; 时间比较操作在定时器应用中经常需要比较两个时间值,以确定timer是否超时,所以Linux内核在timer.h头文件中定义了4个时间关系比较操作宏。这里我们说时刻a在时刻b之后,就意味着时间值ab。Linux强烈推荐用户使用它所定义的下列4个时间比较操作宏(include/linux/timer.h): #define time_after(a,b) (long)(b) - (long)(a) = 0) #define time_before_eq(a,b) time_after_eq(b,a)

6、2.2 Linux 内核定时器 定时器是管理内核时间的基础,用来计算流逝的时间,它以某种频率(节拍率)自行触发时钟中断,当时钟中断发生时,内核就通过一种特殊中断处理程序对其进行处理。但是原来的实现只能是time_t mytime形式的,经过简单的localtime(mytime)和ctime(&mytime)处理.精度是不够的,为了返回高精度的时间,这里使用了gettimeofday函数。 这个syscall用来供用户获取timeval格式的当前时间信息(精确度为微秒级),以及系统的当前时区信息(timezone)。结构类型timeval的指针参数tv指向接受时间信息的用户空间缓冲区,参数tz

7、是一个timezone结构类型的指针,指向接收时区信息的用户空间缓冲区。这两个参数均为输出参数,返回值0表示成功,返回负值表示出错。函数sys_gettimeofday()的源码如下(kernel/time.c): asmlinkage long sys_gettimeofday(struct timeval *tv, struct timezone *tz) if (tv) struct timeval ktv; do_gettimeofday(&ktv); if (copy_to_user(tv, &ktv, sizeof(ktv) return -EFAULT; if (tz) if (

8、copy_to_user(tz, &sys_tz, sizeof(sys_tz) return -EFAULT; return 0; 显然,函数的实现主要分成两个大的方面: (1)如果tv指针有效,则说明用户要以timeval格式来检索系统当前时间。为此,先调用do_gettimeofday()函数来检索系统当前时间并保存到局部变量ktv中。然后再调用copy_to_user()宏将保存在内核空间中的当前时间信息拷贝到由参数指针tv所指向的用户空间缓冲区中。 (2)如果tz指针有效,则说明用户要检索当前时区信息,因此调用copy_to_user()宏将全局变量sys_tz中的时区信息拷贝到参数

9、指针tz所指向的用户空间缓冲区中。 (3)最后,返回0表示成功。函数do_gettimeofday()的源码如下(arch/i386/kernel/time.c): void do_gettimeofday(struct timeval *tv) unsigned long flags; unsigned long usec, sec; read_lock_irqsave(&xtime_lock, flags); usec = do_gettimeoffset(); unsigned long lost = jiffies - wall_jiffies; if (lost) usec += l

10、ost * (1000000 / HZ); sec = xtime.tv_sec; usec += xtime.tv_usec; read_unlock_irqrestore(&xtime_lock, flags); while (usec = 1000000) usec -= 1000000; sec+; tv-tv_sec = sec; tv-tv_usec = usec; 该函数的完成实际的当前时间检索工作。由于gettimeofday()系统调用要求时间精度要达到微秒级,因此do_gettimeofday()函数不能简单地返回xtime中的值即可,而必须精确地确定自从时钟驱动的Bott

11、om Half上一次更新xtime的那个时刻到do_gettimeofday()函数的当前执行时刻之间的具体时间间隔长度,以便精确地修正xtime的值。 假定被do_gettimeofday()用来修正xtime的时间间隔为fixed_usec,而从wall_jiffies到jiffies之间的时间间隔是lost_usec,而从jiffies到do_gettimeofday()函数的执行时刻的时间间隔是offset_usec。则下列三个等式成立: fixed_usec(lost_usecoffset_usec)lost_usec(jiffieswall_jiffies)TICK_SIZE(ji

12、ffieswall_jiffies)(1000000HZ) 由于全局变量last_tsc_low表示上一次时钟中断服务函数timer_interrupt()执行时刻的CPU TSC寄存器的值,因此我们可以用X86 CPU的TSC寄存器来计算offset_usec的值。也即: offset_usec=delay_at_last_interrupt(current_tsc_lowlast_tsc_low)fast_gettimeoffset_quotient 其中,delay_at_last_interrupt是从上一次发生时钟中断到timer_interrupt()服务函数真正执行时刻之间的时间

13、延迟间隔。每一次timer_interrupt()被执行时都会计算这一间隔,并利用TSC的当前值更新last_tsc_low变量。假定current_tsc_low是do_gettimeofday()函数执行时刻TSC的当前值,全局变量fast_gettimeoffset_quotient则表示TSC寄存器每增加1所代表的时间间隔值,它是由time_init()函数所计算的。 2.3 Linux 信号signal处理机制信号signal机制是进程之间相互传递消息的一种方法,全称为软中断信号。系统调用signal用来设定某个信号的处理方法,其调用声明的格式如下: void (*signal(in

14、t signum, void (*handler)(int)(int); 成功则返回该信号以前的处理配置,出错则返回SIG_ERR。在使用该调用的进程中加入以下头文件: 几个常见信号: SIGINT: 当用户按某些终端键时, 引发终端产生的信号. 如Ctrl+C键, 这将产生中断信号(SIGINT),它将停止一个已失去控制的程序。 SIGSEGV: 由硬件异常(除数为0, 无效的内存引用等等)产生的信号。这些条件通常由硬件检测到, 并将其通知内核,然后内核为该条件发生时正在运行的进程产生该信号。 SIGALRM: 进程所设置的闹钟时钟超时的时候产生。 SIGVTALRM:虚拟时钟超时时产生该信

15、号。类似于SIGALRM,但是它只计算该进程占用的CPU时间。 SIGPROF:类似于SIGVTALRM,它不仅包括该进程占用的CPU时间还包括执行系统调用的时间。三、内核定时器机制的实现3.1动态定时器机制的初始化 函数init_timervecs()实现对动态定时器机制的初始化。该函数仅被sched_init()初始化例程所调用。动态定时器机制初始化过程的主要任务就是将tv1、tv2、tv5这5个结构变量中的定时器向量指针数组vec初始化为NULL。如下所示(kernel/timer.c): void init_timervecs (void) int i; for (i = 0; i TVN_SIZE; i+) INIT_LIST_HEAD(tv5.vec + i); INIT_LIST_HEAD(tv4.vec + i); INIT_LIST_HEAD(tv3.ve

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1