新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > linux驅動之內核定時器驅動設計

        linux驅動之內核定時器驅動設計

        作者: 時間:2016-12-01 來源:網絡 收藏
        驅動程序:
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        /*采用宏定義設置設備的主設備號*/
        #define SECOND_MAJOR 0
        /*靜態的分別保存靜態主設備號的變量*/
        static int second_major = SECOND_MAJOR;
        /*設備結構體,通常在設備中包含需要的設備,比如字符、塊等類型*/
        struct second_dev{
        /*添加設備類型,
        我認為可以采用一個聯合體,
        包含塊設備或者字符設備,類似inode的實現方法,
        這樣可以提高結構體的通用性
        */
        struct cdev cdev;
        /*原子變量,用來統計*/
        atomic_t counter;
        /*添加內核定時器結構體變量*/
        struct timer_list s_timer;
        /*用于動態創建設備文件的設備類*/
        struct class *myclass;
        };
        /*結構體指針或者采用全局變量直接定義結構都可以*/
        struct second_dev *second_devp;
        /*如果定時時間到了,定時器的處理函數*/
        static void second_timer_handler(unsigned long arg)
        {
        /*
        修改定時器中的到期時間,增加時間為1s,
        需要注意的是mod_timer函數是重新注冊定時器到內核
        而不管定時器是否被運行過
        */
        mod_timer(&second_devp->s_timer,jiffies + HZ);
        /*原子變量的增加*/
        atomic_inc(&second_devp->counter);
        /*輸出jiffies值*/
        printk(KERN_NOTICE "Current jiffies is %d",jiffies);
        }
        /*open函數實現*/
        static int second_open(struct inode *inode,struct file *filp)
        {
        /*初始化定義的內核定時器*/
        init_timer(&second_devp->s_timer);
        /*指定內核定時器的處理函數是上面定義好的函數*/
        second_devp->s_timer.function = second_timer_handler;
        /*指定定時間隔是1s*/
        second_devp->s_timer.expires = jiffies + HZ;
        /*將定時器添加到內核*/
        add_timer(&second_devp->s_timer);
        /*同時設備相關的統計值為0*/
        atomic_set(&second_devp->counter,0);
        return 0;
        }
        /*release函數的實現*/
        static int second_release(struct inode *inode,struct file *filp)
        {
        /*如果沒有到時間就關閉設備,直接刪除定時器*/
        del_timer(&second_devp->s_timer);
        return 0;
        }
        /*read函數的實現*/
        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);
        /*
        采用put_user實現數值的傳送
        put_user函數存在對指針變量的檢查,
        因此不需要檢測指針是否正確
        */
        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,
        };
        /*初始化函數*/
        static int __init 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_devp->myclass = class_create(THIS_MODULE,"second_timer_class");
        /*字符設備初始化,綁定相關操作到設備*/
        cdev_init(&second_devp->cdev,&second_fops);
        /*設備的擁有者*/
        second_devp->cdev.owner = THIS_MODULE,
        /*添加設備到內核*/
        ret = cdev_add(&second_devp->cdev,devno,1);
        /*錯誤處理*/
        if(ret)
        {
        printk(KERN_NOTICE "ERROR %d",ret);
        goto fail_malloc;
        }
        /*依據以前創建的設備類,創建設備*/
        device_create(second_devp->myclass,NULL,devno,NULL,"second%d",0);
        return 0;
        /*錯誤操作*/
        fail_malloc:
        unregister_chrdev_region(devno,1);
        return ret;
        }
        /*退出函數*/
        static void __exit second_exit(void)
        {
        /*釋放設備*/
        device_destroy(second_devp->myclass,MKDEV(second_major,0));
        /*刪除字符設備*/
        cdev_del(&second_devp->cdev);
        /*釋放設備類*/
        class_destroy(second_devp->myclass);
        /*釋放分配的內存空間大小*/
        kfree(second_devp);
        /*釋放設備號*/
        unregister_chrdev_region(MKDEV(second_major,0),1);
        }
        /*卸載和加載*/
        module_init(second_init);
        module_exit(second_exit);
        /*LICENSE和作者信息*/
        MODULE_LICENSE("GPL");
        MODULE_AUTHOR("GP-");
        應用程序:
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        int main()
        {
        int fd;
        int counter = 0;
        int old_counter = 0;
        fd = open("/dev/second0",O_RDONLY);
        if(fd != -1)
        {
        while(1)
        {
        read(fd,&counter,sizeof(unsigned int));
        if(counter != old_counter)
        {
        printf("second after open /dev/second0 : %d",counter);
        old_counter = counter;
        }
        }
        }
        else
        {
        printf("Device open failure");
        exit(1);
        }
        exit(0);
        }
        實驗效果:
        [root@EmbedSky Test]# ./app-timer
        Current jiffies is 2137721
        second after open /dev/second0 : 1
        Current jiffies is 2137921
        second after open /dev/second0 : 2
        Current jiffies is 2138121
        second after open /dev/second0 : 3
        Current jiffies is 2138321
        second after open /dev/second0 : 4
        Current jiffies is 2138521
        second after open /dev/second0 : 5
        Current jiffies is 2138721
        second after open /dev/second0 : 6
        以上的結果表明內核定時器基本實現了效果,但從實驗結果看好像為每兩秒實現一次顯示。具體的原因還有待于再次分析,因為arm中的HZ應該為100,而不是200。
        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 方城县| 洛宁县| 霸州市| 裕民县| 镇坪县| 无锡市| 鄯善县| 鹰潭市| 龙胜| 出国| 霍林郭勒市| 延安市| 天津市| 深泽县| 辛集市| 石泉县| 博罗县| 喜德县| 益阳市| 新干县| 杭州市| 巴林左旗| 慈溪市| 延安市| 仪征市| 石景山区| 夹江县| 乡宁县| 金乡县| 张北县| 郯城县| 镇安县| 通化市| 两当县| 乌兰浩特市| 宝兴县| 丹寨县| 曲麻莱县| 卢龙县| 曲沃县| 沙田区|