新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM的嵌入式Linux移植體驗(yàn)之設(shè)備驅(qū)動(dòng)

        ARM的嵌入式Linux移植體驗(yàn)之設(shè)備驅(qū)動(dòng)

        作者: 時(shí)間:2012-11-13 來(lái)源:網(wǎng)絡(luò) 收藏

        static struct block_device_operations mtd_fops =
        {
         owner: THIS_MODULE,
         open: mtdblock_open,
         release: mtdblock_release,
         ioctl: mtdblock_ioctl
        };

        static void mtd_notify_add(struct mtd_info* mtd)
        {
         …
        }

        static void mtd_notify_remove(struct mtd_info* mtd)
        {
         if (!mtd || mtd->type == MTD_ABSENT)
          return;

         devfs_unregister(devfs_rw_handle[mtd->index]);
        }

        int __init init_mtdblock(void)
        {
         int i;

         spin_lock_init(mtdblks_lock);
         /* this lock is used just in kernels >= 2.5.x */
         spin_lock_init(mtdblock_lock);

         #ifdef CONFIG_DEVFS_FS
         if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, mtd_fops))
         {
          printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",
        MTD_BLOCK_MAJOR);
          return -EAGAIN;
         }

         devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
         register_mtd_user(notifier);
         #else
          if (register_blkdev(MAJOR_NR,DEVICE_NAME,mtd_fops)) {
           printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",
        MTD_BLOCK_MAJOR);
          return -EAGAIN;
         }
         #endif

        /* We fill it in at open() time. */
        for (i=0; i MAX_MTD_DEVICES; i++) {
         mtd_sizes[i] = 0;
         mtd_blksizes[i] = BLOCK_SIZE;
        }
        init_waitqueue_head(thr_wq);
        /* Allow the block size to default to BLOCK_SIZE. */
        blksize_size[MAJOR_NR] = mtd_blksizes;
        blk_size[MAJOR_NR] = mtd_sizes;

        BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), mtdblock_request, mtdblock_lock);

        kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
        return 0;
        }

        static void __exit cleanup_mtdblock(void)
        {
         leaving = 1;
         wake_up(thr_wq);
         down(thread_sem);
         #ifdef CONFIG_DEVFS_FS
          unregister_mtd_user(notifier);
          devfs_unregister(devfs_dir_handle);
          devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME);
         #else
          unregister_blkdev(MAJOR_NR,DEVICE_NAME);
         #endif
         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
         blksize_size[MAJOR_NR] = NULL;
         blk_size[MAJOR_NR] = NULL;
        }

        module_init(init_mtdblock);
        module_exit(cleanup_mtdblock);

          從上述源代碼中我們發(fā)現(xiàn),塊設(shè)備也以與字符設(shè)備register_chrdev、unregister_ chrdev 函數(shù)類(lèi)似的方法進(jìn)行設(shè)備的注冊(cè)與釋放:

        int register_blkdev(unsigned int major, const char *name, struct block_device_operations *bdops);
        int unregister_blkdev(unsigned int major, const char *name);

          但是,register_chrdev使用一個(gè)向 file_operations 結(jié)構(gòu)的指針,而register_blkdev 則使用 block_device_operations 結(jié)構(gòu)的指針,其中定義的open、release 和 ioctl 方法和字符設(shè)備的對(duì)應(yīng)方法相同,但未定義 read 或者 write 操作。這是因?yàn)椋猩婕暗綁K設(shè)備的 I/O 通常由系統(tǒng)進(jìn)行緩沖處理。

          塊驅(qū)動(dòng)程序最終必須提供完成實(shí)際塊 I/O 操作的機(jī)制,在 Linux 當(dāng)中,用于這些 I/O 操作的方法稱(chēng)為"request(請(qǐng)求)"。在塊設(shè)備的注冊(cè)過(guò)程中,需要初始化request隊(duì)列,這一動(dòng)作通過(guò)blk_init_queue來(lái)完成,blk_init_queue函數(shù)建立隊(duì)列,并將該驅(qū)動(dòng)程序的 request 函數(shù)關(guān)聯(lián)到隊(duì)列。在模塊的清除階段,應(yīng)調(diào)用 blk_cleanup_queue 函數(shù)。

          本例中相關(guān)的代碼為:

        BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), mtdblock_request, mtdblock_lock);
        blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));

          每個(gè)設(shè)備有一個(gè)默認(rèn)使用的請(qǐng)求隊(duì)列,必要時(shí),可使用 BLK_DEFAULT_QUEUE(major) 宏得到該默認(rèn)隊(duì)列。這個(gè)宏在 blk_dev_struct 結(jié)構(gòu)形成的全局?jǐn)?shù)組(該數(shù)組名為 blk_dev)中搜索得到對(duì)應(yīng)的默認(rèn)隊(duì)列。blk_dev 數(shù)組由內(nèi)核維護(hù),并可通過(guò)主設(shè)備號(hào)索引。blk_dev_struct 接口定義如下:

        struct blk_dev_struct {
         /*
         * queue_proc has to be atomic
         */
         request_queue_t request_queue;
         queue_proc *queue;
         void *data;
        };

          request_queue 成員包含了初始化之后的 I/O 請(qǐng)求隊(duì)列,data 成員可由驅(qū)動(dòng)程序使用,以便保存一些私有數(shù)據(jù)。

          request_queue定義為:

        struct request_queue
        {
         /*
         * the queue request freelist, one for reads and one for writes
         */
         struct request_list rq[2];

         /*
         * Together with queue_head for cacheline sharing
         */
         struct list_head queue_head;
         elevator_t elevator;

         request_fn_proc * request_fn;
         merge_request_fn * back_merge_fn;
         merge_request_fn * front_merge_fn;
         merge_requests_fn * merge_requests_fn;
         make_request_fn * make_request_fn;
         plug_device_fn * plug_device_fn;
         /*
         * The queue owner gets to use this for whatever they like.
         * ll_rw_blk doesn't touch it.
         */
         void * queuedata;

         /*
         * This is used to remove the plug when tq_disk runs.
         */
         struct tq_struct plug_tq;

         /*
         * Boolean that indicates whether this queue is plugged or not.
         */
         char plugged;

         /*
         * Boolean that indicates whether current_request is active or
         * not.
         */
         char head_active;

         /*
         * Is meant to protect the queue in the future instead of
         * io_request_lock
         */
         spinlock_t queue_lock;

         /*
         * Tasks wait here for free request
         */
         wait_queue_head_t wait_for_request;
        };

          下圖表征了blk_dev、blk_dev_struct和request_queue的關(guān)系:

          下圖則表征了塊設(shè)備的注冊(cè)和釋放過(guò)程:

          5.小結(jié)

          本章講述了Linux設(shè)備驅(qū)動(dòng)程序的入口函數(shù)及驅(qū)動(dòng)程序中的內(nèi)存申請(qǐng)、中斷等,并分別以實(shí)例講述了字符設(shè)備及塊設(shè)備的驅(qū)動(dòng)開(kāi)發(fā)方法。

        linux操作系統(tǒng)文章專(zhuān)題:linux操作系統(tǒng)詳解(linux不再難懂)

        linux相關(guān)文章:linux教程



        上一頁(yè) 1 2 3 下一頁(yè)

        關(guān)鍵詞: ARM 嵌入式 Linux移植

        評(píng)論


        相關(guān)推薦

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

        關(guān)閉
        主站蜘蛛池模板: 临沭县| 陇川县| 阿荣旗| 伽师县| 凤冈县| 石泉县| 冀州市| 商南县| 通道| 苗栗县| 浦北县| 华阴市| 辉县市| 永靖县| 石河子市| 甘泉县| 县级市| 汉川市| 沾化县| 无锡市| 扶余县| 石嘴山市| 安宁市| 绩溪县| 洛川县| 南康市| 临桂县| 和龙市| 安宁市| 泰州市| 小金县| 沙河市| 莎车县| 阜新市| 湘潭市| 奉节县| 景宁| 临海市| 泗阳县| 仪征市| 洛宁县|