Linux 타이머 사용 가이드 및 예

이 기사에서는주기적인 인터럽트, 중지 및 시작 제어를 포함하여 Linux에서 타이머를 사용하는 방법을 간략하게 설명합니다.

매일 일반적으로 사용되는 몇 가지 타이머 관련 Linux API 함수 :

  1. init_timer (); 타이머 초기화
  2. add_timer (); 커 스터 마이저 시작
  3. del_timer (); 타이머 중지
  4. mod_timer (); 타이머의 현재 계산 시간을 다시 수정합니다.

이러한 API는 kernel \ timer.c에 있습니다. 소스 파일에는 msleep () 및 schedule_timeout ()과 같이 일반적으로 사용되는 지연 스케줄링 기능도 포함되어 있습니다.

다음은 Linux (3.10.0-123 커널 기반)에서 타이머 사용을 소개하는 예제 드라이버입니다.


사례는 다음과 같습니다.

  1. 타이머를 만들고 3 초마다주기적인 인터럽트를 완료하고 인쇄합니다.
  2. 문자 장치 인터페이스를 통해 사용자 계층과 상호 작용하고, 0을 작성하여 타이머를 끄고 (중지), 1을 작성하여 타이머를 켜고 (시작)
    (즉, echo 1> / dev / demo_deva가 타이머를 시작할 때, echo 0 일 때 > / dev / demo_deva가 타이머를 중지 함).
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/ioctl.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/device.h> 
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include "timer_drv.h"

/*
功能:
	定时器3秒定时中断一次打印。
	当echo 1 >/dev/demo_deva开启定时器,当echo 0 >/dev/demo_deva 关闭定时器
*/

#define DRV_VERSION  "V1.0"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LUDY");
MODULE_DESCRIPTION("This is timer demo");
MODULE_VERSION(DRV_VERSION);

//static volatile int time_count = 0;
static void handel_irq_do_timer(unsigned long arg);
u8 delay = 3; //3s
/* 设备要使用的定时器 */
static struct timer_list my_timer;//也可以:TIMER_INITIALIZER(handel_irq_do_timer, 0, 0); 直接快速初始化结构体内容

/* 定时器中断处理函数 */
static void handel_irq_do_timer(unsigned long arg)
{
    
    
	// struct xxx_device *dev = (struct xxx_device *)(arg);
	/* 修改调度定时器,3s再执行 */
	mod_timer(&my_timer, jiffies + delay*HZ); //*HZ即转换成jiffies单位值
	printk("timer arrival\n");
}

/* 定时器初始化*/
void timer_init_run(void* pri_data)
{
    
    

	//device *dev =  (device*)pri_data;
    /* 初始化定时器 */
    init_timer(&my_timer);   
	/* 设备结构体指针作为定时器处理函数参数 */
    my_timer.function = &handel_irq_do_timer; //中断处理函数
	my_timer.expires =  delay*HZ;  //定时时间delay秒  
    //my_timer.data = (unsigned long)dev;
}

/*
写函数;
定时器启动和停止控制
*/
ssize_t  demodrv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    
    
	char rev_data;
      /*只接受一个字符的写入*/
	if(count >2)  //count包括了/0字符
		return -EFAULT;
	//copy_from_user(rev_data1, buf, count);
	if(get_user(rev_data, buf))
	{
    
    
		return -EFAULT;
	}
	printk("driver: device write:%c  count:%d\n" ,rev_data, count);

	switch(rev_data)
	{
    
    
		case '0':
		    /* 删除(停止)定时器 */
			del_timer(&my_timer);
			break;
		case '1':
			/* 添加(注册) 启动定时器 */
			add_timer(&my_timer);  //add添加后,定制器开始运行
			break;
		default:
			PRINT_ERR("write EINVAL:%c\n" ,rev_data);
			break;
	}
	return count;
}


ssize_t demodrv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    
    
	return 1;
}

static int demodrv_open(struct inode *inode, struct file *file)
{
    
    
	printk("driver: device open\n");
	return 0;
}


int demodrv_close(struct inode *inode, struct file *file)
{
    
    
	printk("driver: device close\n");
	return 0;
}


static struct file_operations demo_drv_fops = {
    
    
    .owner   =  THIS_MODULE, 
    .open    =  demodrv_open,     
	.read	 =	demodrv_read,
	.write	 =	demodrv_write,		
	.release =  demodrv_close,
};

int major;
static struct class *demo_drv_class;
static struct class_device	*demo_class_dev;

static int __init demo_drv_init(void)
{
    
    
	major = register_chrdev(0, "demo_drv", &demo_drv_fops);//注册字符驱动获取设备号
	demo_drv_class = class_create(THIS_MODULE, "demo_drv_class"); //sys/class下创建类
	demo_class_dev = device_create(demo_drv_class, NULL, MKDEV(major, 0), NULL, "demo_dev"); /*类下创建设备文件绑定到设备号 /dev/demo_dev */

	timer_init_run(demo_class_dev);
	return 0;
}


static void __exit demo_drv_exit(void)
{
    
    
	unregister_chrdev(major, "demodrv");
	device_unregister(demo_class_dev);
	class_destroy(demo_drv_class);
    /* 删除(停止)定时器 */
    del_timer(&my_timer);

	return 0;
}
module_init(demo_drv_init);
module_exit(demo_drv_exit);

위의 소스 코드에서 알 수 있듯이 타이머를 사용하려면 일반적으로 다음 단계가 필요합니다.

  1. timer_list 구조의 타이머 객체를 정의합니다. 그리고 TIMER_INITIALIZER를 통해 객체의 멤버 (인터럽트 기능, 타이밍 시간 등)를 빠르게 할당 할 수 있습니다.
  2. init_timer는 커 스터 마이저를 초기화합니다 (타이머는 아직 갈 수 없습니다).
  3. 타이머 개체의 구성원 (인터럽트 기능, 타이밍 시간, 개인 데이터 등)에 값을 할당하도록 사용자 정의 할 수 있습니다.
  4. add_timer는 타이머를 시작하고 타이머는 카운트 다운을 시작합니다.
  5. mod_timer는 현재 타이머 값을 수정합니다 (타이머 재설정).
  6. 타이머를 중지 (삭제)하려면 del_timer를 실행하고 다시 시작해야하는 경우 add_timer를 계속 실행합니다.

추천

출처blog.csdn.net/ludaoyi88/article/details/113833912