#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm-generic/termios.h>
#include <asm-generic/ioctl.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <asm-generic/fcntl.h>
#include <linux/poll.h>
//#include <asm-generic/atomic.h>
#include <linux/atomic.h>
int major = 11;
int minor = 0;
/********/
struct mychar_dev
{
struct cdev mysecond;
atomic_t onlyonce;
int second;
struct timer_list mytimer;
};
char* name = "mychar";
struct mychar_dev mydev;
/********/
dev_t devno;
int char_num = 2;
int mysecond_open(struct inode* mynode,struct file* myfile)
{
struct mychar_dev* p = NULL;
myfile->private_data = (void *)container_of(mynode->i_cdev,struct mychar_dev,mysecond);
p = myfile->private_data;
add_timer(&p->mytimer);//定时器开始计时
if(atomic_dec_and_test(&p->onlyonce))
{
return 0;
}
else
{
atomic_inc(&p->onlyonce);
return -1;
}
}
int mysecond_close(struct inode* mynode,struct file* myfile)
{
struct mychar_dev* p = (struct mychar_dev*)myfile->private_data;
p->second = 0;//清零
del_timer(&p->mytimer);//定时器停止计时
atomic_set(&p->onlyonce,1);//初始化原子变量
return 0;
}
ssize_t mysecond_read(struct file* myfile,char __user* puser,size_t size,loff_t* loff)
{
struct mychar_dev* p = (struct mychar_dev *)myfile->private_data;
int count = 0;
int res = 0;
if(size < 4)
{
count = 4;
}
if(size > 4)
{
count = 4;
}
res = copy_to_user(puser,&p->second,sizeof(int));
if(res)
{
printk("copy_to_user error\n");
return -1;
}
return count;
}
struct file_operations mysecond_ops = {
.owner = THIS_MODULE,
.open = mysecond_open,
.read = mysecond_read,
.release = mysecond_close,
};
void myhandler(unsigned long arg)
{
struct mychar_dev* p = (struct mychar_dev*)arg;
p->second++;
mod_timer(&p->mytimer,jiffies + HZ * 1);
}
int __init mysecond_init(void)
{
struct mychar_dev *p = NULL;
int res;
devno = MKDEV(major,minor);
res = register_chrdev_region(devno,char_num,name);
if(res != 0)
{
res = alloc_chrdev_region(&devno,minor,char_num,name);
if(res != 0)
{
printk("alloc_register_region faliued\n");
return -1;
}
printk("alloc ok\n");
major = MAJOR(devno);
}
cdev_init(&mydev.mysecond,&mysecond_ops);
(mydev.mysecond).owner = THIS_MODULE;
cdev_add(&mydev.mysecond,devno,1);
atomic_set(&mydev.onlyonce,1);//初始化原子变量
p = (struct mychar_dev*)&mydev;
mydev.mytimer.expires = jiffies + HZ * 1;
mydev.mytimer.data = (unsigned long )(p);
mydev.mytimer.function = myhandler;
init_timer(&mydev.mytimer);
return 0;
}
void __exit mysecond_exit(void)
{
devno = MKDEV(major,minor);
cdev_del(&mydev.mysecond);
unregister_chrdev_region(devno,char_num);
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jzt");
MODULE_DESCRIPTION("this is a devno test");
module_init(mysecond_init);
module_exit(mysecond_exit);