1.浅析linux 内核 高精度定时器(hrtimer)实现机制(二)
2.ARM cpu性能测试总结
3.UEFI开发探索15 – 图形模式下文字显示
4.Android音视频十二使用OpenSLES和AudioTrack进行播放PCM
5.已知8051单片机的系统fosc=12MHz,用T1 定时,试编程由P1.2 和P1.3 引脚分别输出周期为2ms 和500μs 的方波
6.Linux时间子系统之:时钟源
浅析linux 内核 高精度定时器(hrtimer)实现机制(二)
分析linux内核高精度定时器(hrtimer)的实现机制时,首先介绍的源码是定时器的迁移过程switch_hrtimer_base。该函数会尝试选择一个新的系统hrtimer_cpu_base结构体,用于定时器的源码激活。get_target_base函数被用于挑选新的系统迁移位置,这个函数的源码牛元帅的源码代码与分析低分辨率定时器层时的定时器迁移概念相似。timers_migration_enabled变量在切换到NO_HZ模式时变为True,系统退出NO_HZ模式时变为False,源码用于判断是系统否可以进行迁移。只有在切换到NO_HZ模式且定时器未绑定到特定CPU的源码情况下,才会进行迁移选择。系统get_nohz_timer_target函数会判断当前CPU是源码否处于空闲状态,如果不是系统,则返回当前CPU编号,源码如果是系统空闲,则会找到最近一个忙碌的处理器并返回其编号。所有条件不满足时,会直接返回传入的hrtimer_cpu_base结构体指针。
接下来分析hrtimer_callback_running函数,用于检查要迁移的定时器是否正是当前正在处理的定时器。hrtimer_check_target函数则用于检查定时器的到期时间是否早于要迁移到的CPU上即将到期的时间。如果高分辨率定时器的到期时间比目标CPU上的所有定时器到期时间还要早,并且目标CPU不是当前CPU,那么激活目标CPU会涉及到通知该CPU重新编程定时器,这通常不如直接在当前CPU上激活定时器来得简单。因此,如果迁移操作与实际激活操作没有关系,即使从get_target_base函数获得的base与定时器中指定的base相同,迁移操作也会进行。
在迁移过程中,内核会临时将定时器的源码负数算术移位hrtimer_clock_base结构体变量设置为全局变量migration_base的指针。这个全局变量仅用于在获得定时器所属CPU的hrtimer_cpu_base结构体变量时,通过判断base变量是否等于migration_base的指针来判断定时器是否正在迁移。这样的设计可以在未正式加锁之前过滤掉很多情况,从而提高速度。
文章福利提供Linux内核技术交流群,包含学习书籍、视频资料,前名可额外获得价值的内核资料包(含视频教程、电子书、实战项目及代码)。
内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料
学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂
在低精度模式下,高分辨率定时器层通过普通(低分辨率)定时器层驱动。当Tick到来时,其处理函数会调用hrtimer_run_queues函数通知高分辨率定时器层。每次调用该函数时,都会判断是否可以切换到高精度模式。如果可以切换,会调用hrtimer_switch_to_hres完成切换并退出。如果不需要切换,则从时间维护层获得当前时间和各种偏移值,并设置到所有的hrtimer_clock_base结构体中。如果当前时间不早于softirq_expires_next变量的值,表示“软”定时器已到期,需要激活软中断处理程序。在软中断处理程序中,首先调用hrtimer_update_base函数更新当前时间,并在适当时候执行,处理到期的“软”定时器。该处理程序会遍历所有指定类型(“软”或“硬”)的到期定时器,判断定时器的php阅读app源码“软”到期时间是否已到,处理到期定时器,并循环取下一个要到期的定时器。最后,会调用hrtimer_reprogram函数对底层定时事件设备进行重编程。
在高精度模式下,周期处理函数hrtimer_interrupt在定时事件设备到期后调用。处理过程包括激活HRTIMER_SOFTIRQ软中断处理程序,处理所有“软”定时器,并对底层定时事件设备进行重编程。重编程确保设备在到期后能正确触发中断,同时避免在一次中断中处理过多定时器,以防止超时。通过查找和设置到期时间时使用“硬”到期时间,而在处理定时器时使用“软”到期时间,内核能尽量减少中断调用,提高性能。
低精度模式切换到高精度模式的hrtimer_switch_to_hres函数通过调用tick_init_highres函数实现切换,将定时事件设备切换到单次触发模式,并设置中断处理函数为hrtimer_interrupt。一旦完成切换,底层定时事件设备将始终工作在单次触发模式。切换成功后,必须找到最近到期的定时器,并用其到期事件对定时事件设备进行重编程,确保设备能正确响应到期。
在高精度模式下,中断处理程序通过直接调用__hrtimer_run_queues函数处理所有“硬”定时器,并激活HRTIMER_SOFTIRQ软中断处理程序来处理所有“软”定时器。在高精度模式下,底层定时事件设备始终处于单次触发模式,云豹直播手机源码因此在到期后必须进行重编程。如果编程失败,重试三次后,适当延迟到期事件后再次尝试编程,并强制执行。
使用实例展示了高精度定时器在实际应用中的精度,时间戳显示其定时精度可达到ms级别。
ARM cpu性能测试总结
ARM CPU性能测试总结:
ARM处理器性能的评估通常通过两个关键工具:DMIPS(Dhrystone Million Instructions Per Second)和CoreMark。DMIPS是通过Dhrystone基准测试衡量系统每秒钟执行的Dhrystone指令数量,转化为DMIPS后便于比较。然而,DMIPS只是理论上的性能指标,实际应用性能还需考虑架构、缓存等因素。在Linux上,可通过下载Dhrystone源码并调整Makefile(如使用O3优化,设置HZ值)进行测试,最终结果以DMIPS/MHz表示。
CoreMark则是针对嵌入式应用的性能测试,它关注处理器在执行典型工作负载(如算术、内存操作等)时的迭代次数。CoreMark结果越高,表明处理器性能越好,同时还能提供功耗数据。在GitHub上获取源代码后,通过修改makefile编译并执行,结果以Iterations/Sec(每秒迭代次数)/MHz表示。
另外,Stream测试用于测量内存带宽,对CPU计算能力需求较小,巡风源码分析但对内存带宽压力大。Stream测试包含四个基本功能,如Copy、Scale等,通过修改makefile进行多线程测试,结果反映了内存带宽的性能。
UEFI开发探索 – 图形模式下文字显示
UEFI中利用HII(Human Interface Infrastructure)进行图形界面的文字显示,是一种处理方式。然而,作者之前在进行开发时,没有深入研究这一方法。在项目中,作者采用的是自定义方法,比如在测试样卡界面的实现中,英文和汉字的显示并非通过HII,而是通过Foxdisk中的显示方法,这方法简单直接,将汉字和英文字符看作一个个字模,使用画点函数进行绘制。
HII的使用方式可能不那么直观,作者在面临时间紧迫的开发任务时,决定采用Foxdisk中的显示方法,因为这方法可以快速实现所需功能。对于汉字和英文字符的显示,作者使用了8×像素的英文字符,直接拷贝到程序中编译,而对于汉字,作者编写了一个工具程序来提取字模,这个工具程序只能在位dos下运行,通常在位winxp的cmd环境中使用,理论上在win7 位环境也应该可以运行,因为它主要处理文件内容,并未涉及硬件相关代码,使用Borland C++ 3.1编译。
为了适配不同操作系统和环境,作者近期考虑使用Python重写这些工具软件,以方便在位操作系统下直接运行。尽管作者对这项目持开放态度,但是否会实际进行还未能确定。
作者使用的工具程序主要包括DistillHZ和DisTillLOGO。DistillHZ可以自动生成UEFI程序所需字符串的字模文件,并转换为UEFI程序可使用的格式,而DisTillLOGO则直接从Foxdisk的工具程序中拿来使用,但Logo的提取功能还需手动调整大小,并未完全考虑各种情况,如bmp文件的对齐问题等。
在显示汉字方面,作者采用与Foxdisk中相似的原理和方法,通过DistillHZ提取汉字字模和字符串,然后将字模文件复制到Font.c中,与Font.h中的数据结构和显示函数结合使用,以实现汉字的显示。对于Logo的显示,作者采用从色bmp图中提取像素点,然后逐点显示的简单方法。
最终,UEFI程序的显示效果良好,通过代码列表可以看到,其中的源代码名称与Foxdisk中的保持一致,汉字显示函数以及各种图形的显示函数与Foxdisk中的实现完全相同,因此,Foxdisk中的某些有趣效果,如渐隐和透明效果等,也可以直接应用于UEFI中。
Android音视频十二使用OpenSLES和AudioTrack进行播放PCM
Android中播放PCM数据的两种方法:AudioTrack和OpenSLES。AudioTrack适用于本地播放pcm文件或解码音频流,API简单,适用于场景较为固定;OpenSLES则常用于音频/视频播放器,利用c层直接调用API,减少java-jni反射开销,功能更强大,适合动态处理和复杂播放场景。 AudioTrack的步骤包括:指定采样率(如Hz),声道数(单/双声道)和采样位数(/8位)创建AudioTrack。若数据参数变化,需销毁重建。write方法用于写入pcm数据,同步操作,需在播放前调用play()。播放进度管理需自行处理。 OpenSLES则需先链接系统so库,创建引擎和混音器。配置音频信息后,创建播放器,设置状态,通过回调函数不断注入音频数据。音量和声道控制通过相应的接口实现,提供了更精细的控制选项。完整的源码可以在这里查看。已知单片机的fosc=MHz,用T1 定时,试编程由P1.2 和P1.3 引脚分别输出周期为2ms 和μs 的方波
代码如下:第一个代码程序:
ORG H
LJMP MAIN
ORG BH
JMP T1_INT
ORG H
MAIN:
MOV TMOD, #H
MOV TH1, #6
MOV TL1, #6
MOV IE, #H
SETB TR1
MOV R7, #4
SJMP $
T1_INT:
CPL P1.3
DJNZ R7, T1_END
CPL P1.2
MOV R7, #4
T1_END:
RETI
END
第二个us程序:
#include <reg.h>
sbit P1_0=P1^0;
void main()
{
TMOD=0x;
TH0=0xFC;
TL0=0x;
EA=1;
ET0=1;
TR0=1;
while(1);
}
void time0_int(void) interrupt 1
{
TH0=0xFC;
TL0=0x;
P1_0=!P1_0;
}
扩展资料:
程序存储器特定入口:
H: 复位或开机后的程序入口
H: 外部中断0 服务程序入口
BH: 定时/计数器0 中断服务程序入口
H: 外部中断1 服务程序入口
BH: 定时/计数器1 中断服务程序入口
H: 串行I/O 中断服务程序入口
定时/计数器
片内有两个位定时/计数器(增量式计数)
工作方式(方式0、方式1、方式2、方式3)
以定时/计数器1为例
⑴方式0(位定时/计数)
方波是一种非正弦曲线的波形,通常会于电子和讯号处理时出现。理想方波只有“高”和“低”这两个值。电流的波形为矩形的电流即为方波电流。不论时间轴上下是不是对称的,只要是矩形就可叫方波,必要时,可加“对称”,“不对称”加以说明
通过单片机内部的计数器/定时器,采用软件编程来产生方波,这种方法的硬件线路较简单,系统的功能一般与软件设计相关。
选择MCS-系列中的单片机,由于是用指示灯显示输出方波信号,一个LED显示灯即可满足设计要求。
方波是一种非正弦曲线的波形,通常会与电子和讯号处理时出现。理想方波只有“高”和“低”这两个值。电流或电压的波形为矩形的信号即为矩形波信号,高电平在一个波形周期内占有的时间比值称为占空比,也可理解为电路释放能量的有效释放时间与总释放时间的比值。
占空比为%的矩形波称之为方波,方波有低电平为零与为负之分。必要时,可加以说明“低电平为零”、“低电平为负”。
Linux时间子系统之:时钟源
探索Linux内核的时间奥秘:时钟源的精密构建在Linux内核的精密世界里,时钟源扮演着时间基准的角色,它像一台隐形的精确计时器,通过硬件计数器确保我们与时间的精准同步。struct clocksource是这个系统的核心结构,其中的关键组件,如rating(精度,范围1-,数值越高,时间精度越优)、read回调,以及mult和shift,共同构建了这个时间测量的基石。rating值在1-范围内用于特殊用途,而-区间则为常规选择,read函数则是时间计数的窗口,mult和shift则是处理计数与频率F之间转换的魔力公式,内核采用位精度进行计算。
为了确保时间更新的稳定性和准确性,clocksource_register_hz在初始化时,通过一系列复杂的计算,确定了mult、shift的值,并为最大闲置时间设定了限制。同时,clocksource_register_scale负责性能排序和监控,而watchdog就像一个警惕的眼睛,一旦发现性能偏差超出阈值,就会标记该时钟源为不稳定状态。 在Linux启动的早期阶段,系统首先注册基于jiffies的clocksource,尽管其评级较低,但这正是基础中的基础。想要深入了解这个时钟源体系的更多细节,你可以在Linux内核源码分析学习群中发现丰富的资源。 深入理解clocksource的运作机制- clocksource_jiffies结构体,其设计为每个时钟周期提供1/HZ秒的精度,评级为1,是默认选择,除非有特定需求,否则系统会采用这个基础时钟源。
- init_jiffies_clocksource函数是初始化和注册这个时钟源的关键步骤,它确保了clocksource_jiffies的顺利启动。
- clocksource_default_clock提供了一种可选的默认时钟源,通常设置为clocksource_jiffies,但在特定场景下,可以被自定义以适应特定需求。
- clocksource_done_booting则在系统启动的后期,根据系统的实际情况,选择最合适的clocksource,并通知timekeeping系统进行适时的时间更新,确保系统时间的精准与一致性。
在这个看似简洁的时间管理背后,Linux内核的时钟源系统蕴含着精细的逻辑与优化,每个组件都在默默地守护着系统的稳定和准确性。深入理解这些细节,对于任何想要驾驭Linux内核的开发者来说,无疑是一把打开时间秘密的钥匙。