您好,登錄后才能下訂單哦!
Linux內(nèi)核定時器timer_list怎么用,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
一、簡單介紹一下定時器timer_list:
1、所在頭文件:linux/timer.h
2、結(jié)構(gòu)體:
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_STATSint start_pid;void *start_site;char start_comm[16];#endif#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;#endif};
3、主要成員介紹:
list 實現(xiàn)的時候使用的,和定時器功能無關(guān);
expires 是定時器定時的滴答數(shù)(當前的滴答數(shù)為jiffies);
void (*function)(unsigned long) 定時器超時處理函數(shù);
data 傳遞到超時處理函數(shù)的參數(shù),主要在多個定時器同時使用時,區(qū)別是哪個timer超時。
4、提供的API接口:
a、init_timer(struct timer_list*):定時器初始化函數(shù);
b、add_timer(struct timer_list*):往系統(tǒng)添加定時器;
c、mod_timer(struct timer_list *, unsigned long jiffier_timerout):修改定時器的超時時間為jiffies_timerout;
d、timer_pending(struct timer_list *):定時器狀態(tài)查詢,如果在系統(tǒng)的定時器列表中則返回1,否則返回0;
e、del_timer(struct timer_list*):刪除定時器。
5、使用方法:
a、創(chuàng)建定時器時需要先定義struct timer_list my_timer;
b、在file_operation指定的open函數(shù)中初始化定時器init_timer(&my_timer);
c、在超時處理函數(shù)結(jié)尾重新加載定時器時間mod_timer(&my_timer,HZ);
d、如果自己編寫的驅(qū)動中有中斷,需要在中斷入口處del_timer(&my_timer);并且在入口處重新重新加載定時器時間mod_timer(&my_timer,HZ)。
二、實例演示:
1、驅(qū)動程序代碼:
#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/delay.h> /*delay*/#include <linux/cdev.h>#include <linux/device.h>#include <linux/slab.h> /*kmalloc*/#include <linux/vmalloc.h> /*vmalloc*/#include <linux/types.h> /*ssize_t*/#include <linux/fs.h> /*file_operaiotns*/#include <linux/gpio_keys.h>#include <linux/gpio.h>#include <linux/irq.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/uaccess.h>/************硬件相關(guān)*************/#include <mach/iomux-mx6dl.h> /*普通IO*/#define LED IMX_GPIO_NR(1,15) /*SD2_DAT0*/ /*分配內(nèi)存空間大小*/#define WRITE_MALLOC_SIZE 4096/**主設(shè)備號和次設(shè)備號**/#define DEVICE_MAJOR 102#define DEVICE_MINOR 0/*緩存區(qū)指針,指向內(nèi)存區(qū)*/static char *led_spvm;/*在/sys目錄創(chuàng)造一個類*/static struct class *led_class; /*在這個類下,創(chuàng)造一個設(shè)備節(jié)點*/static struct cdev *led_class_dev;/*定義定時器結(jié)構(gòu)體*/static struct timer_list timer; typedef unsigned short int unit; /*2個字節(jié),16bit*//*超時函數(shù)聲明*/void mytimeout(void); /*定時器初始化函數(shù)*/void mytimer_init(void) { init_timer(&timer); /*初始化定時器*/ timer.expires = jiffies + HZ; /*設(shè)置超時時間為1S*/ timer.function = mytimeout; /*設(shè)置超時之后中斷服務(wù)子程序入口*/add_timer(&timer); /*啟動定時器*/}/*open函數(shù)的實現(xiàn)*/static int led_open(struct inode *inode, struct file *file) {/*定時器初始化*/mytimer_init();return 0; }/*release函數(shù)的實現(xiàn)*/static int led_close(struct inode *inode, struct file *file) { /*釋放占用的資源*/gpio_free(LED);/*刪除定時器*/del_timer(&timer);/*打印提示退出信息*/printk(KERN_ALERT"LED is closed!\n");return 0; }/*具體的文件操作集合*/static const struct file_operations led_fops = {/*這是擁有者*/.owner = THIS_MODULE, .open = led_open, .release = led_close, };/*超時中斷服務(wù)子函數(shù)*/void mytimeout(void) { /*LED閃爍*/__gpio_set_value(LED,1); mdelay(1000); __gpio_set_value(LED,0);/*重新設(shè)置定時時間為1s*/mod_timer(&timer,jiffies + HZ); }/*驅(qū)動的初始化函數(shù)*/static int led_init(void) {/*設(shè)備初始化*/int devno,error;/*設(shè)備號的申請,創(chuàng)建*/devno = MKDEV(DEVICE_MAJOR,DEVICE_MINOR);/*分配設(shè)備結(jié)構(gòu)體的地址空間*/led_spvm = (char *)vmalloc(WRITE_MALLOC_SIZE); led_class_dev = cdev_alloc();/*字符設(shè)備初始化,綁定相關(guān)操作到設(shè)備*/cdev_init(led_class_dev,&led_fops);/*設(shè)備的擁有者*/led_class_dev->owner = THIS_MODULE;/*添加設(shè)備到內(nèi)核*/cdev_add(led_class_dev,devno,1);/*靜態(tài)申請設(shè)備號*/register_chrdev(DEVICE_MAJOR,"led",&led_fops); /*創(chuàng)建設(shè)備類,用于自動創(chuàng)建設(shè)備文件*/led_class = class_create(THIS_MODULE, "led"); /*依據(jù)以前創(chuàng)建的設(shè)備類,創(chuàng)建設(shè)備*/device_create(led_class,NULL,MKDEV(DEVICE_MAJOR,DEVICE_MINOR),NULL,"led"); /*申請gpio*/error = gpio_request(LED,"gpio");if (error < 0) { printk(KERN_ALERT"failed to request GPIO LED\n");goto fail1; }/*設(shè)置IO方向為輸出*/error = gpio_direction_output(LED,0);if (error < 0) { printk(KERN_ALERT"failed to configure direction for LED\n");goto fail2; }return 0; fail1:return error; fail2: gpio_free(LED); }/*退出函數(shù)*/static void led_exit(void) {/*定時器卸載*/ del_timer(&timer); /*設(shè)備卸載*/unregister_chrdev(DEVICE_MAJOR,"led"); device_destroy(led_class,MKDEV(DEVICE_MAJOR,DEVICE_MINOR)); class_destroy(led_class); }/*LICENSE信息*/MODULE_LICENSE("GPL");/*卸載和加載*/module_init(led_init); module_exit(led_exit);
2、測試程序代碼:
#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>int main(int argc,char **argv) { int fd;/*對應(yīng)加載進去的設(shè)備名:dev/led*/fd = open("/dev/led",O_RDWR);/*如果打開設(shè)備出錯,打印信息*/if (fd < 0) {printf("can`t open fd_write!\n"); }while(1) { sleep(1000); }/*退出時候,關(guān)閉設(shè)備*/close(fd); }
看完上述內(nèi)容,你們掌握Linux內(nèi)核定時器timer_list怎么用的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。