Linux内核开发之中断与时钟(三)

OS实验2-2 课后作业2.1 外部中断 阅读详情

  晚上7点10分..

“小涛哥,这章不是叫Linux设备驱动程序之中断与时钟,前边你讲了中断,还给了我很多模版,我都看懂了,这次是不是要开始讲时钟了..”

“真聪明,越来越喜欢你这聪明的样子了,说的不错,今天就要开始一个新的模块--内核时钟”我很少夸人,为啥今天夸她呢了,呵呵.

  定时器,意思大家都明白,我就不说了,要是不明白,把它想成个闹钟总可以吧..

  定时器分为硬件和软件定时器,软件定时器最终还是要依靠硬件定时器来完成。内核在时钟中断发生后检测各定时器是否到期,到期后的定时器处理函数将作为软中断在底半部执行。实质上,时钟中断处理程序执行update_process_timers函数,该函数调用run_local_timers函数,这个函数处理TIMER_SOFTIRQ软中断,运行当前处理上到期的所有定时器。

Linux内核中定义提供了一些用于操作定时器的数据结构和函数如下:

1)timer_list:说定时器,当然要来个定时器的结构体

  struct timer_list{
     struct list_head entry;  //定时器列表
      unsigned long expires;  //定时器到期时间
      void (*function)(unsigned long) ;//定时器处理函数
      unsigned long data;   //作为参数被传入定时器处理函数
      struct timer_base_s *base;
}
2)初始化定时器:void init_timer(struct timer_list *timer);经过这个初始化后,entry的next为NULL,并给base赋值
3)增加定时器:void add_timer(struct timer_list *timer); 该函数用于注册内核定时器,并将定时器加入到内核动态定时器链表中。
4)删除定时器:int del_timer(struct timer_list *timer);
  说明:del_timer_sync是del_timer的同步版,主要在多处理器系统中使用,如果编译内核时不支持SMP,del_timer_sync和del_timer等价.
5)修改定时器:int mod_timer(struct timer_list *timer, unsigned long expires);
下边是一个使用定时器的模版:
struct xxx_dev  /*second设备结构体*/ 
{
  struct cdev cdev; /*cdev结构体*/
  ...
  struct timer_list xxx_timer; /*设备要使用的定时器*/
};
int xxx_func1(...)  //xxx驱动中某函数 
{
  struct xxx_dev *dev = filp->private_data;
    ...
  /*初始化定时器*/
  init_timer(&dev->xxx_timer);
  dev->xxx_timer.function = &xxx_do_handle;
  dev->xxx_timer.data = (unsigned long)dev;
  dev->xxx_timer.expires = jiffies + delay;
  
  add_timer(&dev->xxx_timer); /*添加(注册)定时器*/
  ...
  return 0;
}
int xxx_func2(...)   //驱动中某函数 
{
  ...
  del_timer(&second_devp->s_timer);
  ...
}
static void xxx_do_timer(unsigned long arg)  //定时器处理函数 
{
  struct xxx_device *dev = (struct xxx_device *)(arg);
    ...
    //调度定时器再执行
  dev->xxx_timer.expires = jiffies + delay;
  add_timer(&dev->xxx_timer);
}

在定时器函数中往往会在做完具体工作后,延迟expires并将定时器再次添加到内核定时器链表中,以便定时器能被再次触发(这句话我也是从别处抄来的,别告诉小王哈)。

在内核定时器中,常常少不了要说下内核延迟的事,请接着往下看:

1)短延迟:在linux内核中提供了三个函数来分别实现纳秒,微秒,毫秒延迟,原理上是忙等待,它根据CPU频率进行一定次数的循环

void ndelay(unsigned long nsecs);                   void udelay(unsigned long usecs);                 void mdelay(unsigned long msecs);

毫秒延迟已经相当大了,当然更秒延迟当然要小一些,在内核中,为了性能,最好不要用mdelay,这会耗费大量cpu资源,那么咋办呢,凉拌..

void msleep(unsigned int millisecs);   unsigned long msleep_interruptible(unsigned int millisecs);   void ssleep(unsigned int seconds);

这三个是内核专门提供该我们用来处理毫秒以上的延迟。上述函数将使得调用它的进程睡眠参数指定的秒数,其中第二个是可以被打断的,其余的两个是不可以的。

2)长延迟:内核中进行延迟最常用的方法就是比较当前的jiffies和目标jiffies(当前的加上时间间隔的jiffies),直到未来的jiffies达到目标jiffies。比如:

unsigned long delay = jiffies + 100;  //延迟100个jiffies
while(time_before(jiffies, delay));

与time_before对应的还有一个time_after().其实就是#define time_before(a,b)  time_after(b,a);

另外两个是time_after_eq(a,b)和time_before_eq(a,b)

3)睡着延迟:这显然是比忙等待好的方法,因为在未到来之前,进程会处于睡眠状态,把CPU空出来,让CPU可以做别的事情,等时间到了,调用schedule_timeout()就可以唤醒它并重新调度执行。msleep和msleep_interruptible本质上都是依靠包含了schedule_timeout的schedule_timeout_uninterruptible()和schedule_

timeout_interruptible()实现。就像下边这样:

void msleep(unsigned int msecs)   
{
    unsigned long timeout = msecs_to_jiffies(msecs) + 1;
    while(timeout)
         timeout = schedule_timeout_uninterruptible(timeout);
}
unsigned long msleep_interruptible(unsigned int msecs)
{
    unsigned long timeout = msecs_to_jiffies(msecs) + 1;
    while(timeout && !signal_pending(current))
         timeout = schedule_timeout_interruptible(timeout);
    return jiffies_to_msecs(timeout);
}
signed long __sched schedule_timeout_interruptible()signed long timeout)
{
    __set_current_state(TASK_INTERRUPTIBLE);
    return schedule_timeout(timeout);
}
signed long __sched schedule_timeout_uninterruptible()signed long timeout)
{
    __set_current_state(TASK_UNINTERRUPTIBLE);
    return schedule_timeout(timeout);
}
另外还有如下:
time_on_timeout(wait_queue_head_t *q, unsigned long  timeout);
interruptible_sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout);
这两个将当前进程添加到等待队列,从而在等待队列上睡眠,当超时发生时,进程将被唤醒。
 
“小王,有关中断和系统时钟的咱们也讲完了,下次就给你来一个有关系统时钟的设备驱动例子,巩固一下吧,你可要抓紧哦..“
时钟中断(1) 在所有外部中断中,时钟中断起着特殊的作用。因为计算机是以精确的时间进行数值运算的数据处理的,最基本的时间单元是时钟周期,例如取指令,执行指令,存取内存等,我们将要讨论的是操作系统建立的时间系统,这个时间系统是整个操作系统活动的动力。 阅读详情

相关推荐

Linux 时钟中断详解

在Linux的0号中断是一个定时器中断。在固定的时间间隔都发生一次中断,也是说每秒发生该中断的频率都是固定的。该频率是常量HZ,该值一般是在100 ~ 1000之间。该中断的作用是为了定时更新系统日期和时间,使系统时间不断地得到跳转。另外该中断的中断处理函数除了更新系统时间外,还需要更新本地CPU统计数。指的是调用scheduler_tick递减进程的时间片,若进程的时间片递减到0,进程则被调度出去而放弃CPU使用权。 时钟中断的产生 Linux的OS时钟的物理产生原因是可编程定时/计数器产生的输出脉冲,这

C/C++Linux、音视频、DPDK 4462

课堂练习2.1:外部中断

【代码】课堂练习2.1:外部中断。 1. 时钟中断的发生 2. 第一次时钟中断 第3关:第六次时钟中断 修改版本 1 内核源码,使得每次时钟中断发生时,都在屏幕上输出字符 ‘t’

qq_52331221的博客 2万+

Linux之时钟中断

from:深入分析Linux内核源码(http://oss.org.cn/kernel-book/)  时钟中断的产生      Linux的OS时钟的物理产生原因是可编程定时/计数器产生的输出脉冲,这个脉冲送入CPU,就可以引发一个中断请求信号,我们就把它叫做时钟中断。 “时钟中断”是特别重要的一个中断,因为整个操作系统的活动都受到它的激励。系统利用时钟中断维持系统时间、促使环境的切换,以

Atlas2013的专栏 1万+

2021-07-05 操作系统实操相关知识点笔记--中断、异常的响应和处理

以下实验内容来自educoder,通过实验获得更具体的认知 实验1 通过相关知识回答下列问题: 1.在函数 main 的语句jiffies = jiffies/0;所对应的汇编指令片段中,有一个 idiv 指令,此指令的地址是多少? 2.在该 idiv 指令执行之前,当前指令位置(CS:EIP)和栈位置(SS:ESP)分别是多少? 3.使用 si 命令执行了该指令后,新指令位置和栈位置分别是多少?此时栈中保存的恢复点位置和用户栈位置分别是多少?(使用 gdb 调试内核,是为了跟踪到 main 函数入口) 响

qq_43515555的博客 8248

Linux 时钟中断处理(一)

最近想研究下Linux下的时钟中断,因为时钟中断算是一个操作系统下最频繁的中断事件了吧(个人认为)。 以4.5 x86_64 Linux内核为例。 面对庞大的代码量,无从下手啊。不如从中断号看起吧微笑Linux 源码中有这样的定义(arch/x86/include/asm/irq_vectors.h): #define LOCAL_TIMER_VECTOR 0xef 如果没猜错的话,应该就是Linux下的时钟中断向量了(0xEF=239)。

bgao86的博客 1万+

HDMI设计2----EDID and E-EDID

1,EDID是什么?有什么用? 图1 应用场景 如图1所示的应用场景,PC将视频信号发送 到我们的设备上,经过一系列的传输和切换,设备将视频信号发送到显示器或者投影机上,也就是说,我们的设备位于PC和显示器之间。首先,在输入端,设备需要让PC知道自己是能够接受输入视频信号的,让PC认为自己是一台显示器。如果不这样做的话,PC可能会拒绝输出任何视频信号的(VGA接口不需要EDID也能输出)。除此之外,设备还要告诉PC自己支持的显示时序。而在输出端,当设备需要自建输出时序而不是简单的复制...

Archar_Saber的博客 7988

课后作业2.1

课后作业2.1

m0_52774249的博客 1667

手把手复现论文:SVPWM过调制I区与II区算法仿真(附MATLAB源码)

本文详细介绍了SVPWM过调制I区与II区算法的MATLAB仿真实现,从理论推导到Simulink建模逐步解析。通过源码示例展示幅值补偿和六边形跟踪等关键技术,帮助电力电子研究者掌握过调制算法的核心实现方法,适用于电机控制、变频器等工业应用场景。

weixin_28739079的博客 529

Linux设备驱动程序之中断与时钟(三)

Linux设备驱动程序之中断与时钟(三) http://www.cnblogs.com/hanyan225/archive/2010/10/25/1860201.html     晚上7点10分.. “小涛哥,这章不是叫Linux设备驱动程序之中断与时钟,前边你讲了中断,还给了我很多模版,我都看懂了,这次是不是要开始讲时钟了..” “真聪明,越来越喜欢你这聪明的样子了,说的不错,

lqf785435771的专栏 562

STM32串口调试踩坑记:HAL_UART_ErrorCallback里不先解锁,你的中断接收就废了

本文深入分析了STM32串口调试中HAL_UART_ErrorCallback的锁机制陷阱,指出在错误回调中不先解锁会导致中断接收失效的问题。通过解析HAL库源码,提出了正确的错误处理实现方法,并分享了预防措施与最佳实践,帮助开发者提升串口通信的可靠性。

weixin_33733810的博客 512

QT-使用ECharts显示地图,还有更多惊艳的图表等待你的使用

QT-使用ECharts显示地图前言一、使用步骤1.下载示例2. QT使用HTML文件配置3.使用HTML文件4. 数据交互及自适应总结注意:这个地图是百度的在线地图,需要百度API密钥和在联网的状态下使用。离线使用图表 前言 我上文QT图表chart-饼状图,使用qt自带的图表库charts来显示图表,实现数据可视化,但是QT自带的图表库显示效果并不佳,通俗说,就是不好看。 然而,有这么一个开源图表库,图表种类极多,并且效果良好,能够实现具有很好的视觉冲击的数据可视化。 它就是Apache ECharts

博咯的博客 4897

linux 内核中断与时钟的冲突 问题 del_timer,Linux内核开发之中断与时钟(三)

晚上7点10分..“小涛哥,这章不是叫Linux设备驱动程序之中断与时钟,前边你讲了中断,还给了我很多模版,我都看懂了,这次是不是要开始讲时钟了..”“真聪明,越来越喜欢你这聪明的样子了,说的不错,今天就要开始一个新的模块--内核时钟”我很少夸人,为啥今天夸她呢了,呵呵.定时器,意思大家都明白,我就不说了,要是不明白,把它想成个闹钟总可以吧..定时器分为硬件和软件定时器,软件定时器最终还是要依靠硬...

weixin_29038303的博客 375

[Dify实战] 招投标标书智能生成:模板套用 + 风险校验

摘要:本文提出基于Dify构建AI标书生成工作流,解决传统标书撰写中内容重复(80%复用率)、人工修改效率低、风险检查易出错等痛点。方案包含三大核心模块:1)智能生成(基于模板自动填充项目信息);2)风险校验(AI自动检查废标风险点);3)多角色协作。通过拆分标书结构、设置详细Prompt、建立风险检查清单,实现从"人工撰写"到"参数化自动生成+AI审核"的转型,最终输出标准格式文档并支持企业系统集成。典型应用场景下,系统能自动生成技术方案并识别关键风险(如支付安全合

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 827

嵌入式Linux内核深度对比:i.MX6ULL、全志T113-T与RK3568平台迁移指南

选择i.MX6ULL当项目需要高可靠性工业级方案硬件成本敏感且无需复杂多媒体已有NXP生态开发经验选择全志T113-T当需要高性价比多媒体方案开发周期紧张且功能需求明确偏好中文社区支持选择RK3568当需要AI加速或4K视频处理系统要求高性能多核处理计划长期迭代升级产品迁移验证清单时钟树配置验证(特别是休眠唤醒时序)DMA内存对齐检查(i.MX需32字节对齐)中断映射表一致性确认电源域隔离测试启动时间测量(从复位到用户空间)

niuTyler的博客 901

在Centos上从零开始部署并运行TinyWebServer服务器,过程记录(非常详细)

TinyWebServer是个什么项目?它是Linux下C++轻量级Web服务器,助力初学者快速实践网络编程,搭建属于自己的服务器。使用线程池+非阻塞socket+epoll(ET和LT均实现) +事件处理(Reactor和模拟Proactor均实现) 的并发模型使用状态机解析HTTP请求报文,支持解析GET和POST请求访问服务器数据库实现web端用户注册、登录功能,可以请求服务器图片和视频文件实现同步/异步日志系统,记录服务器运行状态。......

AnChenliang_1002的博客 3021

【CSP-S 提高组】考试大纲集合

【CSP-S提高组】考试大纲集合

weixin_42596089的博客 7255

linux内核-时钟中断

在所有的外部中断中,时钟中断起着特殊的作用,其作用远非单纯的计时所能相比。当然,即使是单纯的计时也已经足够重要了。别的不说,没有正确的时间关系,你用来重建内核的工具make就不能正常运行了,因为make是靠时间标记来确定是否需要重新编译以及链接的。瞌睡时钟中断的重要性还远不止于此。 我们在中断的博客中看到,内核在每次中断(以及系统调用和异常)服务完毕返回用户空间之前都要检查是否需要调度,若有需要就进行进程调度。事实上,调度只有当CPU在内核中运行时才能发生。在进程的博客中,读者将会看到进程调度发生在两种情

guoguangwu的专栏 3403

NSGA-II 多目标优化 —— 理论、案例与交互式 GUI 实现

本文详细介绍了 NSGA-II 多目标优化算法的基本原理、数学模型和实现流程。从非支配排序、拥挤距离计算到遗传操作,NSGA-II 通过对种群进行分层和排序,能够有效求解多目标优化问题,获得 Pareto 前沿解集。通过机械结构优化、资源分配和控制参数调优等典型案例,我们展示了 NSGA-II 在实际工程中的广泛应用。为帮助工程师和研究者更直观地理解算法求解过程,本文提供了基于 Python 与 PyQt6 的交互式 GUI 演示系统代码示例。

闲人编程的博客 2120

Linux内核的时钟中断机制

看到一篇关于Linux时钟机制的文章,觉得分析得非常好,转贴于此:Linux内核的时钟中断机制第七章 Linux内核的时钟中断 (By 詹荣开,NUDT) opyright © 2003 by 詹荣开 E-mail:zhanrk@sohu.com Linux-2.4.0 Version 1.0.0,2003-2-14 摘要:本文主要从内核实现的角度分析了Linux 2.4.0内核

2838

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Linux 内核中的时间管理:时钟源与定时器的实现

Linux 内核中的时间管理系统是一个核心组件,它负责维护系统的时间,提供定时器功能,支持各种时间相关的操作。时间管理的设计思路与企业管理中的时间规划有着密切的联系,它通过时间基准、任务调度、效率优化和可靠性等机制,为系统的高效运行提供了保障。工作也要流程化,时间管理就像是系统中的时间规划工具,它确保了系统的时间准确性和任务的按时执行。在实际应用中,我们需要根据具体场景选择合适的时钟源和定时器类型,并优化定时器的使用,以实现系统的最佳性能。

jiang_style的博客 4508

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

linux时间管理,时钟中断,系统节拍

目录 1 时钟中断/系统节拍 1.1 简介 1.2 系统时钟中断需要处理的事情 2 HZ 2.1 简介 2.2 动态调节时钟中断 / CONFIG_NO_HZ / 降低功耗/tickless mode 2.3 获取当前运行系统的HZ值 / USER_HZ 3 jiffies和jiffies_64(记录系统启动以来产生的节拍数) 3.1 简介 3.2 访问jiffies和jiffies_64 3.3 jiffies和毫秒微秒之间的转换 4 uptime(系统启动到现在的时间;系统空闲时

u010936265的博客 3378

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Linux内核-时间子系统(时钟中断)专题汇总

Linux时间子系统知识汇总

weixin_38597669的博客 1726
上一篇: Linux内核开发之中断与时钟(二)
下一篇: 美妙的诗文语句(不断更新中…)
wustdatamining
博客等级 码龄15年 12粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值