当前位置: 首页 > news >正文

科研网站建设sem公司

科研网站建设,sem公司,wordpress装好域名打不开,酒类网站建设方案前言 这篇博客一起学习定时器#xff0c;定时器是最常用到的功能之一#xff0c;其最大的作用之一就是提供了延时函数。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程#xff0c;未来预计四个月将高强度更新本专栏#xff0c;喜欢的可以关注本博主并订阅本专栏定时器是最常用到的功能之一其最大的作用之一就是提供了延时函数。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程未来预计四个月将高强度更新本专栏喜欢的可以关注本博主并订阅本专栏一起讨论一起学习。现在关注就是老粉啦 行文目录 前言1. Linux内核定时器介绍1.1 定时器介绍1.2 超时时间计算 2. 内核定时器使用2.1 内核定时器的API函数2.2 内核定时器的使用过程2.2 内核定时器的使用案例 3. 内核的延迟机制3.1 对比jiffies的函数3.2 忙等延时3.2.1 短延时3.2.2 长延时 3.3 睡眠延时3.3.1 sleep类延时函数3.3.2 schedule类延时函数3.3.3 sleep_on类延时函数 参考资料 1. Linux内核定时器介绍 1.1 定时器介绍 Linux内核定时器采用系统时钟而非像单片机中使用PIT等硬件定时器。其使用只需要提供超时时间与定时处理函数即可当超时时间到了以后设置的定时函数就会执行。 不同于之前的单片机中的定时器内核定时器并非周期性运行的而是超时后会关闭因此想周期性实现定时的话就需要在定时处理函数中重新开启定时器。 1.2 超时时间计算 Linux内核使用了timer_list结构体表示内核定时器该结构体在include/linux/timer.h中其如下所示 struct timer_list {struct list_head entry;unsigned long expires; // 定时器超时时间单位是节拍数struct tvec_base *base;void (*function)(unsigned long); // 定时处理函数 unsigned long data; // 要传递给 function 函数的参数 int slack; };使用内核定时器需要先定义一个timer_list变量。 其中的expires成员变量表示超时时间单位为节拍数。假设现在需要一个周期为2s的定时器那么定时器的超时时间为jiffies(2*Hz)因此expires就为该值。其中jiffies是系统运行的节拍数jiffies/Hz即系统运行时间单位为s。 结构体中的function为定时器超时后的定时处理函数。 2. 内核定时器使用 2.1 内核定时器的API函数 内核定时器的使用最关键的就是设置超时时间和定时处理函数剩下步骤和其他一样都需要初始化与删除等操作具体的API如下所示 /** description: 初始化timer_list类型变量* param-timer: 要初始化的定时器* return : 无*/ void init_timer(struct timer_list *timer);/** description: 向Linux内核注册定时器注册完后定时器就会开始运行* param-timer: 要注册的定时器* return : 无*/ void add_timer(struct timer_list *timer);不管定时器有没有被激活都可以用del_timer()函数删除。在多处理器系统上定时器可能会在其他的处理器上运行因此在调用此函数之前要先等待其他处理器的定时处理器函数退出。因此可以使用其同步版——del_timer_sync() /** description: 删除一个定时器* param-timer: 要删除的定时器* return : 无*/ int del_timer(struct timer_list *timer);/** description: del_timer函数的同步版会等其他处理器使用完定时器再删除* param-timer: 要删除的定时器* return : 0, 定时器还没被激活1, 定时器已经激活*/ int del_timer_sync(struct timer_list *timer);/** description : 用于修改定时值如果定时器还没有激活的话mod_timer会激活定时器* param-timer : 要修改超时时间的定时器* param-expires: 修改后的超时时间* return : 0调用mod_timer 函数前定时器未激活1调用前定时器已被激活*/ int mod_timer(struct timer_list *timer, unsigned long expires);2.2 内核定时器的使用过程 内核定时器的一般使用流程如下所示 struct timer_list timer;void function(unsigned long arg) {// 定时器处理代码// 如果要周期性运行就用mod_timermod_timer(dev-timertest, jiffiesmsecs_to_jiffies(2000)); }void init(void) {init_timer(timer);timer.function function;timer.expires jffies msecs_to_jiffies(2000);timer.data (unsigned long)dev;add_timer(timer); }void exit(void) {del_timer(timer); // 删除定时器del_timer_sync(timer); // 同步版本 }2.2 内核定时器的使用案例 先在设备结构体中加入定时器变量和自旋锁自旋锁用来保护超时时间。 struct timer_dev {dev_t devid;struct cdev cdev;struct class *class;struct device *device;int major;int minor;struct device_node *nd;int led_gpio;int timerperiod; // 定时周期单位为msstruct timer_list timer; // 定时器spinlock_t lock; // 自旋锁保护超时时间 };编写函数timer_unlocked_ioctl()对应应用程序的ioctl函数应用程序调用ioctl函数向驱动发送控制信号次函数相应并执行 static long timer_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {struct timer_dev *dev (struct timer_dev *)filp-private_data;int timerperiod;unsigned long flags;switch (cmd){// 关闭定时器case CLOSE_CMD: del_timer_sync(dev-timer);break;// 打开定时器case OPEN_CMD:spin_lock_irqsave(dev-lock, flags); // 加锁保护超时时间timerperiod dev-timerperiod;spin_unlock_irqrestore(dev-lock, flags);mod_timer(dev-timer, jiffies msecs_to_jiffies(timerperiod)); // 设置定时器break;// 设置定时器周期case SETPERIOD_CMD:spin_lock_irqsave(dev-lock, flags); // 加锁保护超时时间dev-timerperiod arg;spin_unlock_irqrestore(dev-lock, flags);mod_timer(dev-timer, jiffies msecs_to_jiffies(arg));break;default:break;}return 0; }static struct file_operations timer_fops {.owner THIS_MODULE,.open timer_open,.unlocked_ioctl timer_unlocked_ioctl, };定时器的超时函数在最后重新设置超时时间实现定时器的周期性。 void timer_function(unsigned long arg) {struct timer_dev *dev (struct timer_dev *)arg;static int sta 1;int timerperiod;unsigned long flags;sta !sta;gpio_set_value(dev-led_gpio, sta);spin_lock_irqsave(dev-lock, flags);timerperiod dev-timerperiod;spin_unlock_irqrestore(dev-lock, flags);mod_timer(dev-timer, jiffies msecs_to_jiffies(dev-timerperiod)); }最后在__init()函数中初始化定时器并设置超时函数 static int __init timer_init(void) {// 初始化自旋锁spin_lock_init(timerdev.lock);// 驱动代码// 初始化定时器并设置超时函数init_timer(timerdev.timer);timerdev.timer.function timer_function;timerdev.timer.data (unsigned long)timerdev;return 0; } 3. 内核的延迟机制 内核中涉及的延时主要有两种实现方式忙等待或者睡眠等待。前者阻塞程序在延时时间到达前一直占用CPU后者则是将进程挂起置进程于睡眠态并释放CPU资源。所以前者一般用在毫秒以内的精确延时后者用于延时时间在毫秒以上的长延时。 3.1 对比jiffies的函数 linux内核中提供了以下几个函数用来对比jiffies和设置的值之间是否相等。 time_after(unkown, known); time_before(unkown, known); time_after_eq(unkown, known); time_before_eq(unkown, known);unknown为jiffiesknown为需要对比的值如果unknown超过knowntime_after返回真否则返回假如果unknown没有超过knowntime_before返回真否则返回假。后面的time_after_eq与time_before_eq类似只是增加了相等的判断。 3.2 忙等延时 3.2.1 短延时 Linux内核提供了毫秒微秒和纳秒延时函数。这些实现方式均是忙等待短延时。 void ndelay(unsigned long nsecs); // 纳秒 void udelay(unsigned long usecs); // 微秒 void mdelay(unsigned long msecs); // 毫秒 其本质类似于以下代码 void delay(unsigned int time) { while (time--); }3.2.2 长延时 利用jiffies和time_before()实现延时100个jiffies和2s /*延迟 100 个 jiffies*/ unsigned long delay jiffies 100; while (time_before(jiffies, delay)); /*再延迟 2s*/ unsigned long delay jiffies 2*HZ; while (time_before(jiffies, delay)); 3.3 睡眠延时 3.3.1 sleep类延时函数 下述函数将使得调用它的进程睡眠参数指定的时间受系统 HZ 和进程调度的影响msleep()类似函数的精度是有限的。msleep()、ssleep()不能被打断而msleep_interruptible()则可以被打断。 void msleep(unsigned int millisecs); unsigned long msleep_interruptible(unsigned int millisecs); void ssleep(unsigned int seconds); 3.3.2 schedule类延时函数 schedule_timeout()可以使当前任务睡眠指定的jiffies 之后重新被调度执行它的实现原理是向系统添加一个定时器在定时器处理函数中唤醒参数对应的进程。上一小节的sleep类函数的底层实现也是调用它实现的 signed long schedule_timeout_interruptible(signed long timeout); signed long schedule_timeout_uninterruptible(signed long timeout) 3.3.3 sleep_on类延时函数 函数可以将当前进程添加到等待队列中从而在等待队列上睡眠。当超时发生时进程将被唤醒后者可以在超时前被打断 sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout); interruptible_sleep_on_timeout(wait_queue_head_t*q, unsigned long timeout); 参考资料 [1] 【正点原子】I.MX6U嵌入式Linux驱区动开发指南 第五十章 [2] Linux内核延时机制
http://www.hkea.cn/news/14504187/

相关文章:

  • 开发网站可用性监控wordpress中英文转换
  • 网站建设出找不到网页苏州三笑网络科技有限公司
  • 免费建设小学校网站wordpress评论不审核
  • 青岛同拓网站建设有限公司企业网站建设排名
  • 自己可以建个免费网站吗开发公司管理软件
  • 网页设计师必须知道的网站广西南宁官方网站企业
  • 盘锦建网站上海企业网站制作公司
  • 微信公众号?wordpress网站的优化
  • 哪些网站做宾馆推广好公司部门结构图
  • 毕节做网站西安阎良区建设局网站
  • 浦北网站建设做网站用哪个软件写比较好
  • 北京网站建设策划建设营销型 网站 品牌
  • 长沙百度做网站多少钱百度账号注册
  • 商城网站建设报价单王也头像 呆萌
  • 反腐网站建设的目的wordpress主页设置分类
  • 自己搭建网站做网上商城浙江省建筑工程网
  • 阿里巴巴做公司网站怎样做网站流量
  • 网站制作 北京上海餐饮品牌策划公司
  • 龙岩市住房与城乡建设部网站seo推广小分享
  • 使用三剑客做网站中卫网站建设多少钱
  • 哈尔滨开发网站主题网站界面设计
  • 口碑好网站建设定制专题网站建设的请示
  • 百度上搜索关键词如何在首页北京网络推广优化公司
  • 企业网站模板建站怎么用凡科互动网页版
  • 网站搜索引擎优化的内容wordpress 补丁
  • 网站建设项目收费标准品牌商标设计logo
  • 凡科做网站的方法百度网网站建设的目标
  • 电影网站如何做学校网络建设方案设计
  • 创建集团上海公司网站wordpress自定义菜单设置
  • 网站开发课程百度云duplicator wordpress