linux内核源代码分析-定时器与时间管理
Linux下的时钟中断和相关时间应用
延迟执行
– 忙等待 – 短延迟
Linux内存页
内核中内存的分配要复杂的多 内核以物理页为单位分配内存 物理页的大小取决于体系结构,一般
– 4kB – 8kB
Linux内存页
数据结构:<linux/mm.h>中定义: Struct page { unsigned long flags; Atomic_t count; Struct list_head list; Struct address_space *mapping; Unsigned long index; Struct list_head lru; Union { struct pte_chain *chain; pte_addr_t direct;} pte Unsigned long private; Void *virtual;}
内存管理提供的服务
获得页
– – – – – Alloc_pages() Page_address(struct page *page) __get_free_pages() alloc_page() __get_free_page()
内存管理提供的服务
获得填充为0的页
– Get_zeroed_page()
内核中的时间概念
事件驱动与时间驱动 内核中需管理相对时间和绝对时间 内核时间的硬件基础(系统定时器以某种频率触发, hitting or poping,该频率可以通过编程预定(tick rate) poping, tick rate 直接用处:
– – – – – 更新系统运行时间 更新实际时间 定期均衡运行队列(SMP上) 时间片 定期统计
Linux下的时钟中断和相关时间应用
时钟中断处理程序做的工作:
– 获得xtime_lock锁,对jiffies_64和xtime进行保护(为什么jiffies 不用保护) – 应答或重新设置系统时钟 – 周期性地使用墙上时间更新实时时钟 – 调用体系结构无关的时钟例程:do_timer():
Jiffies_64变量加1 更新资源消耗的统计值 执行到期的动态定时器 执行sheduler_tick()函数 更新墙上时间并存到xtime变量中 计算平均负载值
释放页
– __free_pages – Free_pages – Free_page
内存管理提供的服务 Kmalloc Kfree Vmalloc vfree
内存管理提供的服务 Slab层
– 一种缓存机制(P143-P148)
Linux下的时钟中断和相关时间应用
实际时间
– – – – – 定义在<linux/time.h>中,形式如下: Struct timespec{ Time_t tv_sec; Long tv_nsec; }
Linux下的时钟中断和相关时间应用
实际时间的更新和读取都需要锁。
– Write_seqlock(&xtime_lock); – /* 更新xtime…*/ – Write_sequnlock(&xtime_lock); – Read_seqbegin() , read_seqretry();(P125)
– #define jiffies_to_clock(x) ((x)/(HZ/USER_HZ)) – 否则,需要向时间上做一下转换,误差会小一些。 思考一下,为什么?
硬件时钟和定时器
体系结构提供了两种设备计时
– 系统定时器 – 实时时钟(RTC),不开机时靠电池供电工作,系统启动时, 初始化xtime变量。 xtime
其他几个函数
– Mod_timer() – Del_timer()
Linux下的时钟中断和相关时间应用
定时器竞争条件 定时器的实现
– 在时钟中断处理程序的下半部执行:update_process_timers()函 数,该函数调用run_local_timers() { raise_softirq(TIMER_SOFTIRQ); }Linux下的时钟中断和 Nhomakorabea关时间应用
从用户空间获取时间的调用为
– Gettimeofday() 内核中对应的系统调用为:sys_gettimeofday() P125
Linux下的时钟中断和相关时间应用
动态定时器
– 一些工作要在后面一个相当的时间执行,这就需要定时器的 控制,定时器有时也称内核定时器 – 使用定时器 定时器由timer_list表示,定义在<linux/timer.h>中。 具体结构见:P126
– 溢出时间问题 – 64位问题(2.6中)
Linux中时间表示(jiffies)
64位与32位的结合 Jiffies的回绕 unsigned long timeout = jiffies + HZ/2; /*执行一些任务….*/ if (timeout <jiffies) { 未超时,正常处理} else { 超时,错误处理; }
定时器与时间管理、内存管理
内核中的时间概念 Linux中时间表示 硬件时钟和定时器 Linux下的时钟中断和相关时间应用 Linux内存页 Linux内存区 内存管理提供的服务 内存管理缓存机制 内存映射
上次内容回顾 系统调用和中断(回顾上节课内容) 中断处理程序的上、下半部机制 LINUX下半部处理机制 同步的经典问题 LINUX内核同步实现
Linux中时间表示(HZ)
节拍率(HZ)
– 系统定时器频率,可以通过设置修改,系统启动时设置,不 同体系结构下不同。 如:在include/asm-i386/param.h中: #define Hz 1000 //相当于1秒中断1000次 思考:时间的精确性 – 书上P116表9-1给出一般情况下各种体系结构下的时钟中断频 率 – 理想的HZ值应该是多少?
Void update_process_times(int user_tick) { Struct task_struct *p = current; Int cpu = smp_processor_id() Int system = user_tick ^1; … }(见书上P123)
Linux下的时钟中断和相关时间应用
Linux内存区
由于硬件的限制,内核并不能对所有的页一样看待。 这样内核需要对页进行分类,分不同的区域。
– 一些硬件只能允许某些特定的内存地址来执行DMA. – 一些体系结构其内存的物理地址范围比虚拟寻址范围大得多。 这样有一些内存就不能总是映射到内核空间上。 Linux对应有三个区 ZONE_DMA ZONE_NORMAL ZONE_HIGHMEM (P135)
全局变量,用来记录系统启动以来产生的节拍总数 在<linux/jiffies.h>中定义: Extern unsigned long volatile jiffies;响应地有: Seconds* HZ = jiffies; (jiffies/HZ) = seconds;(还有一些其他的转换) 有关jiffies的内部位数问题:
Linux中时间表示(jiffies)
回绕的处理: time_after Time_before Time_after_eq Time_before_eq 分析怎样避免的回绕影响(借用了LONG的符号)
Linux中时间表示(用户空间和HZ)
内核改变HZ的值会影响一些基于原来值的应用 内核需要导出合适的jeffies值 若新旧HZ数差整数倍则比较简单
统计的不精确性 根据上面的处理可以看出,一个节拍的时间要么给一 个用户进程,要么给系统,这样做很不精确,因为在 一个节拍中进程可能多次进入。这也是要采取更高频 率的原因。
Linux下的时钟中断和相关时间应用
更新墙上时钟 Void update_times(void) { unsigned long ticks; ticks = jiffies – wall_jiffies; if (ticks) { wall_jiffies += ticks; update_wall_time(ticks); last_time_offset = 0; calc_load(ticks); }
定义:struct timer_list my_timer; 初始化:init_timer(&my_timer); 填充结构中需要的值:my_timer.expires =…
my_timer.function = myfunction;
激活定时器:add_timer(&my_timer);
Linux下的时钟中断和相关时间应用
Linux下的时钟中断和相关时间应用
Do_timer() void do_timer(struct pt_regs *regs) { jiffies_64++; update_process_times(user_mode(regs)); update_times(); }
Linux下的时钟中断和相关时间应用
多时会产生中断频繁 但提高精度(分析:平均误差)
Linux中时间表示(HZ)
精度提高的进一步讨论
– – – – 一些关键系统调用的效率提高(poll(),select()) 进程抢占的精度提高 时间测量方面精度提高 中断次数增加带来的问题
综合考虑认为目前体系结构的系统设为1000可以忍受。
Linux中时间表示(jiffies)
Linux定时器的使用
Linux定时器的使⽤使⽤定时器的⽬的⽆⾮是为了周期性的执⾏某⼀任务,或者是到了⼀个指定时间去执⾏某⼀个任务。
要达到这⼀⽬的,⼀般有两个常见的⽐较有效的⽅法。
⼀个是⽤linux内部的三个定时器,另⼀个是⽤sleep, usleep函数让进程睡眠⼀段时间,使⽤alarm定时发出⼀个信号,还有那就是⽤gettimeofday, difftime等⾃⼰来计算时间间隔,然后时间到了就执⾏某⼀任务,但是这种⽅法效率低,所以不常⽤。
alarmalarm⽤在不需要经确定时的时候,返回之前剩余的秒数。
NAMEalarm - set an alarm clock for delivery of a signalSYNOPSIS#include <unistd.h>unsigned int alarm(unsigned int seconds);DESCRIPTIONalarm arranges for a SIGALRM signal to be delivered to the process inseconds seconds.If seconds is zero, no new alarm is scheduled.In any event any previously set alarm is cancelled.测试程序:1 cat timer.c2 #include <stdio.h>3 #include <unistd.h>4 #include <sys/time.h>5 #include <signal.h>67 void func()8 {9 printf("2 s reached.\n");10 }1112 int main()13 {14 signal(SIGALRM,func);15 alarm(2);16 while(1);17 return 0;18 }19Linux内置的3个定时器Linux为每个任务安排了3个内部定时器:ITIMER_REAL:实时定时器,不管进程在何种模式下运⾏(甚⾄在进程被挂起时),它总在计数。
linux定时器详解
查看文章Linux 定时器设置(一)2010-04-12 17:07定时器设置函数alarm设置的定时器只能精确到秒,而以下函数理论上可以精确到微妙:#include <sys/select.h>#include <sys/time.h>int getitimer(int which, struct itimerval *value);int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);函数setitimer可以提供三种定时器,它们相互独立,任意一个定时完成都将发送定时信号到进程,并且自动重新计时。
参数which确定了定时器的类型,如表10-6所示:表10-6 参数which与定时器类型取值含义信号发送ITIMER_REAL 定时真实时间,与alarm类型相同。
SIGALRM ITIMER_VIRT 定时进程在用户态下的实际执行时间。
SIGVTALRM ITIMER_PROF 定时进程在用户态和核心态下的实际执行时间。
SIGPROF 这三种定时器定时完成时给进程发送的信号各不相同,其中ITIMER_REAL类定时器发送SIGALRM信号,ITIMER_VIRT类定时器发送SIGVTALRM信号,ITIMER_REAL类定时器发送SIGPROF信号。
函数alarm本质上设置的是低精确、非重载的ITIMER_REAL类定时器,它只能精确到秒,并且每次设置只能产生一次定时。
函数setitimer设置的定时器则不同,它们不但可以计时到微妙(理论上),还能自动循环定时。
在一个Unix进程中,不能同时使用alarm和ITIMER_REAL类定时器。
结构itimerval描述了定时器的组成:struct itimerval { struct tim. it_interval; /* 下次定时取值*/ struct tim. it_value; /* 本次定时设置值*/} 结构tim.描述了一个精确到微妙的时间:struct tim. { long tv_sec; /* 秒(1000000微秒)*/ long tv_usec; /* 微妙*/}函数setitimer设置一个定时器,参数value指向一个itimerval结构,该结构决定了设置的定时器信息,结构成员it_value指定首次定时的时间,结构成员it_interval指定下次定时的时间。
5.2-Linux定时器
广州致远电子有限公司
MagicARM2410教学实验开发平台
6.实验步骤
(4)输入make命令,对程序进行编译,编译完毕在当前目录下 输入make命令,对程序进行编译, 命令 会生成可执行文件timer. 会生成可执行文件timer. $ make (5)启动ARM Linux,进行NFS连接,进入/mnt/timer目录,执 启动ARM Linux,进行NFS连接, 连接 目录, 行timer程序. timer程序. 程序 # ./timer
广州致远电子有限公司
MagicARM2410教学实验开发平台
3.实验内容
使用Linux定时器进行定时 使用Linux定时器进行定时,定时值到后发出 定时器进行定时, 提示信息. 提示信息.
广州致远电子有限公司
MagicARM2410教学实验开发平台
4.实验预习要求
熟悉Makefile文件编写; 熟悉Makefile文件编写; 文件编写 熟悉NFS方式调试 方式调试Linux应用程序 应用程序; 熟悉NFS方式调试Linux应用程序; 熟悉Linux定时器 熟悉Linux定时器. 定时器.
广州致远电子有限公司
MagicARM2410教学实验开发平台
5.实验原理
Linux为每个任务安排了3个内部定时器: ITIMER_REAL:实时定时器,不管进程在何 种模式下运行(甚至在进程被挂起时),它总 在计数.定时到达,向进程发送SIGALRM信号. ITIMER_VIRTUAL:这个不是实时定时器, 当进程在用户模式(即程序执行时)计算进程 执行的时间.定时到达后向该进程发送 SIGVTALRM信号.
MagicARM2410教学实验开发平台
2.实验设备
硬件: 硬件: PC机 PC机 1台 MagicARM2410教学实验开发平台 MagicARM2410教学实验开发平台 1台 软件: 软件: RedHat Linux 9.0操作系统 9.0操作系统 嵌入式Linux开发环境 嵌入式Linux开发环境
第12讲 Linux内核定时器实验_笔记
一、Linux内核定时器原理
1.1、内核时间管理
1、Cortex-M内核使用systick作为系统定时器。
2、硬件定时器、软件定时器,原理是依靠系统定时器来驱动。
3、linux内核频率可以配置,图形化界面配置。
4、重点,HZ表示系统节拍率,
jiffies,
1.2、节拍率高低的缺陷
1.3、jiffies
1.4、内核定时器
1、软件定时器不像硬件定时器一样,直接给周期值。
设置期满以后的时间点。
2、定时处理函数。
3、内核定时器不是周期性的,一次定时时间到了以后就会关闭,除非重新打开。
二、编写试验驱动
1、定义一个定时器,结构体timer_list
2、应用ioctl函数-》unlocked_ioctl和compat_ioctl。
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long)
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
ioctl的命令是自己定义的,但是要符合linux规则。
构建命令:#define _IO(type,nr) /没有参数的命令
#define _IOR(type,nr,size) //该命令是从驱动读取数据
#define _IOW(type,nr,size) //该命令是向驱动写入数据
#define _IOWR(type,nr,size) //双向数据传输
type是幻数,nr是序号,size是大小。
三、测试。
linux timer用法
linuxtimer用法Linux操作系统提供了丰富的定时器功能,通过使用Linux定时器,可以轻松地实现定时任务、周期性执行的操作等。
本文将介绍Linux定时器的用法,包括定时器的类型、创建、使用和销毁等。
一、定时器类型Linux定时器可以分为以下几种类型:1.软定时器:软定时器是一种基于时间的定时器,可以通过系统调用实现定时任务。
软定时器的时间单位可以是秒、毫秒、微秒等,可以根据实际需求选择合适的单位。
2.硬定时器:硬定时器是一种基于内核定时器的定时器,可以通过内核提供的定时器接口实现周期性执行的操作。
硬定时器的精度较高,可以根据实际需求选择合适的精度。
二、创建定时器创建定时器可以通过系统调用来实现,具体方法如下:1.软定时器创建:可以使用`timer_create()`函数创建一个软定时器,该函数需要指定定时器的名称、指向定时器回调函数的指针、定时器的超时时间等信息。
创建成功后,会返回一个定时器的标识符,可以使用该标识符来控制定时器的执行。
2.硬定时器创建:可以使用`timer_create()`函数创建一个硬定时器,该函数需要指定定时器的名称、指向定时器回调函数的指针、定时器的起始时间等信息。
创建成功后,内核会根据指定的精度周期性地执行回调函数。
三、使用定时器创建了定时器后,需要使用该标识符来控制定时器的执行。
可以使用`timer_set_state()`函数来设置定时器的状态为运行或停止。
可以使用`timer_start()`函数来启动定时器,使定时器进入运行状态;可以使用`timer_try_stop()`函数来尝试停止当前运行的定时器。
需要注意的是,硬定时器不能被取消或延迟执行,只能被重新设置起始时间。
四、销毁定时器定时器执行完毕或不再需要时,需要销毁该定时器。
可以使用`timer_delete()`函数来销毁软定时器,使用`timer_delete(timerfd)`函数来销毁硬定时器。
linux定时器原理
linux定时器原理Linux定时器是Linux操作系统中的一种机制,用于实现在指定时间间隔内执行特定任务的功能。
本文将介绍Linux定时器的原理和工作方式。
一、概述在现代操作系统中,定时器是一项重要的功能。
它可以用于定时执行任务,例如周期性地刷新屏幕、定时发送网络数据包等。
Linux 内核提供了多种定时器机制,其中最常用的是基于时钟事件的定时器。
二、基于时钟事件的定时器Linux内核通过时钟事件来触发定时器的执行。
时钟事件是由硬件时钟产生的,它以固定的频率中断处理器的正常执行流程。
Linux 内核会注册一个中断处理函数来处理时钟事件,并在每次时钟中断时调用该函数。
三、内核定时器APILinux内核提供了一组函数和数据结构,用于管理定时器。
其中最重要的是`timer_create()`、`timer_settime()`和`timer_delete()`函数。
`timer_create()`函数用于创建一个新的定时器,`timer_settime()`函数用于设置定时器的参数和启动定时器,`timer_delete()`函数用于删除定时器。
四、定时器的创建和设置要创建一个定时器,首先需要定义一个`timer_t`类型的变量来存储定时器的ID。
然后使用`timer_create()`函数来创建定时器,并将定时器ID保存在该变量中。
接下来,可以使用`timer_settime()`函数来设置定时器的参数,如定时器的初始时间和间隔时间。
五、定时器的工作原理当定时器被设置并启动后,内核会在每次时钟中断时检查定时器是否到期。
如果定时器到期,则会触发定时器的回调函数。
定时器的回调函数是在内核上下文中执行的,因此需要注意避免使用可能会导致死锁或竞争条件的操作。
六、定时器的删除当不再需要定时器时,可以使用`timer_delete()`函数来删除定时器。
删除定时器后,内核会停止触发定时器的回调函数。
七、定时器的应用Linux定时器在很多场景下都有广泛的应用。
linux中定时器的工作原理
linux中定时器的工作原理
在Linux中,定时器的工作原理通常是通过使用内核提供的计
时器机制来实现的,主要有以下几个步骤:
1. 用户程序通过系统调用(如`timer_create`)创建一个定时器,并设置定时器的触发时间和触发方式等参数。
2. 内核会为每个定时器分配一个数据结构,用于保存定时器的相关信息,如触发时间、触发方式等。
3. 内核会根据定时器的触发时间和触发方式,使用计时器设备(如计时器中断)来按照一定的频率进行计时,并在达到定时器触发时间时产生中断。
4. 当计时器中断发生时,内核会检查当前时间是否与某个定时器的触发时间相匹配,如果匹配则触发定时器的回调函数。
5. 定时器的回调函数会在内核态下执行,可以执行用户指定的操作,如发送信号、唤醒进程或执行特定的任务等。
需要注意的是,不同的定时器实现方式可能有所差异,上述描述是一种通用的工作原理。
此外,Linux中还提供了多种定时
器实现方式,包括基于硬件的实时时钟(RTC)、周期性定时器(`setitimer`)、高精度计时器(`hrtimer`)等,用户可以根
据具体的需求选择合适的定时器类型。
linux_gmtime_源代码简析_概述及解释说明
linux gmtime 源代码简析概述及解释说明1. 引言1.1 概述本文将详细解析和说明Linux操作系统中的gmtime函数的源代码。
gmtime 是一个十分重要的时间处理函数,在Linux系统中被广泛应用于时间管理和日期处理领域。
通过深入研究gmtime函数的源代码,我们可以更好地理解其原理和功能,从而能够更有效地使用这一函数。
1.2 文章结构本文共分为五个部分来展开对gmtime函数的源代码简析。
首先,引言部分对本文进行了概述,介绍了文章目录和主要内容。
接下来,第二部分将介绍gmtime 函数的基本概念和功能,并深入解读其源代码。
第三部分则探讨了时间处理在Linux系统中的重要性,以及gmtime在时间处理中的具体应用场景。
第四部分将对gmtime函数的源代码进行详尽分析与解释,并分享常见问题的解决方案。
最后,在第五部分中我们将总结已掌握的知识点并思考收获,并展望如何优化和扩展gmtime源代码。
1.3 目的本文旨在帮助读者全面理解并掌握Linux操作系统中gmtime函数的工作原理和应用场景。
通过详细剖析其源代码,并提供使用示例和常见问题解答,读者将能够更加熟练地运用gmtime函数进行时间处理和日期管理。
此外,本文还希望为读者提供关于gmtime源代码优化和扩展的展望,并激发读者对Linux操作系统中时间处理相关领域的兴趣。
2. gmtime函数简介:2.1 gmtime概述:gmtime函数是一个时间处理函数,它被用来将给定的时间戳(秒数)转换为一个结构体,该结构体包含了年、月、日、时、分、秒等具体的时间信息。
它返回的结构体是一个tm类型的对象,tm类型定义在<time.h>头文件中。
2.2 gmtime源代码解读:gmtime函数的源代码位于GNU C库的源码中,这个库提供了很多标准C库的实现,包括时间处理相关的函数。
通过查阅GNU C库的源码可以对gmtime函数进行详细解读。
Linux内核分析
深入分析Linux内核源码第一章走进linux走进Linux内核分析Linux内核的意义Linux内核结构Linux内核源代码Linux内核源代码分析工具第二章Linux运行的硬件基础段机制和描述符Linux中的汇编语言第三章中断机制中断基本知识中断描述符表的初始化中断处理中断的后半部分处理机制第四章进程描述task_struct结构在内存中的存放进程组织的方式内核同步第五章进程调度时钟中断Linux的调度程序-Schedule( )进程切换第六章Linux内存管理Linux内存管理的初始化请页机制交换机制缓存和刷新机制进程的创建和执行第七章进程间通信第八章虚拟文件系统高速缓存文件系统的注册、安装与拆卸文件系统的系统调用第九章Ext2文件系统Ext2的磁盘布局和数据结构第十章模块机制概述实现机制模块的装入和卸载内核版本编写内核模块第十一章设备驱动程序设备驱动基础块设备驱动程序字符设备驱动程序第十二章网络网络协议套接字(socket)套接字缓冲区(sk_buff)网络设备接口第十三章启动系统初始化的任务Linux 的Boot Loarder进入操作系统建立init进程附录:1 Linux 内核API前言Linux内核全部源代码是一个庞大的世界,大约有200多万行,占60MB左右的空间。
因此,如何在这庞大而复杂的世界中抓住主要内容,如何找到进入Linux内部的突破口,又如何能把Linux的源代码变为自己的需要,这就是本书要探讨的内容。
首先,本书的第一章领你走入Linux的大门,让你对Linux内核的结构有一个整体的了解。
然后,第二章介绍了分析Linux源代码应具备的基本硬件知识,这是继续向Linux 内核迈进的必备条件。
中断作为操作系统中发生最频繁的一个活动,本书用一章的内容详细描述了中断在操作系统中的具体实现机制。
大家知道,操作系统中最核心的内容就是进程管理、内存管理和文件管理。
本书用大量的篇幅描述了这三部分内容,尤其对最复杂的虚拟内存管理进行了详细的分析,其中对内存初始化部分的详细描述将对嵌入式系统的开发者有所帮助。
linux timerfd定时触发原理
linux timerfd定时触发原理Linux timerfd是Linux内核提供的一种定时器机制,可以实现定时触发的功能。
它是通过文件描述符的方式来操作定时器的,可以方便地与其他I/O事件一起使用。
Linux timerfd的原理是基于内核的定时器子系统。
在内核中,有一个全局的定时器链表,用来管理所有的定时器。
当一个定时器到达指定的时间后,内核会将它加入到已过期的定时器链表中,并唤醒等待该定时器的进程。
timerfd会通过读取文件描述符来获取定时器到期的事件。
使用timerfd需要以下几个步骤:1. 创建timerfd:使用timerfd_create系统调用来创建一个timerfd文件描述符。
timerfd_create函数会返回一个新的文件描述符,用来操作定时器。
2. 设置定时器参数:使用timerfd_settime系统调用来设置定时器的参数,包括定时器的起始时间和间隔时间。
timerfd_settime函数会更新定时器的属性。
3. 等待定时器到期:使用select、poll或epoll等I/O复用函数来等待timerfd文件描述符上的可读事件。
当定时器到期时,timerfd 文件描述符会变为可读,我们就可以读取该文件描述符来获取定时器到期的事件。
4. 处理定时器事件:当timerfd文件描述符可读时,我们可以读取该文件描述符的内容来获取定时器到期的次数。
根据需要进行相应的处理,比如执行某个函数或执行某个操作。
timerfd的优点是精度高、可靠性强。
它可以实现毫秒级别的定时触发,对于需要高精度定时的场景非常适用。
而且,timerfd可以与其他I/O事件一起使用,可以方便地集成到事件驱动的程序中。
总结一下,Linux timerfd是Linux内核提供的一种定时器机制,通过文件描述符的方式来操作定时器,可以实现定时触发的功能。
它的原理是基于内核的定时器子系统,通过定时器链表和文件描述符的读写来实现定时器的触发和处理。
