/*《Linux 設備驅動開發詳解》 http://www.linuxidc.com/Linux/2011-07/38211.htm
驅動程序
*/
- #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>
-
- #define SECOND_MAJOR 248 /*預設的second的主設備號*/
-
- static int second_major = SECOND_MAJOR;
-
- /*second設備結構體*/
- struct second_dev {
- struct cdev cdev; /*cdev結構體*/
- atomic_t counter;/* 一共經歷了多少秒?*/
- struct timer_list s_timer; /*設備要使用的定時器*/
- };
-
- struct second_dev *second_devp; /*設備結構體指針*/
-
- /*定時器處理函數*/
- static void second_timer_handle(unsigned long arg)
- {
- mod_timer(&second_devp->s_timer,jiffies + HZ);
- atomic_inc(&second_devp->counter);
-
- printk(KERN_NOTICE "current jiffies is %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); //計數清0
-
- return 0;
- }
- /*文件釋放函數*/
- int second_release(struct inode *inode, struct file *filp)
- {
- del_timer(&second_devp->s_timer);
-
- return 0;
- }
-
- /*讀函數*/
- 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 const struct file_operations second_fops = {
- .owner = THIS_MODULE,
- .open = second_open,
- .release = second_release,
- .read = second_read,
- };
-
- /*初始化並注冊cdev*/
- static void second_setup_cdev(struct second_dev *dev, int index)
- {
- int err, devno = MKDEV(second_major, index);
-
- cdev_init(&dev->cdev, &second_fops);
- dev->cdev.owner = THIS_MODULE;
- err = cdev_add(&dev->cdev, devno, 1);
- if (err)
- printk(KERN_NOTICE "Error %d adding LED%d", err, index);
- }
-
- /*設備驅動模塊加載函數*/
- 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_malloc;
- }
-
- memset(second_devp, 0, sizeof(struct second_dev));
-
- second_setup_cdev(second_devp, 0);
-
- return 0;
-
- fail_malloc:
- unregister_chrdev_region(devno, 1);
- return ret;
- }
-
- /*模塊卸載函數*/
- void second_exit(void)
- {
- cdev_del(&second_devp->cdev); /*注銷cdev*/
- kfree(second_devp); /*釋放設備結構體內存*/
- unregister_chrdev_region(MKDEV(second_major, 0), 1); /*釋放設備號*/
- }
-
- MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
- MODULE_LICENSE("Dual BSD/GPL");
-
- module_param(second_major, int, S_IRUGO);
-
- module_init(second_init);
- module_exit(second_exit);
/*應用程序*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <sys/stat.h>
-
- main()
- {
- int fd;
- int counter = 0;
- int old_counter = 0;
-
- /*打開/dev/second設備文件*/
- fd = open("/dev/second", O_RDONLY);
- if (fd != - 1) {
- while (1) {
- read(fd,&counter, sizeof(unsigned int));/* 讀目前經歷的秒數 */
- if(counter!=old_counter) {
- printf("seconds after open /dev/second :%d\n",counter);
- old_counter = counter;
- }
- }
- } else {
- printf("Device open failure\n");
- }
- }