内核如果要在将来的某个规定的时刻运行一段程序或进程就要用到内核定时器,内核定时器是一种软件定时器,
linux内核使用结构体struct timer_list
{
struct list_head list;
unsigned long expires;//定时器到期时间
unsigned long data;//作为参数被传入定时器处理函数
void (*function)(unsigned long);//回调处理函数
};
直接贴源码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include "demo.h"
MODULE_AUTHOR("fgj");
MODULE_LICENSE("Dual BSD/GPL");
struct DEMO_dev *DEMO_devices;
static unsigned char demo_inc=0;
static u8 demoBuffer[256];
static struct timer_list mytimer;
int DEMO_open(struct inode *inode, struct file *filp)
{
struct DEMO_dev *dev;
//if(demo_inc>0)return -ERESTARTSYS;
demo_inc++;
dev = container_of(inode->i_cdev, struct DEMO_dev, cdev);
printk("count=%d\n",dev->count);
filp->private_data = dev;
return 0;
}
int DEMO_release(struct inode *inode, struct file *filp)
{
demo_inc--;
return 0;
}
ssize_t DEMO_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
struct DEMO_dev *dev = filp->private_data;
//if (down_interruptible(&dev->sem))
// return -ERESTARTSYS;
/* 把数据拷贝到应用程序空间 */
if (copy_to_user(buf,demoBuffer,count))
{
count=-EFAULT;
}
//up(&dev->sem);
return count;
}
void delay_write(unsigned long data)
{
struct DEMO_dev *dev = (struct DEMO_dev *)data;
printk("in delay_write count=%d\n",dev->count);
printk("buffer=%s\n",dev->buffer);
//if (down_interruptible(&dev->sem))
//{
// return -ERESTARTSYS;
// }
if (copy_from_user(demoBuffer, dev->buffer, dev->count))
{
dev->count = -EFAULT;
}
//up(&dev->sem);
return dev->count;
}
ssize_t DEMO_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
int i = 0;
struct DEMO_dev *dev = filp->private_data;
printk("in write count=%d\n",dev->count);
ssize_t retval = -ENOMEM; /* value used in "goto out" statements */
dev->count = count;
//for(i=0;i < count; i++)
//{
// dev->buffer[i] = buf[i];
//}
//dev->buffer[i] = '\0';
//printk(dev->buffer);
if (copy_from_user(dev->buffer, buf, count))//内核与用户空间的数据的交换必须用copy_from_user 或者copy_to_user,我用这个for循环去一个字符一个字符的区复制是行不
//通的
{
count = -EFAULT;
}
mytimer.expires = jiffies + 1 * HZ;
add_timer(&mytimer);
mytimer.data = dev; //设置定时处理函数的参数,在init函数中这样设置 :mytimer.data = &DEMO_devices;是不行的,这样并不能取到数据
//如果需要通过这个参数传递多个数据项,那么可以将这些数据捆绑成一个数据结构,然后将这个数据结构的指针强制转换成unsigned long传入
/* 把数据拷贝到内核空间 */
/*if (copy_from_user(demoBuffer+*f_pos, buf, count))
{
count = -EFAULT;
}
up(&dev->sem);
return count;*/
return 2;
}
struct file_operations DEMO_fops = {
.owner = THIS_MODULE,
.read = DEMO_read,
.write = DEMO_write,
.open = DEMO_open,
.release = DEMO_release,
};
/*******************************************************
MODULE ROUTINE
*******************************************************/
void DEMO_cleanup_module(void)
{
dev_t devno = MKDEV(DEMO_MAJOR, DEMO_MINOR);
if (DEMO_devices)
{
cdev_del(&DEMO_devices->cdev);
kfree(DEMO_devices);
}
unregister_chrdev_region(devno,1);
}
int DEMO_init_module(void)
{
int result;
dev_t dev = 0;
dev = MKDEV(DEMO_MAJOR, DEMO_MINOR);
result = register_chrdev_region(dev, 1, "DEMO");
if (result < 0)
{
printk(KERN_WARNING "DEMO: can't get major %d\n", DEMO_MAJOR);
return result;
}
DEMO_devices = kmalloc(sizeof(struct DEMO_dev), GFP_KERNEL);
if (!DEMO_devices)
{
result = -ENOMEM;
goto fail;
}
memset(DEMO_devices, 0, sizeof(struct DEMO_dev));
sema_init(&DEMO_devices->sem,1);
cdev_init(&DEMO_devices->cdev, &DEMO_fops);
DEMO_devices->cdev.owner = THIS_MODULE;
DEMO_devices->cdev.ops = &DEMO_fops;
DEMO_devices->count = 3;
init_timer(&mytimer);//timer_list在使用前必须初始化
mytimer.function = &delay_write;
//mytimer.data = &DEMO_devices;
result = cdev_add (&DEMO_devices->cdev, dev, 1);
if(result)
{
printk(KERN_NOTICE "Error %d adding DEMO\n", result);
goto fail;
}
return 0;
fail:
DEMO_cleanup_module();
return result;
}
module_init(DEMO_init_module);
module_exit(DEMO_cleanup_module);
测试代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
int fd;
char num[2];
fd = open("/dev/fgj", O_RDWR, S_IRUSR | S_IWUSR);
if (fd ==- 1)
{
printf("device open failure\n");
}
//while (1)
//{
num[0]='F';
num[1]='G';
write(fd, num, 2);
sleep(3);
read(fd, &num,2); //程序将阻塞在此语句
printf("The data is %s\n", num);
//如果输入是5,则退出
//if (num[1] ==0x35)
//{
// close(fd);
// break;
//}
//}
}