linux定時器使用


作者: 樊穎飛

定時器在內核的定義:

struct timer_list {
  /*
   * All fields that change during normal runtime grouped to the
   * same cacheline
   */
  struct list_head entry; //定時器的鏈表
  unsigned long expires;//以節拍為單位的定時時間,表示為定時器觸發的到期時間
  struct tvec_base *base;

  void (*function)(unsigned long); //該指針指向定時器處理函數,函數參數為長整形
  unsigned long data; //處理函數的參數值

  int slack;

#ifdef CONFIG_TIMER_STATS
  void *start_site;
  char start_comm[16];
  int start_pid;
#endif
#ifdef CONFIG_LOCKDEP
  struct lockdep_map lockdep_map;
#endif
};

使用定時器的步驟:
1) 定義定時器:

struct timer_list my_timer

2)初始化定時器:

初始化定時器的到期節拍數

my_timer.expires = jiffies +delay ;該設置讓定時器的觸發時間設置為 激活定時器后的delay個節拍點

my_timer.function = 處理函數的名稱 該設置設置定時器觸發時處理的函數

my_timer.data 初始化處理函數的參數值,若處理函數沒有參數則可簡單設置為0或任意其他數值

3)激活定時器:即內核會開始定時,直到my_timer.expires

使用函數add_timer 即 add_timer(&my_timer);

內核原型為:

void add_timer(struct timer_list *timer)
{
  BUG_ON(timer_pending(timer));
  mod_timer(timer, timer->expires); //該函數設置定時器timer的定時時間為timer->expires;
}

4)刪除定時器:如果需要在定時器到期之前停止定時器,則可以使用該函數,若是定時器已經過期則不需調用該函數,因為它們會自動刪除

del_timer(&my_timer);

 

定時器的簡單實例:該例子的功能是首先初始化一個定時器,當定時器時間到后觸發定時器出倆函數的執行,該函數又重新設置了該定時器的時間,即該定時器又在下一次定時時間的到來繼續處理函數,一直循環,知道最后在該模塊卸載時進行刪除定時器,結束該定時器

代碼中 HZ為內核每一秒的節拍數,是通過宏進行定義的,通過該程序的打印結果可以得到,本人電腦的節拍數測試結果為250

#include< linux/module.h >
#include< linux/init.h >
#include< linux/sched.h >
#include < linux/timer.h >

#include < linux/kernel.h >

struct timer_list stimer; //定義定時器
static void time_handler(unsigned long data){ //定時器處理函數
  mod_timer(&stimer, jiffies + HZ);
  printk(“current jiffies is %ld\n”, jiffies);
}
static int __init timer_init(void){ //定時器初始化過程
  printk(“My module worked!\n”);
  init_timer(&stimer);
  stimer.data = 0;
  stimer.expires = jiffies + HZ; //設置到期時間
  stimer.function = time_handler;
  add_timer(&stimer);
  return 0;
}
static void __exit timer_exit(void){
  printk(“Unloading my module.\n”);
  del_timer(&stimer);//刪除定時器
  return;
}
module_init(timer_init);//加載模塊
module_exit(timer_exit);//卸載模塊

MODULE_AUTHOR(“fyf”);

MODULE_LICENSE(“GPL”);

加載/ 卸載該程序后通過命令dmesg可以看到

[ 6225.522208] My module worked!
[ 6226.520014] current jiffies is 1481630
[ 6227.520014] current jiffies is 1481880
[ 6228.520013] current jiffies is 1482130
[ 6229.520011] current jiffies is 1482380
[ 6229.770335] Unloading my module.
即每2次的jiffies之差為250

 

定時器的應用:以下是一個簡單的延遲當前進程執行的程序,延遲是通過定時器來實現的;

#include< linux/module.h >
#include< linux/init.h >
#include< linux/sched.h >
#include < linux/timer.h >
#include < linux/kernel.h >
struct timer_list stimer; //定義定時器
int timeout = 10 * HZ;
static void time_handler(unsigned long data){ //定時器處理函數,執行該函數獲取掛起進程的pid,喚醒該進程
  struct task_struct *p = (struct task_struct *)data;//參數為掛起進程pid
  wake_up_process(p);//喚醒進程
  printk(“current jiffies is %ld\n”, jiffies); //打印當前jiffies
}
static int __init timer_init(void){ //定時器初始化過程
  printk(“My module worked!\n”);
  init_timer(&stimer);
  stimer.data = (unsigned long)current; //將當前進程的pid作為參數傳遞
  stimer.expires = jiffies + timeout; //設置到期時間
  stimer.function = time_handler;
  add_timer(&stimer);
  printk(“current jiffies is %ld\n”, jiffies);
  set_current_state(TASK_INTERRUPTIBLE);
  schedule(); //掛起該進程
  del_timer(&stimer); //刪除定時器
  return 0;
}
static void __exit timer_exit(void){
  printk(“Unloading my module.\n”);
  return;
}
module_init(timer_init);//加載模塊
module_exit(timer_exit);//卸載模塊
MODULE_AUTHOR(“fyf”);
MODULE_LICENSE(“GPL”);

運行結果:

[ 9850.099121] My module worked!
[ 9850.099127] current jiffies is 2387524
[ 9860.128017] current jiffies is 2390032
[ 9869.135805] Unloading my module.

打印結果與定時時間2500有一點差距,是因為打印時第一次的jiffies實在add_timer之后打印的,故不是定時器激發時的jiffies,第二次同理,所以結果不是確定的,但都於2500相差不多


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM