在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > arm驅(qū)動(dòng)linux內(nèi)核時(shí)鐘

            arm驅(qū)動(dòng)linux內(nèi)核時(shí)鐘

            作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
            《[arm驅(qū)動(dòng)]linux內(nèi)核時(shí)鐘》涉及內(nèi)核驅(qū)動(dòng)函數(shù)四個(gè),內(nèi)核結(jié)構(gòu)體一個(gè),分析了內(nèi)核驅(qū)動(dòng)函數(shù)一個(gè);可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)模板一個(gè),可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)一個(gè)

            一、內(nèi)核定時(shí)器
            意義:內(nèi)核定時(shí)器是軟件意義上的定時(shí)器,最終依賴(lài)定時(shí)器來(lái)實(shí)現(xiàn)。時(shí)鐘中斷處理程序會(huì)喚起Timer_softirq軟中斷,運(yùn)行當(dāng)前處理器上到期的所有定時(shí)器。
            二、linux設(shè)備驅(qū)動(dòng)編程
            linux內(nèi)核提供一組函數(shù),時(shí)鐘數(shù)據(jù)結(jié)構(gòu);這組函數(shù)和數(shù)據(jù)結(jié)構(gòu)使驅(qū)動(dòng)工程師不用關(guān)心具體的軟件定時(shí)器究竟對(duì)應(yīng)著怎樣的內(nèi)核和硬件行為。
            三、數(shù)據(jù)結(jié)構(gòu)和函數(shù):
            1)數(shù)據(jù)結(jié)構(gòu)
            結(jié)構(gòu)體一)Linux在include/linux/timer.h頭文件中定義了數(shù)據(jù)結(jié)構(gòu)timer_list來(lái)描述一個(gè)內(nèi)核定時(shí)器:

            本文引用地址:http://www.biyoush.com/article/201611/318226.htm

            struct timer_list {
            struct list_head list; //定時(shí)器列表
            unsigned long expires; //定時(shí)器到期時(shí)間,單位HZ等效與秒
            void (*function)(unsigned long); //處理函數(shù)
            unsigned long data;//作為參數(shù)被輸入定時(shí)器處理函數(shù)
            .................
            };

            2)定時(shí)器定義及處理函數(shù)
            a)定義一個(gè)內(nèi)核定時(shí)器

            struct timer_list my_timer;

            內(nèi)核驅(qū)動(dòng)函數(shù)一)b)初始化定時(shí)器的timer_list的entry中的next指針為null

            void init_timer(struct *timer_list timer);

            內(nèi)核源碼一)init_timer內(nèi)核源碼

            void fastcall init_timer(struct timer_list *timer)
            {
            timer->entry.next = NULL;
            timer->base = __raw_get_cpu_var(tvec_bases);
            #ifdef CONFIG_TIMER_STATS
            timer->start_site = NULL;
            timer->start_pid = -1;
            memset(timer->start_comm, 0, TASK_COMM_LEN);
            #endif
            }

            內(nèi)核驅(qū)動(dòng)函數(shù)二)c)添加定時(shí)器

            void add_timer(struct timer_list *timer)

            內(nèi)核驅(qū)動(dòng)函數(shù)三)d)刪除定時(shí)器

            int del_timer(struct timer_list * timer)

            內(nèi)核驅(qū)動(dòng)函數(shù)四)e)修改定時(shí)器的expire

            int mod_timer(struct timer_list *timer, unsigned long expires)

            模板一)四、內(nèi)核定時(shí)器使用模板(結(jié)合虛擬內(nèi)存)

            a)結(jié)構(gòu)體定義

            #define TIMERDELAY 2
            struct VirtualDisk{
            struct cdev cdev;//詳細(xì)看cdev機(jī)制
            timer_list my_timer;//設(shè)備要用的定時(shí)器
            };

            b)結(jié)構(gòu)體賦值,添加時(shí)鐘,時(shí)鐘要處理的函數(shù)

            /***********時(shí)鐘函數(shù),只需調(diào)用initMytimer************/
            //完成工作后,往往會(huì)延后expires并將定時(shí)器再次添加到內(nèi)核定時(shí)器鏈表,以便定時(shí)器能再次被觸發(fā)
            static void domytimer(unsigned long arg){//just used by initMytimer function
            struct VirtualDisk* myVirtualDiskp = (struct VirtualDisk *)(arg);//很重要
            //..........加上你還要做的代碼............
            printk("arg is %ldn", myVirtualDiskp->mytimer.expires);//打印現(xiàn)在的expires
            myVirtualDiskp->mytimer.expires = jiffies + (TIMERDELAY*HZ);//"HZ"等效與"秒"
            add_timer(&myVirtualDiskp->mytimer);
            //.......................
            }
            static void initMytimer(struct VirtualDisk *myVirtualDiskp, int delay){
            init_timer(&myVirtualDiskp->mytimer);
            myVirtualDiskp->mytimer.data = (unsigned long) myVirtualDiskp;
            myVirtualDiskp->mytimer.function = &domytimer;
            myVirtualDiskp->mytimer.expires = jiffies + (delay*HZ);
            add_timer(&myVirtualDiskp->mytimer);
            }
            /***********************/

            c)exit()或其他釋放函數(shù)中刪除時(shí)鐘

            if(VirtualDiskp)del_timer(&VirtualDiskp->mytimer);

            實(shí)例一)五、完整代碼

            //“timerlist_drv”,"timerlist_"
            #include //模塊所需的大量符號(hào)和函數(shù)定義
            #include
            #include //文件系統(tǒng)相關(guān)的函數(shù)和頭文件
            #include //指定初始化和清除函數(shù)
            #include
            #include //cdev結(jié)構(gòu)的頭文件包含
            #include
            #include
            //#include //包含驅(qū)動(dòng)程序使用的大部分內(nèi)核API的定義,包括睡眠函數(shù)以及各種變量聲明
            #include //在內(nèi)核和用戶(hù)空間中移動(dòng)數(shù)據(jù)的函數(shù)
            #include
            #include
            #include
            #include
            #include /*timer*/
            #include /*jiffies*/
            #define VIRTUALDISK_SIZE 0x1000//4k
            #define MEM_CLEAR 0x1
            #define VIRTUALDISK_MAJOR 250
            /******timer *******/
            #define TIMERDELAY 2
            int VirtualDisk_major = VIRTUALDISK_MAJOR;
            struct VirtualDisk{
            struct cdev cdev;//詳細(xì)看cdev機(jī)制
            unsigned char mem[VIRTUALDISK_SIZE ];
            long count; /*記錄設(shè)備目前被多少設(shè)備打開(kāi)*/
            struct timer_list mytimer;
            };
            static struct class *timerlist_class;
            static struct class_device *timerlist_class_dev;
            struct VirtualDisk *VirtualDiskp;
            /*********timer opration*************/
            static void domytimer(unsigned long arg){//just used by follow function
            struct VirtualDisk* myVirtualDiskp = (struct VirtualDisk *)(arg);
            printk("arg is %ldn", myVirtualDiskp->mytimer.expires);
            myVirtualDiskp->mytimer.expires = jiffies + (TIMERDELAY*HZ);
            add_timer(&myVirtualDiskp->mytimer);
            }
            static void initMytimer(struct VirtualDisk *myVirtualDiskp, int delay){
            init_timer(&myVirtualDiskp->mytimer);
            myVirtualDiskp->mytimer.data = (unsigned long) myVirtualDiskp;
            myVirtualDiskp->mytimer.function = &domytimer;
            myVirtualDiskp->mytimer.expires = jiffies + (delay*HZ);
            add_timer(&myVirtualDiskp->mytimer);
            }
            /*********timer opration over*************/
            static int timerlist_drv_open(struct inode *inode, struct file *file)
            {
            printk("timerlist_dev readn");
            file->private_data = VirtualDiskp;
            VirtualDiskp->count++; /*增加設(shè)備打開(kāi)次數(shù)*/
            return 0;
            }
            static int timerlist_drv_release(struct inode *inode, struct file *file)
            {
            printk("timerlist_dev releasen");
            VirtualDiskp->count--; /*減少設(shè)備打開(kāi)次數(shù)*/
            return 0;
            }
            /*seek文件定位函數(shù):seek()函數(shù)對(duì)文件定位的起始地址可以是文件開(kāi)頭(SEEK_SET,0)、當(dāng)前位置(SEEK_CUR,1)、文件尾(SEEK_END,2)*/
            static loff_t timerlist_drv_llseek(struct file *file, loff_t offset, int origin){
            loff_t ret = 0;/*返回的位置偏移*/
            switch (origin)
            {
            case SEEK_SET: /*相對(duì)文件開(kāi)始位置偏移*/
            if (offset < 0)/*offset不合法*/
            {
            ret = - EINVAL; /*無(wú)效的指針*/
            break;
            }
            if ((unsigned int)offset > VIRTUALDISK_SIZE)/*偏移大于設(shè)備內(nèi)存*/
            {
            ret = - EINVAL; /*無(wú)效的指針*/
            break;
            }
            file->f_pos = (unsigned int)offset; /*更新文件指針位置*/
            ret = file->f_pos;/*返回的位置偏移*/
            break;
            case SEEK_CUR: /*相對(duì)文件當(dāng)前位置偏移*/
            if ((file->f_pos + offset) > VIRTUALDISK_SIZE)/*偏移大于設(shè)備內(nèi)存*/
            {
            ret = - EINVAL;/*無(wú)效的指針*/
            break;
            }
            if ((file->f_pos + offset) < 0)/*指針不合法*/
            {
            ret = - EINVAL;/*無(wú)效的指針*/
            break;
            }
            file->f_pos += offset;/*更新文件指針位置*/
            ret = file->f_pos;/*返回的位置偏移*/
            break;
            default:
            ret = - EINVAL;/*無(wú)效的指針*/
            break;
            }
            return ret;
            }
            /*設(shè)備控制函數(shù):ioctl()函數(shù)接受的MEM_CLEAR命令,這個(gè)命令將全局內(nèi)存的有效數(shù)據(jù)長(zhǎng)度清零,對(duì)于設(shè)備不支持的命令,ioctl()函數(shù)應(yīng)該返回-EINVAL*/
            static int timerlist_drv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
            struct VirtualDisk *devp = file->private_data;/*獲得設(shè)備結(jié)構(gòu)體指針*/
            switch (cmd)
            {
            case MEM_CLEAR:/*設(shè)備內(nèi)存清零*/
            memset(devp->mem, 0, VIRTUALDISK_SIZE);
            printk(KERN_INFO "VirtualDisk is set to zeron");
            break;
            default:
            return - EINVAL;
            }
            return 0;
            }
            /*讀函數(shù):讀寫(xiě)函數(shù)主要是讓設(shè)備結(jié)構(gòu)體的mem[]數(shù)組與用戶(hù)空間交互數(shù)據(jù),并隨著訪(fǎng)問(wèn)字節(jié)數(shù)變更返回用戶(hù)的文件讀寫(xiě)偏移位置*/
            static ssize_t timerlist_drv_read(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
            {
            printk("timerlist_dev readn");
            unsigned long p = *ppos; /*記錄文件指針偏移位置*/
            unsigned int countt = count;/*記錄需要讀取的字節(jié)數(shù)*/
            int ret = 0; /*返回值*/
            struct VirtualDisk *devp = file->private_data; /*獲得設(shè)備結(jié)構(gòu)體指針*/
            /*分析和獲取有效的讀長(zhǎng)度*/
            if (p >= VIRTUALDISK_SIZE ) /*要讀取的偏移大于設(shè)備的內(nèi)存空間*/
            return countt ? - ENXIO: 0;/*讀取地址錯(cuò)誤*/
            if (countt > VIRTUALDISK_SIZE - p)/*要讀取的字節(jié)大于設(shè)備的內(nèi)存空間*/
            countt = VIRTUALDISK_SIZE - p;/*將要讀取的字節(jié)數(shù)設(shè)為剩余的字節(jié)數(shù)*/
            /*內(nèi)核空間->用戶(hù)空間交換數(shù)據(jù)*/
            if (copy_to_user(buf, (void*)(devp->mem + p), countt))
            {
            ret = - EFAULT;
            }
            else
            {
            *ppos += countt;
            ret = countt;
            printk("read %d bytes(s) is %ldn", countt, p);
            }
            printk("bytes(s) is %sn", buf);
            initMytimer(devp, 2);
            return ret;
            }
            /*
            file 是文件指針,count 是請(qǐng)求的傳輸數(shù)據(jù)長(zhǎng)度,buff 參數(shù)是指向用戶(hù)空間的緩沖區(qū),這個(gè)緩沖區(qū)或者保存要寫(xiě)入的數(shù)據(jù),或者是一個(gè)存放新讀入數(shù)據(jù)的空緩沖區(qū),該地址在內(nèi)核空間不能直接讀寫(xiě),ppos 是一個(gè)指針指向一個(gè)"long offset type"對(duì)象, 它指出用戶(hù)正在存取的文件位置. 返回值是一個(gè)"signed size type。寫(xiě)的位置相對(duì)于文件開(kāi)頭的偏移。
            */
            static ssize_t timerlist_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
            {
            printk("timerlist_dev writen");
            unsigned long p = *ppos; /*記錄文件指針偏移位置*/
            int ret = 0; /*返回值*/
            unsigned int countt = count;/*記錄需要寫(xiě)入的字節(jié)數(shù)*/
            struct VirtualDisk *devp = file->private_data; /*獲得設(shè)備結(jié)構(gòu)體指針*/
            /*分析和獲取有效的寫(xiě)長(zhǎng)度*/
            if (p >= VIRTUALDISK_SIZE )/*要寫(xiě)入的偏移大于設(shè)備的內(nèi)存空間*/
            return countt ? - ENXIO: 0;/*寫(xiě)入地址錯(cuò)誤*/
            if (countt > VIRTUALDISK_SIZE - p)/*要寫(xiě)入的字節(jié)大于設(shè)備的內(nèi)存空間*/
            countt = VIRTUALDISK_SIZE - p;/*將要寫(xiě)入的字節(jié)數(shù)設(shè)為剩余的字節(jié)數(shù)*/
            /*用戶(hù)空間->內(nèi)核空間*/
            if (copy_from_user(devp->mem + p, buf, countt))
            ret = - EFAULT;
            else
            {
            *ppos += countt;/*增加偏移位置*/
            ret = countt;/*返回實(shí)際的寫(xiě)入字節(jié)數(shù)*/
            printk("written %d bytes(s) from%ldn", countt, p);
            }
            return ret;
            return 0;
            }
            static struct file_operations timerlist_drv_fops = {
            .owner = THIS_MODULE, /* 這是一個(gè)宏,推向編譯模塊時(shí)自動(dòng)創(chuàng)建的__this_module變量 */
            .read = timerlist_drv_read,
            .write = timerlist_drv_write,
            .open = timerlist_drv_open,
            .release = timerlist_drv_release,
            .llseek = timerlist_drv_llseek,
            .ioctl = timerlist_drv_ioctl,
            };
            /*將 cdev 結(jié)構(gòu)嵌入一個(gè)你自己的設(shè)備特定的結(jié)構(gòu),你應(yīng)當(dāng)初始化你已經(jīng)分配的結(jié)構(gòu)使用以上函數(shù),有一個(gè)其他的 struct cdev 成員你需要初始化. 象 file_operations 結(jié)構(gòu),struct cdev 有一個(gè)擁有者成員,應(yīng)當(dāng)設(shè)置為 THIS_MODULE,一旦 cdev 結(jié)構(gòu)建立, 最后的步驟是把它告訴內(nèi)核, 調(diào)用:
            cdev_add(&dev->cdev, devno, 1);*/
            static void VirtualDisk_setup_cdev(struct VirtualDisk *dev, int minorIndex){
            int err;
            int devno = MKDEV(VirtualDisk_major, minorIndex);
            cdev_init(&dev->cdev, &timerlist_drv_fops);
            dev->cdev.owner = THIS_MODULE;
            err = cdev_add(&dev->cdev, devno, 1);
            if(err){
            printk("error %d cdev file addedn", err);
            }
            }
            static int timerlist_drv_init(void)
            {
            int result;
            dev_t devno = MKDEV(VirtualDisk_major, 0);
            if(VirtualDisk_major){
            result = register_chrdev_region(devno, 1, "timerlist_dev");
            }else{
            result = alloc_chrdev_region(&devno, 0, 1, "timerlist_dev");
            VirtualDisk_major = MAJOR(devno);
            }
            if(result < 0 ){
            return result;
            }
            VirtualDiskp = kmalloc(sizeof(struct VirtualDisk), GFP_KERNEL);
            if(!VirtualDiskp){
            result = -ENOMEM;
            goto fail_malloc;
            }
            memset(VirtualDiskp, 0, sizeof(struct VirtualDisk));
            VirtualDisk_setup_cdev(VirtualDiskp, 0);
            timerlist_class = class_create(THIS_MODULE, "timerlist_drv");
            if (IS_ERR(timerlist_class))
            return PTR_ERR(timerlist_class);
            timerlist_class_dev = class_device_create(timerlist_class, NULL, MKDEV(VirtualDisk_major, 0), NULL, "timerlist_dev"); /* /dev/xyz */
            if (IS_ERR(timerlist_class_dev))
            return PTR_ERR(timerlist_class_dev);
            return 0;
            fail_malloc:
            unregister_chrdev_region(devno, 1);
            return result;
            }
            static void timerlist_drv_exit(void)
            {
            if(VirtualDiskp)del_timer(&VirtualDiskp->mytimer);
            cdev_del(&VirtualDiskp->cdev);
            kfree(VirtualDiskp);
            unregister_chrdev_region(MKDEV(VirtualDisk_major, 0), 1);
            class_device_unregister(timerlist_class_dev);
            class_destroy(timerlist_class);
            }
            module_init(timerlist_drv_init);
            module_exit(timerlist_drv_exit);
            MODULE_LICENSE("GPL");



            評(píng)論


            技術(shù)專(zhuān)區(qū)

            關(guān)閉