驅動:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h> #include <linux/cdev.h>//cdev
#include <linux/device.h>//udev
#include <linux/sched.h>//schedule
#include <linux/uaccess.h>//copy_to_user
#include <linux/slab.h>//kmalloc() #define DEVICE_NAME "second_drv"
static int second_major=;/*主裝置號*/
struct class *second_class; /*second裝置結構體*/
static struct second_dev
{
struct cdev cdev;/*cdev 結構體*/
atomic_t counter;/*一共經歷了多少時間;定義原子變數*/
struct timer_list s_timer;/*定義一個定時器*/
};
struct second_dev *second_devp;/*定義裝置結構體指標*/ /*定時器處理函式*/
static void second_timer_handler(unsigned long arg)
{
mod_timer(&second_devp->s_timer,jiffies+HZ);/*再次排程定時器*/
atomic_inc(&second_devp->counter);/*counter 加1*/
printk(KERN_NOTICE"current jiffies is %d!!\n",jiffies);
} static int second_open(struct inode *inode, struct file *filp)
{
//printk("in the second_open!!\n");
filp->private_data=second_devp;/*將裝置結構體指標賦值給檔案私有資料指標*/ /*初始化定時器*/
init_timer(&second_devp->s_timer);
second_devp->s_timer.function=&second_timer_handler;
second_devp->s_timer.expires=jiffies+HZ;
add_timer(&second_devp->s_timer);/*新增定時器*/ atomic_set(&second_devp->counter,);/*計數清零*/ return ;
} static int second_release(struct inode *inode,struct file *filp)
{
del_timer(&second_devp->s_timer);/*刪除定時器*/
return ;
} static ssize_t second_read(struct file *filp,char __user *buf,ssize_t count,loff_t *ppos)
{
//printk("in the second_read!!\n");
int counter;
counter=atomic_read(&second_devp->counter);/*獲取count值*/ if(copy_to_user(buf,&counter,count))
return -EFAULT;
else
return sizeof(unsigned int);
} static ssize_t second_write(struct file *filp,const char __user *buf,ssize_t count,loff_t *ppos)
{
return ;
} /*檔案操作結構體*/
static const struct file_operations second_fops={
.owner = THIS_MODULE,
.open =second_open,
.release =second_release,
.read =second_read,
.write =second_write,
}; /*初始化並註冊cdev*/
static void second_setup_cdev(struct second_dev *dev,int index)
{
int err;
dev_t devno=MKDEV(second_major,index);
cdev_init(&dev->cdev,&second_fops);/*初始化cdev成員*/
dev->cdev.owner=THIS_MODULE;
err=cdev_add(&dev->cdev,devno,);/*向系統註冊字元裝置*/
if(err)
printk(KERN_NOTICE"error=%d",err);
} /*裝置驅動模組載入函式*/
static int __init second_init(void)
{
/*申請裝置號*/
int ret;
dev_t devno=MKDEV(second_major,);/*獲得裝置號*/
if(second_major)
ret=register_chrdev_region(devno,,DEVICE_NAME);
else
{
/*動態申請裝置號*/
ret=alloc_chrdev_region(&devno,,,DEVICE_NAME);
second_major=MAJOR(devno);
}
if(ret)
{
printk("request chrdev failed!!\n");
return ret;
} /*動態申請裝置結構體記憶體*/
second_devp=kmalloc(sizeof(struct second_dev),GFP_KERNEL);
if(!second_devp)
{
ret= -ENOMEM;
goto fail_kmalloc;
}
memset(second_devp,,sizeof(struct second_dev));/*申請到的記憶體空間清零*/ /*註冊字元裝置*/
second_setup_cdev(second_devp,); /*用udev機制自動建立裝置檔案結點*/
second_class=class_create(THIS_MODULE,"second_class");/*在sys/class下新增second_class這個類*/
if (IS_ERR(second_class))
{
printk(KERN_ERR "class_create() failed for second_class\n");
goto fail_class_create;
}
device_create(second_class,NULL,devno,NULL,DEVICE_NAME);/*建立裝置/dev/$DEVICE_NAME*/ printk("init second_drv success!!,major=%d!!\n",second_major);
return ;
fail_class_create:
cdev_del(&second_devp->cdev);/*登出cdev*/
kfree(second_devp);/*釋放裝置結構體記憶體*/
fail_kmalloc:
unregister_chrdev_region(devno,);/*釋放裝置號*/ return ret;
} /*裝置驅動模組解除安裝函式*/
static void __exit second_exit(void)
{
device_destroy(second_class,MKDEV(second_major,));/*登出裝置*/
class_destroy(second_class);/*登出類*/
cdev_del(&second_devp->cdev);/*登出cdev*/
kfree(second_devp);/*釋放裝置結構體記憶體*/
unregister_chrdev_region(MKDEV(second_major,),);/*釋放裝置號*/
} MODULE_AUTHOR("mhb@SEU");
MODULE_LICENSE("GPL"); module_init(second_init);
module_exit(second_exit);

測試程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h> main(int argc,char *argv[])
{
int fd;
int counter=;
int counter_old=; if ((fd=open("/dev/second_drv",O_RDONLY )) < )
{
printf("Open Device failed.\r\n");
exit();
}
else
while()
{
//printf("in the while(1)!\n");
read(fd,&counter,sizeof(unsigned int));
if(counter!=counter_old)
{
printf("seconds after open /dev/second_drv :%d\n",counter);
counter_old=counter;
}
} }