内核定时器使用(example)

1.驱动程序
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/timer.h> /*包括timer.h头文件*/
#include <asm/atomic.h> 

#define SECOND_MAJOR 252

static int second_major = SECOND_MAJOR ;

struct second_dev
{
  struct cdev cdev;
  atomic_t counter;
  struct timer_list s_timer;
};

struct second_dev *second_devp;

static ssize_t second_read(struct file *filp,char __user *buf,
			   size_t count,loff_t *ppos)
{
  int counter;
  counter = atomic_read(&second_devp->counter);
  if(put_user(counter,(int*)buf))
    return - EFAULT;
  else
    return sizeof(unsigned int);
}

static void second_timer_handle(unsigned long arg)
{
  mod_timer(&second_devp->s_timer,jiffies + HZ/4 );
  atomic_inc(&second_devp->counter);
  printk(KERN_NOTICE "hi,this is a timer executing...%ld\n",jiffies);
}

int second_open(struct inode *inode,struct file *filp)
{
  init_timer(&second_devp->s_timer);
  second_devp->s_timer.function = &second_timer_handle;
  second_devp->s_timer.expires = jiffies + HZ ;
  add_timer(&second_devp->s_timer);
  atomic_set(&second_devp->counter,0);
  return 0;
}

int second_release(struct inode *inode,struct file *filp)
{
  del_timer(&second_devp->s_timer);
  return 0;
}

static const struct file_operations second_fops =
  {
    .owner = THIS_MODULE,
    .open = second_open,
    .release = second_release,
    .read = second_read,
};


int second_init(void)
{
  int ret;
  dev_t devno=MKDEV(second_major,0);
  if(second_major)
    {
      ret = register_chrdev_region(devno,1,"second");
    }
  else
    {
      ret = alloc_chrdev_region(&devno,0,1,"second");
      second_major = MAJOR(devno);
    }
  if(ret<0)
    return ret;
  second_devp = kmalloc(sizeof(struct second_dev),GFP_KERNEL);
  if(!second_devp)
    {
      ret = -ENOMEM;
      goto fail;
    }
  memset(second_devp,0,sizeof(struct second_dev));
  
  cdev_init(&second_devp->cdev,&second_fops);
  ret = cdev_add(&second_devp->cdev,devno,1);
  if(ret)
    {
      printk(KERN_ALERT "ERROR ADDING CHAR DEVICE WHILE INITING TIMER.\n");
      goto fail;
    }

  return 0;

fail:
  if(second_devp)
    {
      kfree(second_devp);
      second_devp = NULL;
    }
  unregister_chrdev_region(devno,1);
  return ret;
  
}

void second_exit(void)
{
  cdev_del(&second_devp->cdev);
  kfree(second_devp);
  unregister_chrdev_region(MKDEV(second_major,0),1);
}

MODULE_AUTHOR("ustc");
MODULE_LICENSE("GPL");

module_param(second_major,int,S_IRUGO);

module_init(second_init);
module_exit(second_exit);
2.测试文件
/*======================================================================
    A test program to access /dev/second
    This example is to help understand kernel timer 
    
    The initial developer of the original code is Baohua Song
    <author@linuxdriver.cn>. All Rights Reserved.
======================================================================*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>

int main(int argc,char *argv[])
{
  int fd;
  int counter = 0;
  int old_counter = 0;

  if(argc<2)
    {
      printf("wrong parameter !\n");
      return -1;
    }
  fd = open(argv[1], O_RDONLY);

  if (fd !=  - 1)
  {
    while (1)
    {
      read(fd,&counter, sizeof(unsigned int));//读目前经历的秒数
      if(counter >= 20)
	break;
      if(counter!=old_counter)
      {	
      	printf("1/4 seconds after open %s :%d\n",argv[1],counter);
      	old_counter = counter;
      }	
    }
    close(fd);
  }
  else
  {
    printf("Device open failure\n");
  }
  return 0;
}
3. Makefile文件
KERNELDIR = /usr/src/linux-headers-$(shell uname -r)
PWD := $(shell pwd)
CC    = gcc
OBJ := hi_timer
obj-m := $(OBJ).o 
DEVICE_NAME := second
MAJOR := 252
TEST_FILENAME:=second_test
moudles:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

install:
	sudo insmod $(OBJ).ko
	sudo mknod /dev/$(DEVICE_NAME) c $(MAJOR) 0
	sudo chmod ugo+rw /dev/$(DEVICE_NAME)
exec:
	$(CC) -o $(TEST_FILENAME) $(TEST_FILENAME).c
	./$(TEST_FILENAME) /dev/$(DEVICE_NAME)

uninstall:
	sudo rmmod $(OBJ)
	sudo rm -rf /dev/$(DEVICE_NAME)
clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions $(TEST_FILENAME) *symvers

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux内核定时器内核用于在未来某个时间点或者特定时间段内调度执行某个函数的一种机制。它是一个软定时器,最终依赖于CPU的硬件定时器实现。对于Linux内核来说,它依赖于系统时钟节拍。内核定时器的处理函数在软中断中执行。它有几个特点:依赖于系统时钟节拍、只执行一次,超时后即退出。如果需要周期性的定时器,需要在超时处理函数中重新开启定时器。在Linux内核编程中常常会使用定时器,例如在驱动程序中使用定时器解决按键消抖、延时等待硬件就绪等问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【Linux驱动编程】如何使用内核定时器](https://blog.csdn.net/qq_20553613/article/details/106028620)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [【嵌入式Linux驱动开发】十四、了解Linux内核定时器使用流程,实现LED闪烁](https://download.csdn.net/download/weixin_38664427/14883898)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanzhong104204

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值